Skip to content

Commit 4c0cc7b

Browse files
authored
Merge pull request #421 from bcgov/bugfix/peach-sync
Update Peach sync
2 parents 5fee763 + 935d1f9 commit 4c0cc7b

File tree

14 files changed

+138
-57
lines changed

14 files changed

+138
-57
lines changed

.github/environments/values.dev.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ config:
3232
SERVER_PCNS_APPURL: https://pcns-dev-master.apps.silver.devops.gov.bc.ca
3333
SERVER_PCNS_NAVEMAIL: NRM.PermittingAndData@gov.bc.ca
3434
SERVER_PEACH_APIPATH: "https://nr-peach-dev-main-api.azurewebsites.net/api/v1"
35+
SERVER_PEACH_TOKENURL: https://dev.loginproxy.gov.bc.ca/auth/realms/permittingexchange/protocol/openid-connect/token
3536
SERVER_PORT: "8080"
3637
SERVER_SSO_APIPATH: https://api.loginproxy.gov.bc.ca/api/v1
3738
SERVER_SSO_TOKENURL: https://loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/token

.github/environments/values.prod.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ config:
3232
SERVER_PCNS_APPURL: https://pcns-prod-master.apps.silver.devops.gov.bc.ca
3333
SERVER_PCNS_NAVEMAIL: Navigator.Service@gov.bc.ca
3434
SERVER_PEACH_APIPATH: "https://nr-peach-prod-main-api.azurewebsites.net/api/v1"
35+
SERVER_PEACH_TOKENURL: https://loginproxy.gov.bc.ca/auth/realms/permittingexchange/protocol/openid-connect/token
3536
SERVER_PORT: "8080"
3637
SERVER_SSO_APIPATH: https://api.loginproxy.gov.bc.ca/api/v1
3738
SERVER_SSO_TOKENURL: https://loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/token

.github/environments/values.test.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ config:
3232
SERVER_PCNS_APPURL: https://pcns-test-master.apps.silver.devops.gov.bc.ca
3333
SERVER_PCNS_NAVEMAIL: Navigator.Service@gov.bc.ca
3434
SERVER_PEACH_APIPATH: "https://nr-peach-test-main-api.azurewebsites.net/api/v1"
35+
SERVER_PEACH_TOKENURL: https://test.loginproxy.gov.bc.ca/auth/realms/permittingexchange/protocol/openid-connect/token
3536
SERVER_PORT: "8080"
3637
SERVER_SSO_APIPATH: https://api.loginproxy.gov.bc.ca/api/v1
3738
SERVER_SSO_TOKENURL: https://loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/token

app/config/custom-environment-variables.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@
8989
"navEmail": "SERVER_PCNS_NAVEMAIL"
9090
},
9191
"peach": {
92-
"apiPath": "SERVER_PEACH_APIPATH"
92+
"apiPath": "SERVER_PEACH_APIPATH",
93+
"clientId": "SERVER_PEACH_CLIENTID",
94+
"clientSecret": "SERVER_PEACH_CLIENTSECRET",
95+
"tokenUrl": "SERVER_PEACH_TOKENURL"
9396
},
9497
"port": "SERVER_PORT",
9598
"sso": {

app/src/db/migrations/20260105000000_050-remove-developed-in-bc.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable max-len */
21
import type { Knex } from 'knex';
32

43
export async function up(knex: Knex): Promise<void> {

app/src/parsers/peachParser.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,21 @@ export const getRecordEvents = (
177177
record: PeachRecord,
178178
n = 0,
179179
m = 0
180-
): { processEvent: ProcessEvent; onHoldEvent: CodingEvent } => {
181-
const processEvents = [...record.process_event_set].sort((a, b) => compareProcessEvents(a, b, true));
180+
): { processEvent?: ProcessEvent; onHoldEvent?: CodingEvent } => {
181+
const processEvents = record.process_event_set
182+
? [...record.process_event_set].sort((a, b) => compareProcessEvents(a, b, true))
183+
: [];
182184
// TODO: Once onHold is implemented a tie breaker compartive function will be needed
183-
const onHoldEvents = [...record.on_hold_event_set].sort((a, b) =>
184-
compareDates(piesEventToDate(a.event), piesEventToDate(b.event), true)
185-
);
185+
/* eslint-disable indent */
186+
const onHoldEvents = record.on_hold_event_set
187+
? [...record.on_hold_event_set].sort((a, b) =>
188+
compareDates(piesEventToDate(a.event), piesEventToDate(b.event), true)
189+
)
190+
: [];
191+
/* eslint-enable indent */
186192

187-
const processEvent = processEvents.length > n ? processEvents[n] : processEvents[0];
188-
const onHoldEvent = onHoldEvents.length > m ? onHoldEvents[m] : onHoldEvents[0];
193+
const processEvent = processEvents && processEvents.length > n ? processEvents[n] : undefined;
194+
const onHoldEvent = onHoldEvents && onHoldEvents.length > m ? onHoldEvents[m] : undefined;
189195

190196
return { processEvent, onHoldEvent };
191197
};
@@ -207,10 +213,12 @@ const generateStatus = (
207213
const phase = PermitPhase.APPLICATION;
208214

209215
let statusKey = processEvent.process.code;
210-
211216
if (statusKey in PeachTerminatedStage) {
212-
const { processEvent } = getRecordEvents(record, 1);
213-
const prevStageCode = processEvent.process.code_set[1] as string;
217+
const { processEvent: prevProcessEvent } = getRecordEvents(record, 1);
218+
if (!prevProcessEvent) {
219+
return { phase, stage: undefined, state: undefined };
220+
}
221+
const prevStageCode = prevProcessEvent.process.code_set[1];
214222
statusKey = `${prevStageCode}:${statusKey}`;
215223
}
216224

@@ -265,9 +273,11 @@ export function piesEventToDateParts(piesEvent: PiesEvent): DateTimeStrings {
265273
* @returns A split date representing the submitted date and time, or both null if not found
266274
*/
267275
const findSubmittedDate = (record: PeachRecord): NullableDateTimeStrings => {
268-
for (const pe of record.process_event_set) {
269-
if (pe.process.code === PEACH_SUBMITTED_STATE) {
270-
return piesEventToDateParts(pe.event);
276+
if (record.process_event_set) {
277+
for (const pe of record.process_event_set) {
278+
if (pe.process.code === PEACH_SUBMITTED_STATE) {
279+
return piesEventToDateParts(pe.event);
280+
}
271281
}
272282
}
273283
return {
@@ -282,9 +292,11 @@ const findSubmittedDate = (record: PeachRecord): NullableDateTimeStrings => {
282292
* @returns A split date representing the decision date and time, or both null if not found
283293
*/
284294
const findDecisionDate = (record: PeachRecord): NullableDateTimeStrings => {
285-
for (const pe of record.process_event_set) {
286-
if (PEACH_DECISION_STATES.has(pe.process.code)) {
287-
return piesEventToDateParts(pe.event);
295+
if (record.process_event_set) {
296+
for (const pe of record.process_event_set) {
297+
if (PEACH_DECISION_STATES.has(pe.process.code)) {
298+
return piesEventToDateParts(pe.event);
299+
}
288300
}
289301
}
290302
return {
@@ -313,6 +325,8 @@ export function summarizePeachRecord(record: PeachRecord): PeachSummary | null {
313325
// // set set permit values based on process
314326
// }
315327

328+
if (!processEvent) return null;
329+
316330
const { stage, state } = generateStatus(processEvent, record);
317331

318332
if (!stage || !state) return null;

app/src/services/peach.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@ import { Problem } from '../utils/index.ts';
66
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
77
import type { Record as PeachRecord } from '../types/pies.d.ts';
88

9+
/**
10+
* Gets Auth token using PEACH client credentials
11+
* @returns A valid access token
12+
*/
13+
async function getToken() {
14+
const response = await axios({
15+
method: 'POST',
16+
url: config.get('server.peach.tokenUrl'),
17+
data: {
18+
grant_type: 'client_credentials',
19+
client_id: config.get('server.peach.clientId'),
20+
client_secret: config.get('server.peach.clientSecret')
21+
},
22+
headers: {
23+
'Content-type': 'application/x-www-form-urlencoded'
24+
},
25+
withCredentials: true
26+
});
27+
return response.data.access_token;
28+
}
29+
930
/**
1031
* Returns an Axios instance for the PEACH API
1132
* @param options Axios request config options
@@ -19,6 +40,13 @@ function peachAxios(options: AxiosRequestConfig = {}): AxiosInstance {
1940
...options
2041
});
2142

43+
// Add bearer token
44+
instance.interceptors.request.use(async (config) => {
45+
const token = await getToken();
46+
const auth = token ? `Bearer ${token}` : '';
47+
config.headers['Authorization'] = auth;
48+
return config;
49+
});
2250
return instance;
2351
}
2452

app/src/types/pies.d.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ export interface Header {
5050
*/
5151
record_id: string;
5252
/**
53-
* The kind of record the source system stores this record as (i.e. Permit, Project, Submission or Tracking).
53+
* The kind of record the source system stores this record as (i.e. Anchor or Permit).
5454
*/
55-
record_kind: 'Permit' | 'Project' | 'Submission' | 'Tracking';
55+
record_kind: 'Anchor' | 'Permit';
5656
}
5757
export interface Record2 {
58-
on_hold_event_set: CodingEvent[];
59-
process_event_set: [ProcessEvent, ...ProcessEvent[]];
58+
on_hold_event_set?: CodingEvent[];
59+
process_event_set?: ProcessEvent[];
6060
}
6161
/**
6262
* Represents a coding concept at a specific event in time.
@@ -75,8 +75,8 @@ export interface Coding {
7575
*/
7676
code_display?: string;
7777
/**
78-
* An ordered set of code symbols, where the last element must match the code attribute. The set must contain at least
79-
* one symbol, preserve order, and not include duplicates.
78+
* An ordered set of code symbols, where the last element must match the code attribute. The set must contain at
79+
* least one symbol, preserve order, and not include duplicates.
8080
*/
8181
code_set: [Code] | [Code, Code] | [Code, Code, Code];
8282
/**
@@ -105,8 +105,8 @@ export interface Event1 {
105105
end_datetime?: string;
106106
}
107107
/**
108-
* This schema is used when the event starts with a date (`start_date`), and optionally, an end date (`end_date`) can be
109-
* specified. Mixing a start date with a datetime is not allowed.
108+
* This schema is used when the event starts with a date (`start_date`), and optionally, an end date (`end_date`) can
109+
* be specified. Mixing a start date with a datetime is not allowed.
110110
*/
111111
export interface Date {
112112
start_date: string;
@@ -152,16 +152,16 @@ export type RecordLinkage1 = Header;
152152

153153
export interface RecordLinkage2 {
154154
/**
155-
* A valid NRIDS IT Service Management code which identifies the source system,
156-
* service or asset that the linked data originates from.
155+
* A valid NRIDS IT Service Management code which identifies the source system, service or asset that the linked data
156+
* originates from.
157157
*/
158158
linked_system_id: string;
159159
/**
160160
* The record or primary key representing what record should be linked with the primary header record.
161161
*/
162162
linked_record_id: string;
163163
/**
164-
* The kind of record the source system stores this linked record as (i.e. Permit, Project, Submission or Tracking).
164+
* The kind of record the source system stores this linked record as (i.e. Anchor or Permit).
165165
*/
166-
linked_record_kind: 'Permit' | 'Project' | 'Submission' | 'Tracking';
166+
linked_record_kind: 'Anchor' | 'Permit';
167167
}

app/tests/unit/parsers/peachParser.test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ describe('peachRecordParser', () => {
5757

5858
const { processEvent } = getRecordEvents(record);
5959

60-
expect(processEvent.process.code).toBe('REJECTED');
60+
expect(processEvent?.process.code).toBe('REJECTED');
6161
});
6262

63-
it('falls back to the first process event when n is out of range', () => {
63+
it('returns undefined when n is out of range', () => {
6464
const record: PeachRecord = {
6565
...TEST_PEACH_RECORD_1,
6666
process_event_set: [
@@ -78,8 +78,7 @@ describe('peachRecordParser', () => {
7878

7979
const { processEvent } = getRecordEvents(record, 5);
8080

81-
expect(processEvent.event.start_datetime).toBe('2024-09-01T00:00:00.000Z');
82-
expect(processEvent.process.code).toBe('SUBMITTED');
81+
expect(processEvent).toBe(undefined);
8382
});
8483
});
8584

charts/pcns/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: nr-permitconnect-navigator-service
33
# This is the chart version. This version number should be incremented each time you make changes
44
# to the chart and its templates, including the app version.
55
# Versions are expected to follow Semantic Versioning (https://semver.org/)
6-
version: 0.0.28
6+
version: 0.0.29
77
kubeVersion: ">= 1.13.0"
88
description: PermitConnect Navigator Service
99
# A chart can be either an 'application' or a 'library' chart.

0 commit comments

Comments
 (0)