diff --git a/gitops/charts/traffic-court-dev-values.yaml b/gitops/charts/traffic-court-dev-values.yaml index 71890fe6b..52cf38efc 100644 --- a/gitops/charts/traffic-court-dev-values.yaml +++ b/gitops/charts/traffic-court-dev-values.yaml @@ -7,6 +7,7 @@ global: arc-dispute-api: image: + tag: "2.2.12" tag: "2.3.0" pullPolicy: Always env: diff --git a/src/backend/TrafficCourts/Common/Features/Lookups/AgencyLookupService.cs b/src/backend/TrafficCourts/Common/Features/Lookups/AgencyLookupService.cs index b4f28ae18..639f73928 100644 --- a/src/backend/TrafficCourts/Common/Features/Lookups/AgencyLookupService.cs +++ b/src/backend/TrafficCourts/Common/Features/Lookups/AgencyLookupService.cs @@ -11,4 +11,32 @@ public AgencyLookupService(IConnectionMultiplexer redis, IMemoryCache cache, ILo : base("Agencies", redis, cache, TimeSpan.FromHours(1), logger) { } + + public async Task GetByIdAsync(string agencyId) + { + if (string.IsNullOrEmpty(agencyId)) + { + return null; + } + + var agencies = await GetAgenciesAsync(agency => agency.Id == agencyId); + if (agencies.Count == 0) + { + return null; + } + + if (agencies.Count > 1) + { + _logger.LogInformation("{Count} agencies were returned matching {Id}, returning first value", agencies.Count, agencyId); + } + + return agencies[0]; + } + + private async Task> GetAgenciesAsync(Func predicate) + { + var values = await GetListAsync(); + var sections = values.Where(predicate).ToList(); + return sections; + } } diff --git a/src/backend/TrafficCourts/Common/Features/Lookups/IAgencyLookupService.cs b/src/backend/TrafficCourts/Common/Features/Lookups/IAgencyLookupService.cs index ed72555c5..8e4a70924 100644 --- a/src/backend/TrafficCourts/Common/Features/Lookups/IAgencyLookupService.cs +++ b/src/backend/TrafficCourts/Common/Features/Lookups/IAgencyLookupService.cs @@ -4,4 +4,10 @@ namespace TrafficCourts.Common.Features.Lookups; public interface IAgencyLookupService : ICachedLookupService { + /// + /// Returns a specific Agency from the Redis Cache based on the agency id + /// + /// + /// + Task GetByIdAsync(string agencyId); } diff --git a/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_DigitalCaseFile.docx b/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_DigitalCaseFile.docx index 9c38837b4..1902fb8e7 100644 Binary files a/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_DigitalCaseFile.docx and b/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_DigitalCaseFile.docx differ diff --git a/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_HR_DigitalCaseFile.docx b/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_HR_DigitalCaseFile.docx index b4efa093f..21aec84ca 100644 Binary files a/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_HR_DigitalCaseFile.docx and b/src/backend/TrafficCourts/Staff.Service/Models/DigitalCaseFiles/Print/Templates/template_HR_DigitalCaseFile.docx differ diff --git a/src/backend/TrafficCourts/Staff.Service/Services/DisputeService.cs b/src/backend/TrafficCourts/Staff.Service/Services/DisputeService.cs index ec445ba94..a48c55800 100644 --- a/src/backend/TrafficCourts/Staff.Service/Services/DisputeService.cs +++ b/src/backend/TrafficCourts/Staff.Service/Services/DisputeService.cs @@ -190,13 +190,17 @@ public async Task CancelDisputeAsync(long disputeId, string cancelledReason, Cla GetUserName(user)); await _bus.PublishWithLog(_logger, fileHistoryRecord, cancellationToken); - // Publish file history of cancellation email - fileHistoryRecord.AuditLogEntryType = FileHistoryAuditLogEntryType.EMCA; - await _bus.PublishWithLog(_logger, fileHistoryRecord, cancellationToken); + // Publish file history for cancelled remarks + SaveFileHistoryRecord fileHistoryRecordRemark = Mapper.ToFileHistoryWithNoticeOfDisputeId( + dispute.NoticeOfDisputeGuid, + FileHistoryAuditLogEntryType.FRMK, + GetUserName(user), + cancelledReason); + await _bus.PublishWithLog(_logger, fileHistoryRecordRemark, cancellationToken); // Publish cancel event (consumer(s) will generate email, etc) DisputeCancelled cancelledEvent = Mapper.ToDisputeCancelled(dispute); - await _bus. PublishWithLog(_logger, cancelledEvent, cancellationToken); + await _bus.PublishWithLog(_logger, cancelledEvent, cancellationToken); } public async Task RejectDisputeAsync(long disputeId, string rejectedReason, ClaimsPrincipal user, CancellationToken cancellationToken) @@ -214,7 +218,15 @@ public async Task RejectDisputeAsync(long disputeId, string rejectedReason, Clai GetUserName(user)); await _bus.PublishWithLog(_logger, fileHistoryRecord, cancellationToken); - // Publish submit event (consumer(s) will generate email, etc) + // Publish file history for rejected remarks + SaveFileHistoryRecord fileHistoryRecordRemark = Mapper.ToFileHistoryWithNoticeOfDisputeId( + dispute.NoticeOfDisputeGuid, + FileHistoryAuditLogEntryType.FRMK, + GetUserName(user), + rejectedReason); + await _bus.PublishWithLog(_logger, fileHistoryRecordRemark, cancellationToken); + + // Publish reject event (consumer(s) will generate email, etc) DisputeRejected rejectedEvent = Mapper.ToDisputeRejected(dispute); await _bus.PublishWithLog(_logger, rejectedEvent, cancellationToken); } diff --git a/src/backend/TrafficCourts/Staff.Service/Services/PrintDigitalCaseFileService.cs b/src/backend/TrafficCourts/Staff.Service/Services/PrintDigitalCaseFileService.cs index 32b1d1306..b1296b0d3 100644 --- a/src/backend/TrafficCourts/Staff.Service/Services/PrintDigitalCaseFileService.cs +++ b/src/backend/TrafficCourts/Staff.Service/Services/PrintDigitalCaseFileService.cs @@ -13,6 +13,7 @@ public class PrintDigitalCaseFileService : IPrintDigitalCaseFileService private readonly IJJDisputeService _jjDisputeService; private readonly IOracleDataApiService _oracleDataApi; private readonly IProvinceLookupService _provinceLookupService; + private readonly IAgencyLookupService _agencyLookupService; private readonly ICountryLookupService _countryLookupService; private readonly IDocumentGenerationService _documentGeneration; private readonly IDisputeService _disputeService; @@ -22,6 +23,7 @@ public PrintDigitalCaseFileService( IJJDisputeService jjDisputeService, IOracleDataApiService oracleDataApi, IProvinceLookupService provinceLookupService, + IAgencyLookupService agencyLookupService, ICountryLookupService countryLookupService, IDocumentGenerationService documentGeneration, IDisputeService disputeService, @@ -30,6 +32,7 @@ public PrintDigitalCaseFileService( _jjDisputeService = jjDisputeService ?? throw new ArgumentNullException(nameof(jjDisputeService)); _oracleDataApi = oracleDataApi ?? throw new ArgumentNullException(nameof(oracleDataApi)); _provinceLookupService = provinceLookupService ?? throw new ArgumentNullException(nameof(provinceLookupService)); + _agencyLookupService = agencyLookupService ?? throw new ArgumentNullException(nameof(agencyLookupService)); _countryLookupService = countryLookupService ?? throw new ArgumentNullException(nameof(countryLookupService)); _documentGeneration = documentGeneration ?? throw new ArgumentNullException(nameof(documentGeneration)); _disputeService = disputeService ?? throw new ArgumentNullException(nameof(disputeService)); @@ -244,6 +247,22 @@ private Stream GetTemplate(string name) return country; } + /// + /// Returns Agency (Courthouse Location) based on the provided agencyId through agencyLookupService. + /// + /// + /// + private async Task GetCourthouseLocationAsync(string agencyId) + { + Domain.Models.Agency? courthouseLocation = null; + if (agencyId is not null) + { + courthouseLocation = await _agencyLookupService.GetByIdAsync(agencyId); + } + + return courthouseLocation; + } + /// /// Fetches the based on ticket number. This really should be using the tco_dispute.dispute_id. /// @@ -257,6 +276,9 @@ internal async Task GetDigitalCaseFileAsync(string ticketNumber Domain.Models.Province? driversLicenceProvince = await GetDriversLicenceProvinceAsync(dispute.DrvLicIssuedProvSeqNo, dispute.DrvLicIssuedCtryId); + // Get courthouse location data from the courthouse location lookup service based on CourtAgenId provided from the dispute + Agency? courthouseLocation = await GetCourthouseLocationAsync(dispute.CourtAgenId); + var digitalCaseFile = new DigitalCaseFile(); // fill in each section, the sections and fields are populated in order matching the template @@ -273,7 +295,7 @@ internal async Task GetDigitalCaseFileAsync(string ticketNumber ticket.Submitted = new FormattedDateOnly(dispute.SubmittedTs); ticket.IcbcReceived = new FormattedDateOnly(dispute.IcbcReceivedDate); ticket.CourtAgenyId = dispute.CourtAgenId; - ticket.CourtHouse = dispute.CourthouseLocation; + ticket.CourtHouse = courthouseLocation?.Name ?? string.Empty; // set the contact information var contact = digitalCaseFile.Contact; diff --git a/src/backend/TrafficCourts/TrafficCourts.Arc.Dispute.Service/Controllers/TcoDisputeTicketController.cs b/src/backend/TrafficCourts/TrafficCourts.Arc.Dispute.Service/Controllers/TcoDisputeTicketController.cs index 69ecb832c..158f083da 100644 --- a/src/backend/TrafficCourts/TrafficCourts.Arc.Dispute.Service/Controllers/TcoDisputeTicketController.cs +++ b/src/backend/TrafficCourts/TrafficCourts.Arc.Dispute.Service/Controllers/TcoDisputeTicketController.cs @@ -12,13 +12,13 @@ public class TcoDisputeTicketController : ControllerBase { private readonly IMapper _mapper; private readonly IArcFileService _arcFileService; - private readonly ILogger _logger; + private readonly ILogger _logger; // Assign the object in the constructor for dependency injection public TcoDisputeTicketController( IMapper mapper, IArcFileService arcFileService, - ILogger logger) + ILogger logger) { _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); _arcFileService = arcFileService ?? throw new ArgumentNullException(nameof(arcFileService)); diff --git a/src/backend/TrafficCourts/TrafficCourts.Staff.Service.Test/Services/PrintDigialCaseFile/PrintDigitalCaseFileIntegrationTest.cs b/src/backend/TrafficCourts/TrafficCourts.Staff.Service.Test/Services/PrintDigialCaseFile/PrintDigitalCaseFileIntegrationTest.cs index 5fd0d7df3..35d0ca5cf 100644 --- a/src/backend/TrafficCourts/TrafficCourts.Staff.Service.Test/Services/PrintDigialCaseFile/PrintDigitalCaseFileIntegrationTest.cs +++ b/src/backend/TrafficCourts/TrafficCourts.Staff.Service.Test/Services/PrintDigialCaseFile/PrintDigitalCaseFileIntegrationTest.cs @@ -71,6 +71,7 @@ public PrintDigitalCaseFileIntegrationTest() jjDisputeService, oracleDataApi, Mock.Of(), + Mock.Of(), Mock.Of(), Mock.Of(), disputeService, diff --git a/src/frontend/staff-portal/src/app/api/.openapi-generator/FILES b/src/frontend/staff-portal/src/app/api/.openapi-generator/FILES index 1b3e0a095..d359245de 100644 --- a/src/frontend/staff-portal/src/app/api/.openapi-generator/FILES +++ b/src/frontend/staff-portal/src/app/api/.openapi-generator/FILES @@ -19,6 +19,7 @@ model/agency.model.ts model/boundingBox.model.ts model/country.model.ts model/credentialRepresentation.model.ts +model/dcfTemplateType.model.ts model/dispute.model.ts model/disputeAppearanceLessThan14DaysYn.model.ts model/disputeContactTypeCd.model.ts diff --git a/src/frontend/staff-portal/src/app/api/api/dispute.service.ts b/src/frontend/staff-portal/src/app/api/api/dispute.service.ts index 417e9780d..766ac0a65 100644 --- a/src/frontend/staff-portal/src/app/api/api/dispute.service.ts +++ b/src/frontend/staff-portal/src/app/api/api/dispute.service.ts @@ -18,6 +18,8 @@ import { HttpClient, HttpHeaders, HttpParams, import { CustomHttpParameterCodec } from '../encoder'; import { Observable } from 'rxjs'; +// @ts-ignore +import { DcfTemplateType } from '../model/dcfTemplateType.model'; // @ts-ignore import { Dispute } from '../model/dispute.model'; // @ts-ignore @@ -341,13 +343,14 @@ export class DisputeService { * Returns generated document. * @param disputeId Dispute Id * @param timeZone The IANA timze zone id + * @param type The type of template to generate * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @param reportProgress flag to report request and response progress. */ - public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable; - public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; - public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; - public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable { + public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, type?: DcfTemplateType, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable; + public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, type?: DcfTemplateType, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; + public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, type?: DcfTemplateType, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; + public apiDisputeDisputeIdPrintGet(disputeId: number, timeZone: string, type?: DcfTemplateType, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable { if (disputeId === null || disputeId === undefined) { throw new Error('Required parameter disputeId was null or undefined when calling apiDisputeDisputeIdPrintGet.'); } @@ -360,6 +363,10 @@ export class DisputeService { localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, timeZone, 'timeZone'); } + if (type !== undefined && type !== null) { + localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, + type, 'type'); + } let localVarHeaders = this.defaultHeaders; diff --git a/src/frontend/staff-portal/src/app/api/api/jJ.service.ts b/src/frontend/staff-portal/src/app/api/api/jJ.service.ts index 1c7158fce..7f406eeaa 100644 --- a/src/frontend/staff-portal/src/app/api/api/jJ.service.ts +++ b/src/frontend/staff-portal/src/app/api/api/jJ.service.ts @@ -18,6 +18,8 @@ import { HttpClient, HttpHeaders, HttpParams, import { CustomHttpParameterCodec } from '../encoder'; import { Observable } from 'rxjs'; +// @ts-ignore +import { DcfTemplateType } from '../model/dcfTemplateType.model'; // @ts-ignore import { DocumentType } from '../model/documentType.model'; // @ts-ignore @@ -643,13 +645,14 @@ export class JJService { * Returns generated document. This really should be using the tco_dispute.dispute_id. * @param ticketNumber The ticket number to print. This really should be using the tco_dispute.dispute_id * @param timeZone The IANA timze zone id + * @param type The type of template to generate * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @param reportProgress flag to report request and response progress. */ - public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable; - public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; - public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; - public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable { + public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, type?: DcfTemplateType, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable; + public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, type?: DcfTemplateType, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; + public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, type?: DcfTemplateType, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable>; + public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string, type?: DcfTemplateType, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'text/plain' | 'application/json' | 'text/json', context?: HttpContext}): Observable { if (ticketNumber === null || ticketNumber === undefined) { throw new Error('Required parameter ticketNumber was null or undefined when calling apiJjTicketNumberPrintGet.'); } @@ -662,6 +665,10 @@ export class JJService { localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, timeZone, 'timeZone'); } + if (type !== undefined && type !== null) { + localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, + type, 'type'); + } let localVarHeaders = this.defaultHeaders; diff --git a/src/frontend/staff-portal/src/app/api/model/dcfTemplateType.model.ts b/src/frontend/staff-portal/src/app/api/model/dcfTemplateType.model.ts new file mode 100644 index 000000000..8c7bda034 --- /dev/null +++ b/src/frontend/staff-portal/src/app/api/model/dcfTemplateType.model.ts @@ -0,0 +1,21 @@ +/** + * VTC Staff API + * Violation Ticket Centre Staff API + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type DcfTemplateType = 'DcfTemplate' | 'HrDcfTemplate' | 'WrDcfTemplate'; + +export const DcfTemplateType = { + DcfTemplate: 'DcfTemplate' as DcfTemplateType, + HrDcfTemplate: 'HrDcfTemplate' as DcfTemplateType, + WrDcfTemplate: 'WrDcfTemplate' as DcfTemplateType +}; + diff --git a/src/frontend/staff-portal/src/app/api/model/jJDispute.model.ts b/src/frontend/staff-portal/src/app/api/model/jJDispute.model.ts index 048270691..fef8ab768 100644 --- a/src/frontend/staff-portal/src/app/api/model/jJDispute.model.ts +++ b/src/frontend/staff-portal/src/app/api/model/jJDispute.model.ts @@ -62,6 +62,7 @@ export interface JJDispute { occamDisputantGiven2Nm?: string | null; occamDisputantGiven3Nm?: string | null; occamDisputantSurnameNm?: string | null; + occamDisputantPhoneNumber?: string | null; occamDisputeId?: number; occamViolationTicketUpldId?: string | null; submittedTs?: string | null; diff --git a/src/frontend/staff-portal/src/app/api/model/models.ts b/src/frontend/staff-portal/src/app/api/model/models.ts index fc7fc6202..76574f84e 100644 --- a/src/frontend/staff-portal/src/app/api/model/models.ts +++ b/src/frontend/staff-portal/src/app/api/model/models.ts @@ -2,6 +2,7 @@ export * from './agency.model'; export * from './boundingBox.model'; export * from './country.model'; export * from './credentialRepresentation.model'; +export * from './dcfTemplateType.model'; export * from './dispute.model'; export * from './disputeAppearanceLessThan14DaysYn.model'; export * from './disputeContactTypeCd.model'; diff --git a/src/frontend/staff-portal/src/app/api/swagger.json b/src/frontend/staff-portal/src/app/api/swagger.json index 19817b424..f9b235dd7 100644 --- a/src/frontend/staff-portal/src/app/api/swagger.json +++ b/src/frontend/staff-portal/src/app/api/swagger.json @@ -722,7 +722,7 @@ } }, "405": { - "description": "A Dispute status can only be set to REJECTED iff status is NEW, VALIDATED or PROCESSING and the rejected reason must be <= 256 characters. Update failed.", + "description": "A Dispute status can only be set to REJECTED iff status is NEW, VALIDATED or PROCESSING and the rejected reason must be \u003C= 256 characters. Update failed.", "content": { "text/plain": { "schema": { @@ -1617,6 +1617,14 @@ "schema": { "type": "string" } + }, + { + "name": "type", + "in": "query", + "description": "The type of template to generate", + "schema": { + "$ref": "#/components/schemas/DcfTemplateType" + } } ], "responses": { @@ -4496,6 +4504,14 @@ "schema": { "type": "string" } + }, + { + "name": "type", + "in": "query", + "description": "The type of template to generate", + "schema": { + "$ref": "#/components/schemas/DcfTemplateType" + } } ], "responses": { @@ -4955,12 +4971,22 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, "additionalProperties": false }, + "DcfTemplateType": { + "enum": [ + "DcfTemplate", + "HrDcfTemplate", + "WrDcfTemplate" + ], + "type": "string" + }, "Dispute": { "type": "object", "properties": { @@ -5293,7 +5319,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -5356,7 +5384,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -5502,7 +5532,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -5662,7 +5694,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -5867,7 +5901,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -5910,7 +5946,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -5997,7 +6035,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -6290,6 +6330,10 @@ "type": "string", "nullable": true }, + "occamDisputantPhoneNumber": { + "type": "string", + "nullable": true + }, "occamDisputeId": { "type": "integer", "format": "int64" @@ -6469,7 +6513,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -6567,7 +6613,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -6691,7 +6739,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -6820,7 +6870,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -6958,7 +7010,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -7188,7 +7242,9 @@ "nullable": true } }, - "additionalProperties": { } + "additionalProperties": { + + } }, "Province": { "type": "object", @@ -7229,7 +7285,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -7312,7 +7370,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -7357,7 +7417,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -7514,7 +7576,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -7665,7 +7729,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true }, "violationTicketImage": { @@ -7752,7 +7818,9 @@ }, "additionalProperties": { "type": "object", - "additionalProperties": { }, + "additionalProperties": { + + }, "nullable": true } }, @@ -7840,7 +7908,7 @@ }, "security": [ { - "Bearer": [ ] + "Bearer": [] } ] } \ No newline at end of file diff --git a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-court-appearances/jj-dispute-court-appearances.component.html b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-court-appearances/jj-dispute-court-appearances.component.html index f32449add..3995f7e5c 100644 --- a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-court-appearances/jj-dispute-court-appearances.component.html +++ b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-court-appearances/jj-dispute-court-appearances.component.html @@ -101,7 +101,7 @@ - JJ endorsements: {{ element.comments }} + JJ Endorsements: {{ element.comments }} diff --git a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-remarks/jj-dispute-remarks.component.ts b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-remarks/jj-dispute-remarks.component.ts index 62f0b3a59..53eff6f7b 100644 --- a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-remarks/jj-dispute-remarks.component.ts +++ b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute-remarks/jj-dispute-remarks.component.ts @@ -1,4 +1,4 @@ -import { Component, OnChanges, ViewChild, Input, OnDestroy } from '@angular/core'; +import { Component, ViewChild, Input, OnDestroy } from '@angular/core'; import { MatLegacyTableDataSource as MatTableDataSource } from '@angular/material/legacy-table'; import { MatSort } from '@angular/material/sort'; import { FileHistory, JJDisputeRemark } from 'app/api'; @@ -10,7 +10,7 @@ import { Subscription } from 'rxjs'; templateUrl: './jj-dispute-remarks.component.html', styleUrls: ['./jj-dispute-remarks.component.scss'], }) -export class JJDisputeRemarksComponent implements OnChanges, OnDestroy { +export class JJDisputeRemarksComponent implements OnDestroy { @Input() data: JJDisputeRemark[]; @ViewChild(MatSort) sort = new MatSort(); @@ -30,10 +30,6 @@ export class JJDisputeRemarksComponent implements OnChanges, OnDestroy { })); } - ngOnChanges(): void { - this.refreshData(); - } - ngOnDestroy(): void { this.subscriptions.forEach(subscription => { subscription.unsubscribe(); @@ -43,11 +39,13 @@ export class JJDisputeRemarksComponent implements OnChanges, OnDestroy { refreshData(): void { // Add ticket validation saving remarks this.historyRecordService.FileHistories?.filter(i => i.auditLogEntryType === "FRMK").forEach((fileHistory: FileHistory) => { - this.data.push({ - createdTs: fileHistory.createdTs, - userFullName: fileHistory.actionByApplicationUser, - note: fileHistory.comment - }) + if(this.data){ + this.data.push({ + createdTs: fileHistory.createdTs, + userFullName: fileHistory.actionByApplicationUser, + note: fileHistory.comment + }) + } }) this.data = this.data?.sort((a: JJDisputeRemark, b: JJDisputeRemark) => { @@ -55,4 +53,4 @@ export class JJDisputeRemarksComponent implements OnChanges, OnDestroy { }); this.dataSource = new MatTableDataSource(this.data); } -} +} \ No newline at end of file diff --git a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.html b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.html index 42d7865c2..00bff3ed4 100644 --- a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.html +++ b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.html @@ -21,21 +21,10 @@ -   - - - - + + @@ -418,7 +407,7 @@

Court Appearance

-

JJ endorsements:

+

JJ Endorsements:

diff --git a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.ts b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.ts index 3b8373d73..167a8cb53 100644 --- a/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.ts +++ b/src/frontend/staff-portal/src/app/components/jj-dispute-info/jj-dispute/jj-dispute.component.ts @@ -2,7 +2,7 @@ import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } import { LoggerService } from '@core/services/logger.service'; import { JJDisputeService, JJDispute } from '../../../services/jj-dispute.service'; import { Observable, map } from 'rxjs'; -import { JJDisputedCount, JJDisputeStatus, JJDisputedCountRequestReduction, JJDisputedCountRequestTimeToPay, JJDisputeHearingType, JJDisputeCourtAppearanceRoPAppCd, JJDisputeCourtAppearanceRoPCrown, JJDisputeCourtAppearanceRoPDattCd, JJDisputeCourtAppearanceRoPJjSeized, FileMetadata, JJDisputeElectronicTicketYn, JJDisputeNoticeOfHearingYn, TicketImageDataJustinDocumentReportType, DocumentType, JJDisputeContactType, JJDisputedCountRoPFinding, Province, Language, JJDisputeDisputantAttendanceType, JJDisputeAccidentYn, JJDisputeMultipleOfficersYn, JJDisputeSignatoryType } from 'app/api/model/models'; +import { JJDisputedCount, JJDisputeStatus, JJDisputedCountRequestReduction, JJDisputedCountRequestTimeToPay, JJDisputeHearingType, JJDisputeCourtAppearanceRoPAppCd, JJDisputeCourtAppearanceRoPCrown, JJDisputeCourtAppearanceRoPDattCd, JJDisputeCourtAppearanceRoPJjSeized, FileMetadata, JJDisputeElectronicTicketYn, JJDisputeNoticeOfHearingYn, TicketImageDataJustinDocumentReportType, DocumentType, JJDisputeContactType, JJDisputedCountRoPFinding, Province, Language, JJDisputeDisputantAttendanceType, JJDisputeAccidentYn, JJDisputeMultipleOfficersYn, JJDisputeSignatoryType, DcfTemplateType } from 'app/api/model/models'; import { DialogOptions } from '@shared/dialogs/dialog-options.model'; import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog'; import { AuthService, UserRepresentation } from 'app/services/auth.service'; @@ -552,8 +552,25 @@ export class JJDisputeComponent implements OnInit { }); } - onPrint() { - this.jjDisputeService.apiJjTicketNumberPrintGet(this.lastUpdatedJJDispute.ticketNumber).subscribe(result => { + onPrint(isCompleteVersion: boolean) { + var type = DcfTemplateType.DcfTemplate; + if (!isCompleteVersion) { + switch (this.lastUpdatedJJDispute.hearingType) { + case this.HearingType.WrittenReasons: + // Use WrittenReasons template for print + type = DcfTemplateType.WrDcfTemplate; + break; + case this.HearingType.CourtAppearance: + // Use Hearing template for print + type = DcfTemplateType.HrDcfTemplate; + break; + default: + // Use main complete template by default + type = DcfTemplateType.DcfTemplate; + } + } + + this.jjDisputeService.apiJjTicketNumberPrintGet(this.lastUpdatedJJDispute.ticketNumber, type).subscribe(result => { if (result) { var url = URL.createObjectURL(result); window.open(url); diff --git a/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-digital-case-file/jj-dispute-digital-case-file.component.scss b/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-digital-case-file/jj-dispute-digital-case-file.component.scss index e29d9dea0..547fb3ca8 100644 --- a/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-digital-case-file/jj-dispute-digital-case-file.component.scss +++ b/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-digital-case-file/jj-dispute-digital-case-file.component.scss @@ -70,4 +70,8 @@ th { } } } + + .mat-sort-header-arrow { + color: #757575; + } } \ No newline at end of file diff --git a/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-wr-assignments/jj-dispute-wr-assignments.component.ts b/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-wr-assignments/jj-dispute-wr-assignments.component.ts index 4fcaf0eea..5cb5053a5 100644 --- a/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-wr-assignments/jj-dispute-wr-assignments.component.ts +++ b/src/frontend/staff-portal/src/app/components/jj-workbench/jj-dispute-wr-assignments/jj-dispute-wr-assignments.component.ts @@ -71,7 +71,9 @@ export class JJDisputeWRAssignmentsComponent implements OnInit, AfterViewInit { // custom sorting on columns this.dataSource.sortingDataAccessor = (data: any, sortHeaderId: string): string => { - if (typeof data[sortHeaderId] === 'string') { + if (sortHeaderId === 'timeToPayReason'){ + return this.getType(data); + } else if (typeof data[sortHeaderId] === 'string') { return data[sortHeaderId].toLocaleLowerCase(); } return data[sortHeaderId]; diff --git a/src/frontend/staff-portal/src/app/components/staff-workbench/contact-info/contact-info.component.ts b/src/frontend/staff-portal/src/app/components/staff-workbench/contact-info/contact-info.component.ts index 8aeb0c595..421866f41 100644 --- a/src/frontend/staff-portal/src/app/components/staff-workbench/contact-info/contact-info.component.ts +++ b/src/frontend/staff-portal/src/app/components/staff-workbench/contact-info/contact-info.component.ts @@ -12,7 +12,7 @@ import { DialogOptions } from '@shared/dialogs/dialog-options.model'; import { ConfirmReasonDialogComponent } from '@shared/dialogs/confirm-reason-dialog/confirm-reason-dialog.component'; import { ConfirmDialogComponent } from '@shared/dialogs/confirm-dialog/confirm-dialog.component'; import { CountryCodeValue, ProvinceCodeValue } from '@config/config.model'; -import { DisputeContactTypeCd, DisputeStatus } from 'app/api'; +import { DcfTemplateType, DisputeContactTypeCd, DisputeStatus } from 'app/api'; @Component({ selector: 'app-contact-info', @@ -238,7 +238,7 @@ export class ContactInfoComponent implements OnInit { actionType: "warn", cancelTextKey: "Go back", icon: "error_outline", - message: this.form.get('rejectedReason').value + message: "" }; this.dialog.open(ConfirmReasonDialogComponent, { data }).afterClosed() .subscribe((action?: any) => { @@ -269,7 +269,7 @@ export class ContactInfoComponent implements OnInit { actionType: "warn", cancelTextKey: "Go back", icon: "error_outline", - message: this.form.get('rejectedReason').value + message: "" }; this.dialog.open(ConfirmReasonDialogComponent, { data }).afterClosed() .subscribe((action?: any) => { @@ -379,7 +379,9 @@ export class ContactInfoComponent implements OnInit { } onPrint() { - this.disputeService.apiTicketValidationPrintGet(this.lastUpdatedDispute.disputeId).subscribe(result => { + var type = DcfTemplateType.DcfTemplate; + + this.disputeService.apiTicketValidationPrintGet(this.lastUpdatedDispute.disputeId, type).subscribe(result => { if (result) { var url = URL.createObjectURL(result); window.open(url); diff --git a/src/frontend/staff-portal/src/app/components/staff-workbench/ticket-info/ticket-info.component.ts b/src/frontend/staff-portal/src/app/components/staff-workbench/ticket-info/ticket-info.component.ts index e159d9a31..3bbcf3d07 100644 --- a/src/frontend/staff-portal/src/app/components/staff-workbench/ticket-info/ticket-info.component.ts +++ b/src/frontend/staff-portal/src/app/components/staff-workbench/ticket-info/ticket-info.component.ts @@ -8,7 +8,7 @@ import { FormControlValidators } from '@core/validators/form-control.validators' import { Dispute, DisputeService } from '../../../services/dispute.service'; import { CountryCodeValue, ProvinceCodeValue } from '@config/config.model'; import { ConfigService } from '@config/config.service'; -import { DisputeContactTypeCd, ViolationTicket, ViolationTicketCount, ViolationTicketCountIsAct, ViolationTicketCountIsRegulation, DisputeStatus } from 'app/api'; +import { DisputeContactTypeCd, ViolationTicket, ViolationTicketCount, ViolationTicketCountIsAct, ViolationTicketCountIsRegulation, DisputeStatus, DcfTemplateType } from 'app/api'; import { LookupsService, Statute } from 'app/services/lookups.service'; import { DialogOptions } from '@shared/dialogs/dialog-options.model'; import { ConfirmReasonDialogComponent } from '@shared/dialogs/confirm-reason-dialog/confirm-reason-dialog.component'; @@ -660,7 +660,7 @@ export class TicketInfoComponent implements OnInit { actionType: "warn", cancelTextKey: "Go back", icon: "error_outline", - message: this.form.get('rejectedReason').value + message: "" }; this.dialog.open(ConfirmReasonDialogComponent, { data }).afterClosed() .subscribe((action?: any) => { @@ -692,7 +692,7 @@ export class TicketInfoComponent implements OnInit { actionType: "warn", cancelTextKey: "Go back", icon: "error_outline", - message: this.form.get('rejectedReason').value + message: "" }; this.dialog.open(ConfirmReasonDialogComponent, { data }).afterClosed() .subscribe((action?: any) => { @@ -895,7 +895,9 @@ export class TicketInfoComponent implements OnInit { } onPrint() { - this.disputeService.apiTicketValidationPrintGet(this.lastUpdatedDispute.disputeId).subscribe(result => { + var type = DcfTemplateType.DcfTemplate; + + this.disputeService.apiTicketValidationPrintGet(this.lastUpdatedDispute.disputeId, type).subscribe(result => { if (result) { var url = URL.createObjectURL(result); window.open(url); diff --git a/src/frontend/staff-portal/src/app/services/dispute.service.ts b/src/frontend/staff-portal/src/app/services/dispute.service.ts index 9f2bf656e..5076e8b57 100644 --- a/src/frontend/staff-portal/src/app/services/dispute.service.ts +++ b/src/frontend/staff-portal/src/app/services/dispute.service.ts @@ -1,7 +1,7 @@ import { ConfigService } from '@config/config.service'; import { LoggerService } from '@core/services/logger.service'; import { ToastService } from '@core/services/toast.service'; -import { DisputeService as DisputeApiService, Dispute as DisputeBase, DisputeWithUpdates as DisputeWithUpdatesBase, DisputeUpdateRequest as DisputantUpdateRequestBase, DisputeUpdateRequestStatus2, DisputeListItem, PagedDisputeListItemCollection, DisputeStatus, GetDisputeCountResponse, SortDirection, ExcludeStatus } from 'app/api'; +import { DisputeService as DisputeApiService, Dispute as DisputeBase, DisputeWithUpdates as DisputeWithUpdatesBase, DisputeUpdateRequest as DisputantUpdateRequestBase, DisputeUpdateRequestStatus2, DisputeListItem, PagedDisputeListItemCollection, DisputeStatus, GetDisputeCountResponse, SortDirection, ExcludeStatus, DcfTemplateType } from 'app/api'; import { Observable, BehaviorSubject } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { EventEmitter, Injectable } from '@angular/core'; @@ -523,9 +523,9 @@ export class DisputeService implements IDisputeService { return dispute; } - public apiTicketValidationPrintGet(disputeId: number, timeZone: string = Intl.DateTimeFormat().resolvedOptions().timeZone): Observable { + public apiTicketValidationPrintGet(disputeId: number, type: DcfTemplateType, timeZone: string = Intl.DateTimeFormat().resolvedOptions().timeZone): Observable { return this.http - .get(`/api/dispute/${disputeId}/print?timeZone=${timeZone}`, { + .get(`/api/dispute/${disputeId}/print?timeZone=${timeZone}&type=${type}`, { observe: 'response', responseType: 'blob', context: new HttpContext(), diff --git a/src/frontend/staff-portal/src/app/services/jj-dispute.service.ts b/src/frontend/staff-portal/src/app/services/jj-dispute.service.ts index 05651f442..7d32a8f99 100644 --- a/src/frontend/staff-portal/src/app/services/jj-dispute.service.ts +++ b/src/frontend/staff-portal/src/app/services/jj-dispute.service.ts @@ -6,7 +6,7 @@ import { catchError, map } from 'rxjs/operators'; import { HttpClient, HttpContext, HttpHeaders, HttpResponse } from '@angular/common/http'; import { EventEmitter, Injectable } from '@angular/core'; import { DatePipe } from '@angular/common'; -import { JJService, JJDispute as JJDisputeBase, JJDisputeStatus, JJDisputeRemark, DocumentType, JJDisputeCourtAppearanceRoP } from 'app/api'; +import { JJService, JJDispute as JJDisputeBase, JJDisputeStatus, JJDisputeRemark, DocumentType, JJDisputeCourtAppearanceRoP, DcfTemplateType } from 'app/api'; import { AuthService } from './auth.service'; import { cloneDeep } from "lodash"; import { Store } from '@ngrx/store'; @@ -397,9 +397,9 @@ export class JJDisputeService { return jjDispute; } - public apiJjTicketNumberPrintGet(ticketNumber: string, timeZone: string = Intl.DateTimeFormat().resolvedOptions().timeZone): Observable { + public apiJjTicketNumberPrintGet(ticketNumber: string, type: DcfTemplateType, timeZone: string = Intl.DateTimeFormat().resolvedOptions().timeZone): Observable { return this.http - .get(`/api/jj/${ticketNumber}/print?timeZone=${timeZone}`, { + .get(`/api/jj/${ticketNumber}/print?timeZone=${timeZone}&type=${type}`, { observe: 'response', responseType: 'blob', context: new HttpContext(),