diff --git a/.changeset/customer-portal-client-entity-export.md b/.changeset/customer-portal-client-entity-export.md new file mode 100644 index 00000000..787e750c --- /dev/null +++ b/.changeset/customer-portal-client-entity-export.md @@ -0,0 +1,8 @@ +--- +"@epilot/customer-portal-client": minor +--- + +Update customer-portal export endpoints to the column-config contract (MO-2626) + +- `createExport` (`POST /v1/portal/exports`) — now takes a JSON body with required `schema` and ordered `columns` (new `PortalDataExportColumn` schema: key, localized header, source path/attribute, formatter, enum_labels), plus optional `search`, `expand_over` and `language`. Replaces the earlier draft that only accepted a `language` query param. +- `getExport` (`GET /v1/portal/exports/{jobId}`) — unchanged; poll status (`queued`/`running`/`ready`/`failed`/`expired`) and pick up the short-lived `downloadUrl` when ready. diff --git a/clients/customer-portal-client/src/openapi-runtime.json b/clients/customer-portal-client/src/openapi-runtime.json index 676505e0..8c69a389 100644 --- a/clients/customer-portal-client/src/openapi-runtime.json +++ b/clients/customer-portal-client/src/openapi-runtime.json @@ -131,13 +131,12 @@ "/v1/portal/exports": { "post": { "operationId": "createExport", - "parameters": [ - { - "in": "query", - "name": "language", - "required": false + "requestBody": { + "required": true, + "content": { + "application/json": {} } - ], + }, "responses": {} } }, diff --git a/clients/customer-portal-client/src/openapi.d.ts b/clients/customer-portal-client/src/openapi.d.ts index d98ed745..b445ed38 100644 --- a/clients/customer-portal-client/src/openapi.d.ts +++ b/clients/customer-portal-client/src/openapi.d.ts @@ -1170,6 +1170,12 @@ declare namespace Components { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -1691,6 +1697,12 @@ declare namespace Components { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -6170,6 +6182,12 @@ declare namespace Components { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -6783,6 +6801,12 @@ declare namespace Components { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -7098,6 +7122,63 @@ declare namespace Components { grants?: Grant[]; pages?: Page[]; } + /** + * One column of the portal data export CSV. + */ + export interface PortalDataExportColumn { + /** + * Stable, immutable column id (snake_case). Append-only contract: never rename, reorder semantics, or remove an existing key; new columns are appended. + * + * example: + * vertragsnummer + */ + key: string; + /** + * Localized header label, keyed by language (de, en). + * example: + * { + * "de": "Vertragsnummer", + * "en": "Contract number" + * } + */ + header: { + [name: string]: string; + }; + /** + * Where the value comes from: relation hops from the anchor entity plus the attribute to read on the resolved entity. An empty path means the anchor itself. + * + */ + source: { + /** + * Relation hops from the anchor entity (max 3). + * example: + * [ + * "customer" + * ] + */ + path?: string[]; + /** + * Attribute to read on the resolved entity. + * example: + * customer_number + */ + attribute: string; + /** + * Which part of an address-typed attribute to render. + */ + address_field?: "full" | "street" | "street_number" | "postal_code" | "city" | "additional_info" | "country"; + }; + formatter?: "text" | "date" | "money_cents" | "enum" | "address"; + /** + * Localized value maps for the enum formatter, keyed by language then raw value. + * + */ + enum_labels?: { + [name: string]: { + [name: string]: string; + }; + }; + } /** * ID of the portal * example: @@ -8282,6 +8363,12 @@ declare namespace Components { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -8863,6 +8950,12 @@ declare namespace Components { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -9752,11 +9845,31 @@ declare namespace Paths { } } namespace CreateExport { - namespace Parameters { - export type Language = "de" | "en"; - } - export interface QueryParameters { - language?: Parameters.Language; + export interface RequestBody { + /** + * Entity schema to export (must be an allowed portal entity). + */ + schema: string; + /** + * Search parameters, same shape the entity list queries with. + */ + search?: { + q?: string; + q_fields?: string[]; + filters?: { + [key: string]: any; + }[]; + filters_context?: { + [key: string]: any; + }[]; + sort?: any; + }; + /** + * Ordered column definitions; order is the CSV column order. + */ + columns: /* One column of the portal data export CSV. */ Components.Schemas.PortalDataExportColumn[]; + expand_over?: string; + language?: "de" | "en"; } namespace Responses { export interface $202 { @@ -11915,6 +12028,12 @@ declare namespace Paths { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -12527,6 +12646,12 @@ declare namespace Paths { * true */ require_symbols?: boolean; + /** + * Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan. + * example: + * 3 + */ + password_history_size?: number; }; }; /** @@ -15861,11 +15986,12 @@ export interface OperationMethods { /** * createExport - createExport * - * Request an asynchronous CSV export of the portal user's contracts, delivery points and meters. Returns a job id to poll. + * Request an asynchronous CSV export of the portal user's entities for one schema. Columns come from the request Returns a job id to poll. + * */ 'createExport'( - parameters?: Parameters | null, - data?: any, + parameters?: Parameters | null, + data?: Paths.CreateExport.RequestBody, config?: AxiosRequestConfig ): OperationResponse /** @@ -17563,11 +17689,12 @@ export interface PathsDictionary { /** * createExport - createExport * - * Request an asynchronous CSV export of the portal user's contracts, delivery points and meters. Returns a job id to poll. + * Request an asynchronous CSV export of the portal user's entities for one schema. Columns come from the request Returns a job id to poll. + * */ 'post'( - parameters?: Parameters | null, - data?: any, + parameters?: Parameters | null, + data?: Paths.CreateExport.RequestBody, config?: AxiosRequestConfig ): OperationResponse } @@ -19535,6 +19662,7 @@ export type PageRequest = Components.Schemas.PageRequest; export type PaymentWidget = Components.Schemas.PaymentWidget; export type PortalConfig = Components.Schemas.PortalConfig; export type PortalConfigV3 = Components.Schemas.PortalConfigV3; +export type PortalDataExportColumn = Components.Schemas.PortalDataExportColumn; export type PortalId = Components.Schemas.PortalId; export type PortalUser = Components.Schemas.PortalUser; export type PortalUserRegistrationStatus = Components.Schemas.PortalUserRegistrationStatus; diff --git a/clients/customer-portal-client/src/openapi.json b/clients/customer-portal-client/src/openapi.json index d52c7ea9..90c7371f 100644 --- a/clients/customer-portal-client/src/openapi.json +++ b/clients/customer-portal-client/src/openapi.json @@ -484,25 +484,75 @@ "post": { "operationId": "createExport", "summary": "createExport", - "description": "Request an asynchronous CSV export of the portal user's contracts, delivery points and meters. Returns a job id to poll.", + "description": "Request an asynchronous CSV export of the portal user's entities for one schema. Columns come from the request Returns a job id to poll.\n", "tags": [ "ECP" ], - "parameters": [ - { - "in": "query", - "name": "language", - "required": false, - "schema": { - "type": "string", - "enum": [ - "de", - "en" - ] - }, - "description": "Output language for headers and value formatting. Defaults to German when omitted or unsupported." + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "schema", + "columns" + ], + "properties": { + "schema": { + "type": "string", + "description": "Entity schema to export (must be an allowed portal entity)." + }, + "search": { + "type": "object", + "description": "Search parameters, same shape the entity list queries with.", + "properties": { + "q": { + "type": "string" + }, + "q_fields": { + "type": "array", + "items": { + "type": "string" + } + }, + "filters": { + "type": "array", + "items": { + "type": "object" + } + }, + "filters_context": { + "type": "array", + "items": { + "type": "object" + } + }, + "sort": {} + } + }, + "columns": { + "type": "array", + "description": "Ordered column definitions; order is the CSV column order.", + "items": { + "$ref": "#/components/schemas/PortalDataExportColumn" + } + }, + "expand_over": { + "type": "string" + }, + "language": { + "type": "string", + "enum": [ + "de", + "en" + ] + } + } + } + } } - ], + }, "security": [ { "PortalAuth": [] @@ -540,7 +590,7 @@ "$ref": "#/components/responses/Forbidden" }, "404": { - "description": "No export profile configured for this organization." + "description": "Missing or invalid export columns." }, "500": { "$ref": "#/components/responses/InternalServerError" @@ -12013,6 +12063,13 @@ "type": "boolean", "example": true, "description": "Require symbols" + }, + "password_history_size": { + "type": "integer", + "minimum": 0, + "maximum": 24, + "example": 3, + "description": "Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan." } } } @@ -18207,6 +18264,13 @@ "type": "boolean", "example": true, "description": "Require symbols" + }, + "password_history_size": { + "type": "integer", + "minimum": 0, + "maximum": 24, + "example": 3, + "description": "Number of previous passwords a user is prevented from reusing. Set to 0 to disable reuse prevention. Maps to Cognito's PasswordHistorySize and requires the user pool to be on the Essentials or Plus feature plan." } } } @@ -18523,6 +18587,90 @@ "description": "ID of the portal", "example": "453ad7bf-86d5-46c8-8252-bcc868df5e3c" }, + "PortalDataExportColumn": { + "type": "object", + "description": "One column of the portal data export CSV.", + "required": [ + "key", + "header", + "source" + ], + "properties": { + "key": { + "type": "string", + "description": "Stable, immutable column id (snake_case). Append-only contract: never rename, reorder semantics, or remove an existing key; new columns are appended.\n", + "example": "vertragsnummer" + }, + "header": { + "type": "object", + "description": "Localized header label, keyed by language (de, en).", + "additionalProperties": { + "type": "string" + }, + "example": { + "de": "Vertragsnummer", + "en": "Contract number" + } + }, + "source": { + "type": "object", + "description": "Where the value comes from: relation hops from the anchor entity plus the attribute to read on the resolved entity. An empty path means the anchor itself.\n", + "required": [ + "attribute" + ], + "properties": { + "path": { + "type": "array", + "description": "Relation hops from the anchor entity (max 3).", + "items": { + "type": "string" + }, + "example": [ + "customer" + ] + }, + "attribute": { + "type": "string", + "description": "Attribute to read on the resolved entity.", + "example": "customer_number" + }, + "address_field": { + "type": "string", + "description": "Which part of an address-typed attribute to render.", + "enum": [ + "full", + "street", + "street_number", + "postal_code", + "city", + "additional_info", + "country" + ] + } + } + }, + "formatter": { + "type": "string", + "enum": [ + "text", + "date", + "money_cents", + "enum", + "address" + ] + }, + "enum_labels": { + "type": "object", + "description": "Localized value maps for the enum formatter, keyed by language then raw value.\n", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + } + } + }, "UpsertPortalConfigV3": { "allOf": [ {