@@ -2,10 +2,11 @@ import * as fs from "node:fs";
22import path from "node:path" ;
33import {
44 $PackSpecification ,
5- $Paper ,
6- $Postage ,
75 PackSpecification ,
86} from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/pack-specification" ;
7+ import { $Postage } from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/postage" ;
8+ import { $Paper } from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/paper" ;
9+ import { Constraint } from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/constraint" ;
910import { Supplier } from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/supplier" ;
1011import { SupplierAllocation } from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/supplier-allocation" ;
1112import { SupplierPack } from "@nhsdigital/nhs-notify-event-schemas-supplier-config/src/domain/supplier-pack" ;
@@ -47,6 +48,19 @@ function formatValue(value: unknown): string {
4748 return escapeHtml ( String ( value ) ) ;
4849}
4950
51+ function formatConstraint ( constraint : Constraint | undefined ) : string {
52+ if ( ! constraint ) return "<em>Not specified</em>" ;
53+ const operatorSymbols : Record < string , string > = {
54+ EQUALS : "=" ,
55+ NOT_EQUALS : "≠" ,
56+ GREATER_THAN : ">" ,
57+ LESS_THAN : "<" ,
58+ } ;
59+ const symbol =
60+ operatorSymbols [ constraint . operator ] || escapeHtml ( constraint . operator ) ;
61+ return `${ symbol } ${ escapeHtml ( constraint . value ) } ` ;
62+ }
63+
5064function sanitizeAnchorId ( text : string ) : string {
5165 return text
5266 . toLowerCase ( )
@@ -87,43 +101,49 @@ function getPackSpecificationStatusTooltip(status: string): string {
87101 return tooltips [ status ] || "" ;
88102}
89103
90- function renderOptionalRow (
91- label : string ,
92- value : unknown ,
93- formatter : ( v : unknown ) => string = ( v ) => escapeHtml ( String ( v ) ) ,
94- tooltip ?: string ,
95- ) : string {
96- if ( value === undefined || value === null ) return "" ;
97- const tooltipAttr = tooltip
98- ? ` data-tooltip="${ escapeHtml ( tooltip ) } " class="has-tooltip"`
99- : "" ;
100- return `<tr><th${ tooltipAttr } >${ label } </th><td>${ formatter ( value ) } </td></tr>` ;
101- }
102-
103104function renderConstraintsSection (
104105 constraints : PackSpecification [ "constraints" ] ,
105106) : string {
106107 // Get the Constraints schema from PackSpecification
107108 const constraintsSchema = $PackSpecification . shape . constraints ;
108- const unwrapped = constraintsSchema . unwrap ( ) . shape ;
109-
110- const maxSheetsTooltip = unwrapped . maxSheets . meta ( ) ?. description ;
111- const deliveryDaysTooltip = unwrapped . deliveryDays . meta ( ) ?. description ;
112- const blackCoverageTooltip = unwrapped . blackCoveragePercentage . meta ( ) ?. description ;
113- const colourCoverageTooltip = unwrapped . colourCoveragePercentage . meta ( ) ?. description ;
114-
115- const maxSheetsHeader = maxSheetsTooltip ? ` data-tooltip="${ escapeHtml ( maxSheetsTooltip ) } " class="has-tooltip"` : "" ;
116- const deliveryDaysHeader = deliveryDaysTooltip ? ` data-tooltip="${ escapeHtml ( deliveryDaysTooltip ) } " class="has-tooltip"` : "" ;
117- const blackCoverageHeader = blackCoverageTooltip ? ` data-tooltip="${ escapeHtml ( blackCoverageTooltip ) } " class="has-tooltip"` : "" ;
118- const colourCoverageHeader = colourCoverageTooltip ? ` data-tooltip="${ escapeHtml ( colourCoverageTooltip ) } " class="has-tooltip"` : "" ;
109+ const unwrapped = constraintsSchema . unwrap ( ) ;
110+
111+ const sheetsTooltip = unwrapped . shape . sheets . unwrap ( ) . meta ( ) ?. description ;
112+ const sidesTooltip = unwrapped . shape . sides . unwrap ( ) . meta ( ) ?. description ;
113+ const deliveryDaysTooltip = unwrapped . shape . deliveryDays
114+ . unwrap ( )
115+ . meta ( ) ?. description ;
116+ const blackCoverageTooltip = unwrapped . shape . blackCoveragePercentage
117+ . unwrap ( )
118+ . meta ( ) ?. description ;
119+ const colourCoverageTooltip = unwrapped . shape . colourCoveragePercentage
120+ . unwrap ( )
121+ . meta ( ) ?. description ;
122+
123+ const sheetsHeader = sheetsTooltip
124+ ? ` data-tooltip="${ escapeHtml ( sheetsTooltip ) } " class="has-tooltip"`
125+ : "" ;
126+ const sidesHeader = sidesTooltip
127+ ? ` data-tooltip="${ escapeHtml ( sidesTooltip ) } " class="has-tooltip"`
128+ : "" ;
129+ const deliveryDaysHeader = deliveryDaysTooltip
130+ ? ` data-tooltip="${ escapeHtml ( deliveryDaysTooltip ) } " class="has-tooltip"`
131+ : "" ;
132+ const blackCoverageHeader = blackCoverageTooltip
133+ ? ` data-tooltip="${ escapeHtml ( blackCoverageTooltip ) } " class="has-tooltip"`
134+ : "" ;
135+ const colourCoverageHeader = colourCoverageTooltip
136+ ? ` data-tooltip="${ escapeHtml ( colourCoverageTooltip ) } " class="has-tooltip"`
137+ : "" ;
119138
120139 return `
121140 <h4>Constraints</h4>
122141 <table class="details-table">
123- <tr><th${ maxSheetsHeader } >Max Sheets</th><td>${ constraints ?. maxSheets !== undefined ? escapeHtml ( constraints . maxSheets ) : "<em>Not specified</em>" } </td></tr>
124- <tr><th${ deliveryDaysHeader } >Delivery Days</th><td>${ constraints ?. deliveryDays !== undefined ? escapeHtml ( constraints . deliveryDays ) : "<em>Not specified</em>" } </td></tr>
125- <tr><th${ blackCoverageHeader } >Black Coverage (%)</th><td>${ constraints ?. blackCoveragePercentage !== undefined ? escapeHtml ( constraints . blackCoveragePercentage ) : "<em>Not specified</em>" } </td></tr>
126- <tr><th${ colourCoverageHeader } >Colour Coverage (%)</th><td>${ constraints ?. colourCoveragePercentage !== undefined ? escapeHtml ( constraints . colourCoveragePercentage ) : "<em>Not specified</em>" } </td></tr>
142+ <tr><th${ sheetsHeader } >Sheets</th><td>${ formatConstraint ( constraints ?. sheets ) } </td></tr>
143+ <tr><th${ sidesHeader } >Sides</th><td>${ formatConstraint ( constraints ?. sides ) } </td></tr>
144+ <tr><th${ deliveryDaysHeader } >Delivery Days</th><td>${ formatConstraint ( constraints ?. deliveryDays ) } </td></tr>
145+ <tr><th${ blackCoverageHeader } >Black Coverage (%)</th><td>${ formatConstraint ( constraints ?. blackCoveragePercentage ) } </td></tr>
146+ <tr><th${ colourCoverageHeader } >Colour Coverage (%)</th><td>${ formatConstraint ( constraints ?. colourCoveragePercentage ) } </td></tr>
127147 </table>
128148 ` ;
129149}
@@ -168,12 +188,29 @@ function renderPaperSection(
168188function renderAssemblySection (
169189 assembly : PackSpecification [ "assembly" ] ,
170190) : string {
171- const envelopeId = assembly ?. envelopeId ? escapeHtml ( assembly . envelopeId ) : "<em>Not specified</em>" ;
172- const printColour = assembly ?. printColour ? escapeHtml ( assembly . printColour ) : "<em>Not specified</em>" ;
173- const duplex = assembly ?. duplex !== undefined ? ( assembly . duplex ? "Yes" : "No" ) : "<em>Not specified</em>" ;
174- const features = assembly ?. features && assembly . features . length > 0 ? formatValue ( assembly . features ) : "<em>Not specified</em>" ;
175- const insertIds = assembly ?. insertIds && assembly . insertIds . length > 0 ? formatValue ( assembly . insertIds ) : "<em>Not specified</em>" ;
176- const additional = assembly ?. additional ? `<pre>${ escapeHtml ( JSON . stringify ( assembly . additional , null , 2 ) ) } </pre>` : "<em>Not specified</em>" ;
191+ const envelopeId = assembly ?. envelopeId
192+ ? escapeHtml ( assembly . envelopeId )
193+ : "<em>Not specified</em>" ;
194+ const printColour = assembly ?. printColour
195+ ? escapeHtml ( assembly . printColour )
196+ : "<em>Not specified</em>" ;
197+ const duplex =
198+ assembly ?. duplex === undefined
199+ ? "<em>Not specified</em>"
200+ : assembly . duplex
201+ ? "Yes"
202+ : "No" ;
203+ const features =
204+ assembly ?. features && assembly . features . length > 0
205+ ? formatValue ( assembly . features )
206+ : "<em>Not specified</em>" ;
207+ const insertIds =
208+ assembly ?. insertIds && assembly . insertIds . length > 0
209+ ? formatValue ( assembly . insertIds )
210+ : "<em>Not specified</em>" ;
211+ const additional = assembly ?. additional
212+ ? `<pre>${ escapeHtml ( JSON . stringify ( assembly . additional , null , 2 ) ) } </pre>`
213+ : "<em>Not specified</em>" ;
177214
178215 return `
179216 <h4>Assembly</h4>
@@ -194,9 +231,15 @@ function generatePackDetailsHtml(pack: PackSpecification): string {
194231 const maxWeightTooltip = $Postage . shape . maxWeightGrams . meta ( ) ?. description ;
195232 const maxThicknessTooltip = $Postage . shape . maxThicknessMm . meta ( ) ?. description ;
196233
197- const deliveryDaysHeader = deliveryDaysTooltip ? ` data-tooltip="${ escapeHtml ( deliveryDaysTooltip ) } " class="has-tooltip"` : "" ;
198- const maxWeightHeader = maxWeightTooltip ? ` data-tooltip="${ escapeHtml ( maxWeightTooltip ) } " class="has-tooltip"` : "" ;
199- const maxThicknessHeader = maxThicknessTooltip ? ` data-tooltip="${ escapeHtml ( maxThicknessTooltip ) } " class="has-tooltip"` : "" ;
234+ const deliveryDaysHeader = deliveryDaysTooltip
235+ ? ` data-tooltip="${ escapeHtml ( deliveryDaysTooltip ) } " class="has-tooltip"`
236+ : "" ;
237+ const maxWeightHeader = maxWeightTooltip
238+ ? ` data-tooltip="${ escapeHtml ( maxWeightTooltip ) } " class="has-tooltip"`
239+ : "" ;
240+ const maxThicknessHeader = maxThicknessTooltip
241+ ? ` data-tooltip="${ escapeHtml ( maxThicknessTooltip ) } " class="has-tooltip"`
242+ : "" ;
200243
201244 const versionTooltip = $PackSpecification . shape . version . meta ( ) ?. description ;
202245 const versionHeader = versionTooltip
@@ -222,9 +265,9 @@ function generatePackDetailsHtml(pack: PackSpecification): string {
222265 <table class="details-table">
223266 <tr><th>Postage ID</th><td>${ escapeHtml ( pack . postage . id ) } </td></tr>
224267 <tr><th>Size</th><td>${ escapeHtml ( pack . postage . size ) } </td></tr>
225- <tr><th${ deliveryDaysHeader } >Delivery Days</th><td>${ pack . postage . deliveryDays !== undefined ? escapeHtml ( pack . postage . deliveryDays ) : "<em>Not specified</em>" } </td></tr>
226- <tr><th${ maxWeightHeader } >Max Weight (grams)</th><td>${ pack . postage . maxWeightGrams !== undefined ? escapeHtml ( pack . postage . maxWeightGrams ) : "<em>Not specified</em>" } </td></tr>
227- <tr><th${ maxThicknessHeader } >Max Thickness (mm)</th><td>${ pack . postage . maxThicknessMm !== undefined ? escapeHtml ( pack . postage . maxThicknessMm ) : "<em>Not specified</em>" } </td></tr>
268+ <tr><th${ deliveryDaysHeader } >Delivery Days</th><td>${ pack . postage . deliveryDays === undefined ? "<em>Not specified</em>" : escapeHtml ( pack . postage . deliveryDays ) } </td></tr>
269+ <tr><th${ maxWeightHeader } >Max Weight (grams)</th><td>${ pack . postage . maxWeightGrams === undefined ? "<em>Not specified</em>" : escapeHtml ( pack . postage . maxWeightGrams ) } </td></tr>
270+ <tr><th${ maxThicknessHeader } >Max Thickness (mm)</th><td>${ pack . postage . maxThicknessMm === undefined ? "<em>Not specified</em>" : escapeHtml ( pack . postage . maxThicknessMm ) } </td></tr>
228271 </table>
229272
230273 ${ renderConstraintsSection ( pack . constraints ) }
@@ -909,7 +952,10 @@ function generateSupplierHtml(report: SupplierReport): string {
909952</html>` ;
910953}
911954
912- function buildSupplierReports ( data : ParseResult , options : GenerateReportsOptions = { } ) : Map < string , SupplierReport > {
955+ function buildSupplierReports (
956+ data : ParseResult ,
957+ options : GenerateReportsOptions = { } ,
958+ ) : Map < string , SupplierReport > {
913959 const reports = new Map < string , SupplierReport > ( ) ;
914960
915961 // Initialize reports for all suppliers
0 commit comments