Skip to content

Commit

Permalink
Merge pull request #7578 from GCTC-NTGC/5347-remove-roles-salaries
Browse files Browse the repository at this point in the history
[Debt] Removes `expectedClassifications`, `expectedSalary`, `expectedGenericJobTitle`
  • Loading branch information
mnigh authored Aug 14, 2023
2 parents b88c7e1 + e6eb1a8 commit 8c6bb77
Show file tree
Hide file tree
Showing 50 changed files with 79 additions and 1,555 deletions.
18 changes: 0 additions & 18 deletions api/app/GraphQL/Mutations/PoolCandidateSnapshot.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,6 @@ query getProfile($userId: UUID!) {
fr
}
}
expectedGenericJobTitles {
id
key
name {
en
fr
}
}
isWoman
hasDisability
isIndigenous
Expand All @@ -63,16 +55,6 @@ query getProfile($userId: UUID!) {
locationPreferences
locationExemptions
acceptedOperationalRequirements
expectedSalary
expectedClassifications {
id
name {
en
fr
}
group
level
}
positionDuration
userSkills {
id
Expand Down
5 changes: 0 additions & 5 deletions api/app/GraphQL/Queries/CountPoolCandidatesByPool.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,6 @@ public function __invoke($_, array $args)
User::scopePositionDuration($userQuery, $filters['positionDuration']);
}

// expectedClassifications
if (array_key_exists('expectedClassifications', $filters)) {
User::scopeExpectedClassifications($userQuery, $filters['expectedClassifications']);
}

// skills
if (array_key_exists('skills', $filters)) {
User::scopeSkillsAdditive($userQuery, $filters['skills']);
Expand Down
3 changes: 0 additions & 3 deletions api/app/Http/Resources/UserResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ public function toArray($request)
'govEmployeeType' => $this->gov_employee_type,
'department' => $this->department ? (new DepartmentResource(Department::find($this->department))) : null,
'currentClassification' => (new ClassificationResource($this->currentClassification)),
'expectedClassifications' => ClassificationResource::collection($this->expectedClassifications),
'expectedGenericJobTitles' => GenericJobTitleResource::collection($this->expectedGenericJobTitles),
'isWoman' => $this->is_woman,
'hasDisability' => $this->has_disability,
'isIndigenous' => $this->is_indigenous,
Expand All @@ -92,7 +90,6 @@ public function toArray($request)
'locationPreferences' => $this->location_preferences,
'locationExemptions' => $this->location_exemptions,
'acceptedOperationalRequirements' => $this->accepted_operational_requirements,
'expectedSalary' => $this->expected_salary,
'positionDuration' => $this->position_duration,
'poolCandidates' => PoolCandidateResource::collection($this->poolCandidates),
'experiences' => $collection,
Expand Down
2 changes: 0 additions & 2 deletions api/app/Listeners/StoreApplicationSnapshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public function handle(ApplicationSubmitted $event)
$user = User::with([
'department',
'currentClassification',
'expectedClassifications',
'expectedGenericJobTitles',
'userSkills.skill',
'awardExperiences',
'awardExperiences.skills',
Expand Down
26 changes: 0 additions & 26 deletions api/app/Models/PoolCandidate.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,30 +214,6 @@ public static function scopeQualifiedClassifications(Builder $query, ?array $cla
return $query;
}

/**
* scopeExpectedClassifications
*
* Scopes the query to only include applicants who have expressed interest in any of $classifications.
*
* @param Builder $query
* @param array|null $classifications
* @return Builder
*/
public function scopeExpectedClassifications(Builder $query, ?array $classifications): Builder
{
// if no filters provided then return query unchanged
if (empty($classifications)) {
return $query;
}

// pointing to the classification scope on the User model
// that scope also contains filterByClassificationToSalary and filterByClassificationToGenericJobTitles
$query->whereHas('user', function ($query) use ($classifications) {
User::scopeExpectedClassifications($query, $classifications);
});
return $query;
}

/**
* Scope Publishing Groups
*
Expand Down Expand Up @@ -502,8 +478,6 @@ public function createSnapshot()
$user = User::with([
'department',
'currentClassification',
'expectedClassifications',
'expectedGenericJobTitles',
'awardExperiences',
'awardExperiences.skills',
'communityExperiences',
Expand Down
1 change: 0 additions & 1 deletion api/app/Models/PoolCandidateFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
* @property boolean $is_woman
* @property string $language_ability
* @property array $work_regions
* @property array $expected_salary
* @property array $operational_requirements
* @property Illuminate\Support\Carbon $created_at
* @property Illuminate\Support\Carbon $updated_at
Expand Down
155 changes: 0 additions & 155 deletions api/app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
* @property boolean $has_diploma
* @property array $location_preferences
* @property string $location_exemptions
* @property array $expected_salary
* @property array $position_duration
* @property array $accepted_operational_requirements
* @property string $gov_employee_type
Expand Down Expand Up @@ -81,7 +80,6 @@ class User extends Model implements Authenticatable, LaratrustUser

protected $casts = [
'location_preferences' => 'array',
'expected_salary' => 'array',
'accepted_operational_requirements' => 'array',
'position_duration' => 'array',
'indigenous_communities' => 'array',
Expand All @@ -108,14 +106,6 @@ public function currentClassification(): BelongsTo
{
return $this->belongsTo(Classification::class, "current_classification");
}
public function expectedClassifications(): BelongsToMany
{
return $this->belongsToMany(Classification::class, 'classification_user')->withTimestamps();
}
public function expectedGenericJobTitles(): BelongsToMany
{
return $this->belongsToMany(GenericJobTitle::class, 'generic_job_title_user')->withTimestamps();
}
/**
* @deprecated
*/
Expand Down Expand Up @@ -247,7 +237,6 @@ public static function scopeIsProfileComplete(Builder $query, ?bool $isProfileCo
$query->whereNotNull('location_preferences');
$query->whereJsonLength('location_preferences', '>', 0);
$query->whereJsonLength('position_duration', '>', 0);
$query->has('expectedGenericJobTitles');
$query->whereNotNull('citizenship');
$query->whereNotNull('armed_forces_status');
}
Expand Down Expand Up @@ -471,52 +460,6 @@ public static function scopeQualifiedStreams(Builder $query, ?array $streams): B
return $query;
}

/**
* scopeExpectedClassifications
*
* Scopes the query to only return applicants who have expressed interest in any of $classifications.
* Applicants have been able to record this interest in various ways, so this scope may consider three fields on
* the user: expectedClassifications, expectedSalary, and expectedGenericJobTitles.
*
* @param Builder $query
* @param array|null $classifications Each classification is an object with a group and a level field.
* @return Builder
*/
public static function scopeExpectedClassifications(Builder $query, ?array $classifications): Builder
{
// if no filters provided then return query unchanged
if (empty($classifications)) {
return $query;
}

// Classifications act as an OR filter. The query should return candidates with any of the classifications.
// A single whereHas clause for the relationship, containing multiple orWhere clauses accomplishes this.
$query->where(function ($query) use ($classifications) {
$query->whereHas('expectedClassifications', function ($query) use ($classifications) {
foreach ($classifications as $index => $classification) {
if ($index === 0) {
// First iteration must use where instead of orWhere
$query->where(function ($query) use ($classification) {
$query->where('group', $classification['group'])->where('level', $classification['level']);
});
} else {
$query->orWhere(function ($query) use ($classification) {
$query->where('group', $classification['group'])->where('level', $classification['level']);
});
}
}
});
$query->orWhere(function ($query) use ($classifications) {
self::filterByClassificationToSalary($query, $classifications);
});
$query->orWhere(function ($query) use ($classifications) {
self::filterByClassificationToGenericJobTitles($query, $classifications);
});
});

return $query;
}

/**
* Scope Publishing Groups
*
Expand Down Expand Up @@ -556,104 +499,6 @@ public static function scopeInITPublishingGroup(Builder $query)
return $query;
}

public static function filterByClassificationToGenericJobTitles(Builder $query, ?array $classifications): Builder
{
// if no filters provided then return query unchanged
if (empty($classifications)) {
return $query;
}
// Classifications act as an OR filter. The query should return candidates with any of the classifications.
// A single whereHas clause for the relationship, containing multiple orWhere clauses accomplishes this.

// group these in a subquery to properly handle "OR" condition
$query->whereHas('expectedGenericJobTitles', function ($query) use ($classifications) {
$query->whereHas('classification', function ($query) use ($classifications) {
foreach ($classifications as $index => $classification) {
if ($index === 0) {
// First iteration must use where instead of orWhere
$query->where(function ($query) use ($classification) {
$query->where('group', $classification['group'])->where('level', $classification['level']);
});
} else {
$query->orWhere(function ($query) use ($classification) {
$query->where('group', $classification['group'])->where('level', $classification['level']);
});
}
}
});
});

return $query;
}
private static function filterByClassificationToSalary(Builder $query, ?array $classifications): Builder
{
// When managers search for a classification, also return any users whose expected salary
// ranges overlap with the min/max salaries of any of those classifications.
// Since salary ranges are text enums a custom SQL subquery is used to convert them to
// numeric values and compare them to specified classifications

// This subquery only works for a non-zero number of filter classifications.
// If passed zero classifications then return same query builder unchanged.
if (empty($classifications)) {
return $query;
}

$parameters = [];
$sql = <<<RAWSQL1
SELECT NULL -- find all candidates where a salary/group combination matches a classification filter
FROM (
SELECT -- convert salary ranges to numeric min/max values
t.user_id,
CASE t.salary_range_id
WHEN '_50_59K' THEN 50000
WHEN '_60_69K' THEN 60000
WHEN '_70_79K' THEN 70000
WHEN '_80_89K' THEN 80000
WHEN '_90_99K' THEN 90000
WHEN '_100K_PLUS' THEN 100000
END min_salary,
CASE t.salary_range_id
WHEN '_50_59K' THEN 59999
WHEN '_60_69K' THEN 69999
WHEN '_70_79K' THEN 79999
WHEN '_80_89K' THEN 89999
WHEN '_90_99K' THEN 99999
WHEN '_100K_PLUS' THEN 2147483647
END max_salary
FROM (
SELECT -- find all salary ranges for each candidate
users.id user_id,
JSONB_ARRAY_ELEMENTS_TEXT(users.expected_salary) salary_range_id
FROM users
) t
) u
JOIN classifications c ON
c.max_salary >= u.min_salary
AND c.min_salary <= u.max_salary
WHERE (
RAWSQL1;

foreach ($classifications as $index => $classification) {
if ($index === 0) {
// First iteration must use where instead of orWhere
$sql .= '(c.group = ? AND c.level = ?)';
} else {
$sql .= ' OR (c.group = ? AND c.level = ?)';
}
array_push($parameters, [$classification['group'], $classification['level']]);
}

$sql .= <<<RAWSQL2
)
AND u.user_id = "users".id
RAWSQL2;

return $query->whereRaw('EXISTS (' . $sql . ')', $parameters);
}

public static function scopeHasDiploma(Builder $query, ?bool $hasDiploma): Builder
{
if ($hasDiploma) {
Expand Down
Loading

0 comments on commit 8c6bb77

Please sign in to comment.