Skip to content

Commit 5207746

Browse files
Quick emergency fix for 0FTE check
1 parent 83ad8b6 commit 5207746

File tree

6 files changed

+252
-13
lines changed

6 files changed

+252
-13
lines changed

config/ucpath_fields.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,8 @@ job:
205205
jpath: "$.position.percentOfFullTime"
206206
dbdef: "VARCHAR(16)"
207207
status: OPTIONAL
208+
209+
- name: percent_of_fulltime_job
210+
jpath: "$.percentOfFullTime"
211+
dbdef: "VARCHAR(16)"
212+
status: OPTIONAL

lib/ucpath/jobs.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,13 @@ def valid_org_relationship?(j)
105105
end
106106

107107
# 4. The job will be ineligible if the percentage of full time is zero
108+
# Note - percentage of full time can appear in 2 different places (ugh)
108109
def positive_full_time?(j)
109-
j.percent_of_fulltime.to_f.positive?
110+
values = []
111+
values << j.percent_of_fulltime if j.respond_to?(:percent_of_fulltime)
112+
values << j.percent_of_fulltime_job if j.respond_to?(:percent_of_fulltime_job)
113+
114+
values.any? { |v| v.to_f.positive? }
110115
end
111116

112117
def find_priority_jobs(job_list)

lib/ucpath/user.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,13 @@ def create_user_record
144144
job_code = jobs.job.job_code || nil
145145
priority_job = Config.check_ucpath_code('priority_job_codes', job_code)
146146
percent_of_fulltime = jobs.job.percent_of_fulltime.to_f
147+
percent_of_fulltime_job = jobs.job.percent_of_fulltime_job.to_f
147148

148149
# PERCENT OF FULL TIME CHECK
149150
# AP-559 If an employee is in a position that is 0 FTE,
150151
# their record should should be filtered out from the UCPath files.
151-
if percent_of_fulltime.zero?
152-
logger.info "#{id} - Ineligible: Percentage of Full Time Check: #{percent_of_fulltime}"
152+
if percent_of_fulltime.zero? && percent_of_fulltime_job.zero?
153+
logger.info "#{id} - Ineligible: Percentage of Full Time Check"
153154
return nil
154155
end
155156

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
{
2+
"source": "UCB-HR-PATH-DB",
3+
"correlationId": "8c37994b-3132-4f04-98b0-5ecdc96aec79",
4+
"timeStamp": "2026-02-03",
5+
"httpStatus": {
6+
"code": "200",
7+
"description": "OK"
8+
},
9+
"response": [
10+
{
11+
"identifiers": [
12+
{
13+
"type": "hr-employee-id",
14+
"id": "10725310"
15+
},
16+
{
17+
"type": "campus-uid",
18+
"id": "10725310"
19+
}
20+
],
21+
"jobs": [
22+
{
23+
"number": 0,
24+
"sequence": 0,
25+
"type": {
26+
"code": "4",
27+
"description": "Staff: Limited"
28+
},
29+
"classification": {
30+
"code": "1",
31+
"description": "Professional & Support Staff"
32+
},
33+
"position": {
34+
"number": "41195443",
35+
"department": {
36+
"code": "KPADM",
37+
"description": "Library Administration"
38+
},
39+
"description": "LIBRARY AST 2",
40+
"pool": {
41+
},
42+
"percentOfFullTime": 0.000000,
43+
"employeeRelationship": {
44+
"code": "E",
45+
"description": "All Others, Not Confidential"
46+
},
47+
"jobCode": {
48+
"code": {
49+
"code": "006760",
50+
"description": "LIBRARY AST 2"
51+
},
52+
"status": {
53+
"code": "A",
54+
"description": "Active"
55+
},
56+
"family": {
57+
"code": "J092",
58+
"description": "Library Services"
59+
},
60+
"function": {
61+
"code": "442",
62+
"description": "Library"
63+
},
64+
"flsaEligibilty": {
65+
},
66+
"representation": {
67+
"union": {
68+
"code": "CX",
69+
"description": "Clerical & Allied Services"
70+
}
71+
}
72+
},
73+
"reportsTo": {
74+
"position": {
75+
"number": "40145569"
76+
}
77+
},
78+
"status": {
79+
"code": "A",
80+
"description": "Approved"
81+
},
82+
"headCount": {
83+
"active": 1,
84+
"maximum": 1,
85+
"status": {
86+
"code": "F",
87+
"description": "Filled"
88+
}
89+
},
90+
"active": {
91+
"code": "A",
92+
"description": "Active"
93+
},
94+
"fromDate": "2025-08-22"
95+
},
96+
"organizationRelationship": {
97+
"code": "EMP",
98+
"description": "Employee"
99+
},
100+
"flsaEligibilty": {
101+
"code": "N",
102+
"description": "Nonexempt"
103+
},
104+
"percentOfFullTime": 0.000000,
105+
"fullTimeStatus": {
106+
"code": "X",
107+
"description": "Fixed"
108+
},
109+
"permanent": {
110+
"code": "R",
111+
"description": "Not Applicable"
112+
},
113+
"primary": {
114+
"code": "P",
115+
"description": "Primary Job"
116+
},
117+
"department": {
118+
"code": "KPADM",
119+
"description": "Library Administration"
120+
},
121+
"location": {
122+
"code": "10467",
123+
"description": "Bancroft Lib (Doe Anx)-F03-94704"
124+
},
125+
"status": {
126+
"hrStatus": {
127+
"code": "A",
128+
"description": "Active"
129+
},
130+
"employmentStatus": {
131+
"code": "A",
132+
"description": "Active"
133+
},
134+
"benefitsStatus": {
135+
"code": "A",
136+
"description": "Active"
137+
}
138+
},
139+
"fromDate": "2025-10-28"
140+
}
141+
]
142+
}
143+
]
144+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"source": "UCB-HR-PATH-DB",
3+
"correlationId": "23d9a1b2-7f7a-4693-8a88-051a7d3c5caa",
4+
"timeStamp": "2026-02-18",
5+
"httpStatus": {
6+
"code": "200",
7+
"description": "OK"
8+
},
9+
"response": [
10+
{
11+
"identifiers": [
12+
{
13+
"type": "hr-employee-id",
14+
"id": "10725310"
15+
},
16+
{
17+
"type": "campus-uid",
18+
"id": "1926706"
19+
},
20+
{
21+
"type": "calnet-id",
22+
"id": "hptruong"
23+
},
24+
{
25+
"type": "campus-solutions-id",
26+
"id": "3040792017"
27+
}
28+
],
29+
"names": [
30+
{
31+
"type": {
32+
"code": "PRF",
33+
"description": "Preferred"
34+
},
35+
"familyName": "Familyname",
36+
"givenName": "Givenname",
37+
"fromDate": "2024-03-26"
38+
},
39+
{
40+
"type": {
41+
"code": "PRI",
42+
"description": "Primary"
43+
},
44+
"familyName": "Familyname",
45+
"givenName": "Givenname",
46+
"fromDate": "2024-03-26"
47+
}
48+
]
49+
}
50+
]
51+
}

spec/lib/ucpath_spec.rb

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,15 @@
586586
u = UCPath::User.new(id)
587587
expect(u.eligible?).to be(false)
588588
end
589+
590+
it 'skips with zero Percentage of FullTime' do
591+
id = '10725310'
592+
stub_ucpath_user(id)
593+
stub_ucpath_jobs(id)
594+
595+
u = UCPath::User.new(id)
596+
expect(u.eligible?).to be(false)
597+
end
589598
end
590599

591600
describe UCPath::Jobs do
@@ -603,7 +612,7 @@ def eligible(job)
603612
# Minimal structs to stand in for your “job” objects
604613
let(:choose_job_struct) { Struct.new(:expected_end_date) }
605614
let(:eligible_job_struct) do
606-
Struct.new(:hr_status_code, :expected_end_date, :org_relationship_code, :job_code, :percent_of_fulltime)
615+
Struct.new(:hr_status_code, :expected_end_date, :org_relationship_code, :job_code, :percent_of_fulltime, :percent_of_fulltime_job)
607616
end
608617

609618
describe '#choose_job' do
@@ -651,56 +660,80 @@ def eligible(job)
651660
allow(Date).to receive(:today).and_return(today)
652661
end
653662

663+
# context 'when position percentOfFullTime (in both position and job) is zero' do
664+
# let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 0.0, 0.0) }
665+
666+
# it 'returns false' do
667+
# expect(eligible(job)).to be(false)
668+
# end
669+
# end
670+
671+
# context 'when position percentOfFullTime is zero in position but not zero in job' do
672+
# let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 0.0, 0.1) }
673+
674+
# it 'returns true' do
675+
# expect(eligible(job)).to be(true)
676+
# end
677+
# end
678+
679+
# context 'when position percentOfFullTime is zero in job but not position' do
680+
# let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 0.5, 0.0) }
681+
682+
# it 'returns true' do
683+
# expect(eligible(job)).to be(true)
684+
# end
685+
# end
686+
654687
context "when hr_status_code is not 'A'" do
655-
let(:job) { eligible_job_struct.new('I', '', '', 'ANY', 1.0) }
688+
let(:job) { eligible_job_struct.new('I', '', '', 'ANY', 1.0, 0.0) }
656689

657690
it 'returns false' do
658691
expect(eligible(job)).to be(false)
659692
end
660693
end
661694

662695
context "when hr_status_code is 'A' and expected_end_date is blank" do
663-
let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 1.0) }
696+
let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 1.0, 0.0) }
664697

665698
it 'returns true' do
666699
expect(eligible(job)).to be(true)
667700
end
668701
end
669702

670703
context "when hr_status_code is 'A' and expected_end_date is after today" do
671-
let(:job) { eligible_job_struct.new('A', '2026-03-01', '', 'ANY', 1.0) }
704+
let(:job) { eligible_job_struct.new('A', '2026-03-01', '', 'ANY', 1.0, 0.0) }
672705

673706
it 'returns true' do
674707
expect(eligible(job)).to be(true)
675708
end
676709
end
677710

678711
context "when hr_status_code is 'A' and expected_end_date is today" do
679-
let(:job) { eligible_job_struct.new('A', '2026-02-23', '', 'ANY', 1.0) }
712+
let(:job) { eligible_job_struct.new('A', '2026-02-23', '', 'ANY', 1.0, 0.0) }
680713

681714
it 'returns false (<= today is not eligible per implementation)' do
682715
expect(eligible(job)).to be(false)
683716
end
684717
end
685718

686719
context "when hr_status_code is 'A' and expected_end_date is before today" do
687-
let(:job) { eligible_job_struct.new('A', '2026-02-01', '', 'ANY', 1.0) }
720+
let(:job) { eligible_job_struct.new('A', '2026-02-01', '', 'ANY', 1.0, 0.0) }
688721

689722
it 'returns false' do
690723
expect(eligible(job)).to be(false)
691724
end
692725
end
693726

694727
context 'when org_relationship_code is blank and other conditions pass' do
695-
let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 1.0) }
728+
let(:job) { eligible_job_struct.new('A', '', '', 'ANY', 1.0, 0.0) }
696729

697730
it 'returns true' do
698731
expect(eligible(job)).to be(true)
699732
end
700733
end
701734

702735
context "when org_relationship_code is 'CWR' and job_code is NOT in either allowlist" do
703-
let(:job) { eligible_job_struct.new('A', '', 'CWR', 'NOT_ALLOWED', 1.0) }
736+
let(:job) { eligible_job_struct.new('A', '', 'CWR', 'NOT_ALLOWED', 1.0, 0.0) }
704737

705738
before do
706739
allow(Config).to receive(:check_ucpath_code)
@@ -718,7 +751,7 @@ def eligible(job)
718751
end
719752

720753
context "when org_relationship_code is 'CWR' and job_code IS in visiting_scholar_job_code" do
721-
let(:job) { eligible_job_struct.new('A', '', 'CWR', 'ALLOWED', 1.0) }
754+
let(:job) { eligible_job_struct.new('A', '', 'CWR', 'ALLOWED', 1.0, 0.0) }
722755

723756
before do
724757
allow(Config).to receive(:check_ucpath_code)
@@ -736,7 +769,7 @@ def eligible(job)
736769
end
737770

738771
context "when org_relationship_code is 'CWR' and job_code IS in ucb_academic_dept_affiliate_code" do
739-
let(:job) { eligible_job_struct.new('A', '', 'CWR', 'ALLOWED', 1.0) }
772+
let(:job) { eligible_job_struct.new('A', '', 'CWR', 'ALLOWED', 1.0, 0.0) }
740773

741774
before do
742775
allow(Config).to receive(:check_ucpath_code)

0 commit comments

Comments
 (0)