diff --git a/app/config/openapi.js b/app/config/openapi.js index 1862ae8..f23f08b 100644 --- a/app/config/openapi.js +++ b/app/config/openapi.js @@ -221,8 +221,12 @@ const purchaseOrderHeaderSchema = { properties: { pohId: { type: 'integer', readOnly: true }, pohDate: { type: 'string', format: 'date-time' }, - pohReference: { type: 'string' }, - pohTerms: { type: 'string' }, + // Lengths mirror purchaseorderheader.schema.js: pohReference is + // 1-255 chars, pohTerms is 1-1000 chars (the longer cap suits + // free-text "net 30, late fees per §2.3, …" payment-terms + // strings). + pohReference: { type: 'string', minLength: 1, maxLength: 255 }, + pohTerms: { type: 'string', minLength: 1, maxLength: 1000 }, pohPovId: { type: 'integer' }, pohArch: { type: 'boolean', readOnly: true }, }, @@ -233,7 +237,10 @@ const purchaseOrderLineSchema = { properties: { polId: { type: 'integer', readOnly: true }, polpoh: { type: 'integer' }, - polItemDesc: { type: 'string' }, + // Mirrors purchaseorderline.schema.js: 1-1000 chars. Same + // free-text rationale as pohTerms above — line items often + // carry SKU + brief description on one line. + polItemDesc: { type: 'string', minLength: 1, maxLength: 1000 }, polQty: { type: 'number' }, polPrice: { type: 'number' }, polInvtId: { type: 'integer' }, diff --git a/tests/api/openapi.test.js b/tests/api/openapi.test.js index 75f3878..d77c889 100644 --- a/tests/api/openapi.test.js +++ b/tests/api/openapi.test.js @@ -70,6 +70,26 @@ describe('OpenAPI spec', () => { expect(schemas.TimeEntry.properties.teStartedAt).toBeDefined(); }); + test('PurchaseOrderHeader pins the validator field-length bounds', async () => { + // Mirrors purchaseorderheader.schema.js. Without these, SDK + // generators expose pohReference/pohTerms as unbounded strings + // and miss the server-side caps. + const res = await request(app).get('/openapi.json'); + const poh = res.body.components.schemas.PurchaseOrderHeader; + expect(poh.properties.pohReference.minLength).toBe(1); + expect(poh.properties.pohReference.maxLength).toBe(255); + expect(poh.properties.pohTerms.minLength).toBe(1); + expect(poh.properties.pohTerms.maxLength).toBe(1000); + }); + + test('PurchaseOrderLine.polItemDesc pins the validator field-length bound', async () => { + // Mirrors purchaseorderline.schema.js — 1..1000 chars. + const res = await request(app).get('/openapi.json'); + const pol = res.body.components.schemas.PurchaseOrderLine; + expect(pol.properties.polItemDesc.minLength).toBe(1); + expect(pol.properties.polItemDesc.maxLength).toBe(1000); + }); + test('TimeEntry.teDescription pins the 10000-char bound from the validator', async () => { // The zod schema (app/schemas/timeentry.schema.js) caps // teDescription at 10000 chars. The OpenAPI component schema