From 55facd6d1f1b1289bc387c9749e78e70854bc070 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 28 May 2024 08:48:11 +0530 Subject: [PATCH 01/15] Add mock client generation for the CLI --- .../openapi/cmd/BallerinaCodeGenerator.java | 32 +- .../io/ballerina/openapi/cmd/OpenApiCmd.java | 7 +- .../client/MockClientGenerationTests.java | 60 + .../client/mock/basic_response_example.yaml | 3224 +++++++++++++++++ openapi-cli/src/test/resources/testng.xml | 1 + .../client/AdvanceMockClientGenerator.java | 162 + .../client/BallerinaClientGenerator.java | 12 +- ...aClientGeneratorWithStatusCodeBinding.java | 47 +- .../client/BallerinaMockClientGenerator.java | 148 + .../client/diagnostic/DiagnosticMessages.java | 4 +- .../mock/MockClientFunctionGenerator.java | 110 + .../mock/MockFunctionBodyGenerator.java | 113 + .../mock/MockImplFunctionBodyGenerator.java | 24 + .../client/model/OASClientConfig.java | 12 + openapi-core/src/main/java/module-info.java | 1 + 15 files changed, 3923 insertions(+), 34 deletions(-) create mode 100644 openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java create mode 100644 openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml create mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java create mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java create mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java create mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java create mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java index 1face1c4d..adda01304 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java @@ -20,8 +20,10 @@ import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; +import io.ballerina.openapi.core.generators.client.AdvanceMockClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGeneratorWithStatusCodeBinding; +import io.ballerina.openapi.core.generators.client.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaTestGenerator; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; import io.ballerina.openapi.core.generators.client.exception.ClientException; @@ -98,7 +100,7 @@ public class BallerinaCodeGenerator { public void generateClientAndService(String definitionPath, String serviceName, String outPath, Filter filter, boolean nullable, boolean isResource, boolean generateServiceType, - boolean generateWithoutDataBinding, boolean statusCodeBinding) + boolean generateWithoutDataBinding, boolean statusCodeBinding, boolean isMock) throws IOException, FormatterException, BallerinaOpenApiException, OASTypeGenException, ClientException { Path srcPath = Paths.get(outPath); @@ -134,9 +136,11 @@ public void generateClientAndService(String definitionPath, String serviceName, .withNullable(nullable) .withPlugin(false) .withOpenAPI(openAPIDef) - .withResourceMode(isResource).build(); + .withResourceMode(isResource) + .withMock(isMock).build(); - BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig, statusCodeBinding); + BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig, statusCodeBinding, + isMock); String clientContent = Formatter.format(clientGenerator.generateSyntaxTree()).toSourceCode(); //Update type definition list with auth related type definitions @@ -236,7 +240,8 @@ public void generateClient(String definitionPath, String outPath, Filter filter, Path implPath = getImplPath(srcPackage, srcPath); List genFiles = null; try { - genFiles = generateClientFiles(Paths.get(definitionPath), filter, nullable, isResource, statusCodeBinding); + genFiles = generateClientFiles(Paths.get(definitionPath), filter, nullable, isResource, statusCodeBinding, + true); if (!genFiles.isEmpty()) { writeGeneratedSources(genFiles, srcPath, implPath, GEN_CLIENT); } @@ -357,7 +362,7 @@ private void writeGeneratedSources(List sources, Path srcPath, Path * @throws IOException when code generation with specified templates fails */ private List generateClientFiles(Path openAPI, Filter filter, boolean nullable, boolean isResource, - boolean statusCodeBinding) + boolean statusCodeBinding, boolean isMock) throws IOException, BallerinaOpenApiException, FormatterException, ClientException { if (srcPackage == null || srcPackage.isEmpty()) { srcPackage = DEFAULT_CLIENT_PKG; @@ -385,12 +390,13 @@ private List generateClientFiles(Path openAPI, Filter filter, boolea .withOpenAPI(openAPIDef) .withResourceMode(isResource) .withStatusCodeBinding(statusCodeBinding) + .withMock(isMock) .build(); //Take default DO NOT modify licenseHeader = licenseHeader.isBlank() ? DO_NOT_MODIFY_FILE_HEADER : licenseHeader; TypeHandler.createInstance(openAPIDef, nullable); BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig, - statusCodeBinding); + statusCodeBinding, isMock); String mainContent = Formatter.format(clientGenerator.generateSyntaxTree()).toSourceCode(); //Update type definition list with auth related type definitions List authNodes = clientGenerator.getBallerinaAuthConfigGenerator() @@ -440,11 +446,17 @@ private List generateClientFiles(Path openAPI, Filter filter, boolea } private static BallerinaClientGenerator getBallerinaClientGenerator(OASClientConfig oasClientConfig, - boolean statusCodeBinding) { - if (!statusCodeBinding) { - return new BallerinaClientGenerator(oasClientConfig); + boolean statusCodeBinding, boolean isMock) { + if (statusCodeBinding && isMock) { + return new AdvanceMockClientGenerator(oasClientConfig); + } + if (statusCodeBinding) { + return new BallerinaClientGeneratorWithStatusCodeBinding(oasClientConfig); + } + if (isMock) { + return new BallerinaMockClientGenerator(oasClientConfig); } - return new BallerinaClientGeneratorWithStatusCodeBinding(oasClientConfig); + return new BallerinaClientGenerator(oasClientConfig); } diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java index 048c61628..9b28eb3ad 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java @@ -121,6 +121,11 @@ public class OpenApiCmd implements BLauncherCmd { description = "Generate service without data binding") private boolean generateWithoutDataBinding; + @CommandLine.Option(names = {"--mock"}, hidden = true, + description = "Generate service without data binding") + private boolean mock; + + @CommandLine.Parameters private List argList; @@ -450,7 +455,7 @@ private void generateBothFiles(BallerinaCodeGenerator generator, String fileName assert resourcePath != null; generator.generateClientAndService(resourcePath.toString(), fileName, targetOutputPath.toString(), filter, baseCmd.nullable, generateClientResourceFunctions, generateServiceType, generateWithoutDataBinding, - statusCodeBinding); + statusCodeBinding, mock); } catch (BallerinaOpenApiException e) { outStream.println(e.getMessage()); exitError(this.exitWhenFinish); diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java new file mode 100644 index 000000000..c7b310fa1 --- /dev/null +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java @@ -0,0 +1,60 @@ +package io.ballerina.openapi.generators.client; + +import io.ballerina.compiler.syntax.tree.FunctionBodyNode; +import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator; +import io.ballerina.openapi.core.generators.common.TypeHandler; +import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import static io.ballerina.openapi.generators.common.GeneratorTestUtils.getOpenAPI; + +public class MockClientGenerationTests { + private static final Path RES_DIR = Paths.get("src/test/resources/generators/client/mock").toAbsolutePath(); + @Test + public void mockClientTest() throws IOException, BallerinaOpenApiException { + Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); + OpenAPI openapi = getOpenAPI(definitionPath); + TypeHandler.createInstance(openapi, false); + String path = "/api/v1/payment_run_schedules"; + Set> pathItem = openapi.getPaths().get(path). + readOperationsMap().entrySet(); + Iterator> iterator = pathItem.iterator(); + Map.Entry operation = iterator.next(); + + MockFunctionBodyGenerator mockFunctionBodyGenerator = new MockFunctionBodyGenerator(path, operation, openapi, + false); + Optional functionBodyNode = mockFunctionBodyGenerator.getFunctionBodyNode(); + FunctionBodyNode body = functionBodyNode.get(); + String string = body.toString(); + } + + @Test + public void mockClientTestWithReferenceExample() throws IOException, BallerinaOpenApiException { + Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); + OpenAPI openapi = getOpenAPI(definitionPath); + TypeHandler.createInstance(openapi, false); + String path = "/api/v1/payment_run_schedules"; + Set> pathItem = openapi.getPaths().get(path). + readOperationsMap().entrySet(); + Iterator> iterator = pathItem.iterator(); + Map.Entry operation = iterator.next(); + + MockFunctionBodyGenerator mockFunctionBodyGenerator = new MockFunctionBodyGenerator(path, operation, openapi, + false); + Optional functionBodyNode = mockFunctionBodyGenerator.getFunctionBodyNode(); + FunctionBodyNode body = functionBodyNode.get(); + String string = body.toString(); + + } +} diff --git a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml new file mode 100644 index 000000000..4bc4ef534 --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml @@ -0,0 +1,3224 @@ +openapi: 3.0.0 +info: + version: 2021-08 + title: 'API Reference: Collections' + x-logo: + url: >- + https://www.zuora.com/wp-content/uploads/2016/10/zuora-dev-logo-api-ref.svg + description: > + This is a generated connector for [Zuora Collections API V1](https://www.zuora.com/developer/collect-api/#) OpenAPI specification. + + This reference provides detailed descriptions about functions, requests, and responses of + the APIs for the following two component apps. Rest APIs for other component + apps will be included in this reference when they are released. + + - Advanced Payment Manager + + - Collections Window + + - Configurable Payment Retry + + - Statement Generator + x-ballerina-init-description: > + The connector initialization requires setting the API credentials. + + Create a [Zuora account](https://www.zuora.com/) and obtain tokens by following [this guide](https://www.zuora.com/developer/collect-api/#section/Authentication). + x-ballerina-display: + label: Zuora Collection + iconPath: "icon.png" +tags: + - name: Advanced Payment Manager + description: > + Advanced Payment Manager APIs use basic authentication. The user name is + the email address that you use for logging in Zuora. The password is the + API token that is shown in the settings of Advanced Payment Manager. + + Before you use the APIs, ensure that you have completed the initial + configurations of Advanced Payment Manager. To learn more about the + configuration and usage of Advanced Payment Manager, see [Advanced Payment + Manager](https://knowledgecenter.zuora.com/CE_Collect/CA_Advanced_Payment_Manager). + - name: Collections Window + description: > + Collections Window APIs use basic authentication. The user name is the + email address that you use for logging in Zuora. The password is the API + token that is shown in the settings of Collections Window. + + To learn more about the configuration and usage of Collections Window, see + [Collections + Window](https://knowledgecenter.zuora.com/CE_Collect/Collections_Window). + - name: Configurable Payment Retry + description: > + Configurable Payment Retry APIs use basic authentication. The user name is + the email address that you use for logging in Zuora. The password is the + API token that is shown in the settings of Configurable Payment Retry. + + To learn more about the configuration and usage of Configurable Payment + Retry, see [Configurable Payment + Retry](https://knowledgecenter.zuora.com/CE_Collect/Configurable_Payment_Retry). + - name: Notes + description: > + Notes APIs use API-token only for authentication. You need to use + "API-Token" as the header key and the api token that is shown in the + Setting of Notes as the value. + + To learn more about the configuration and usage of Notes, see + [Notes](https://knowledgecenter.zuora.com/CE_Collect/Notes). + - name: Statement Generator + description: > + + Statement Generator APIs use basic authentication. The user name is the + email address that you use for logging in Zuora. The password is the API + token that is shown in the settings of Statement Generator. + + To learn more about the configuration and usage of Statement Generator, + see [Statement + Generator](https://knowledgecenter.zuora.com/CE_Collect/Statement_Generator). + description: The number of accounts that have paid in full. +security: + - BasicAuth: [] +paths: + /api/v1/subscription_payment_runs/{payment_run_id}: + get: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: getPaymentRun + summary: Get a payment run + description: > + Gets details about a particular payment run based on a payment run id in + Advanced Payment Manager. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: payment_run_id + required: true + schema: + type: integer + description: >- + The payment run ID. A payment run id in Advanced Payment Manager is + different from a payment run id in Zuora. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETPaymentRunResponse' + examples: + response: + value: + success: true + id: 6 + status: Complete + target_date: 2018-01-02T00:00:00.000Z + filter: Account.Currency = 'CAD' + payment_run_schedule_id: Adhoc + invoices_held: {} + metrics: + documents: 0 + payments: 0 + failed: 0 + skipped: 0 + amount: 0 + credit: 0 + /api/v1/subscription_payment_runs: + post: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + description: > + Creates a payment run to be executed immediately. You must specify the + **target_date** field. You can specify one or more filters to determine + which receivables are to be paid in the payment run. + + + If you use a custom filter, you cannot use other filters. + summary: Create a payment run + operationId: createPaymentRun + tags: + - Advanced Payment Manager + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRun' + required: true + responses: + '200': + description: '' + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRunResponse' + application/json: + examples: + response: + value: + id: 6 + success: 'true' + /api/v1/payment_run_schedules: + get: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: getPaymentRunSchedules + summary: Get all payment run schedules + description: | + Retrieves all payment run schedules in Advanced Payment Manager. + tags: + - Advanced Payment Manager + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETPaymentRunSchedulesResponse' + examples: + response: + value: + success: true + size: 3 + schedules: + - id: 6 + status: Active + filter: Account.BillCycleDay = 8 + schedule: At 6:00 AM, only on Monday and Tuesday + post: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + description: | + Creates a payment run schedule. + summary: Create a payment run schedule + operationId: createPaymentRunSchedule + tags: + - Advanced Payment Manager + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRunSchedule' + required: true + responses: + '200': + description: '' + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRunScheduleResponse' + application/json: + examples: + response: + value: + id: 6 + success: 'true' + /api/v1/payment_run_schedules/{schedule_id}: + get: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: getPaymentRunSchedule + summary: Get a payment run schedule + description: | + Gets details about a particular payment run schedule. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: schedule_id + required: true + schema: + type: integer + description: The schedule ID + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETPaymentRunScheduleResponse' + examples: + response: + value: + success: true + id: 6 + status: Active + filter: Account.BillCycleDay = 8 + schedule: At 6:00 AM, only on Monday and Tuesday + put: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: updatePaymentRunSchedule + summary: Update a payment run schedule + description: | + Updates details about a particular payment run schedule. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: schedule_id + required: true + schema: + type: integer + description: The schedule ID + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/PUTPaymentRunSchedule' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/POSTPaymentRunScheduleResponse' + examples: + response: + value: + id: 6 + success: true + delete: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: deletePaymentRunSchedule + summary: Cancel a payment run schedule + description: | + Cancels a payment run schedule. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: schedule_id + required: true + schema: + type: integer + description: The schedule ID + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/DELETEPaymentRunScheduleResponse' + examples: + response: + value: + success: true + /api/v1/fetch_statement?statement_number={statement_number}: + get: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: getStatement + summary: Get a statement + description: > + Gets details about a particular statement. The statement will be + available for download in the response. + tags: + - Statement Generator + parameters: + - in: path + name: statement_number + required: true + schema: + type: integer + description: The statement number + responses: + '200': + description: '' + /api/v1/fetch_settings: + get: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: getSettings + summary: Get Statement Generator settings + description: > + Gets several key settings of Statement Generator, including the + available templates, whether Invoice Settlement is enabled on the + tenant, the name of the default template, and the statement cycle being + used. + tags: + - Statement Generator + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETStatementSettingsResponse' + examples: + response: + value: + success: true + templates: + - name: Default Template + - name: Template for end consumers + default_template: Default Template + default_cycle: Month + /api/v1/run: + post: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: createAdhocStatementRun + summary: Create an ad hoc statement run + description: | + Create an ad hoc statement run. + tags: + - Statement Generator + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTAdhocStatementRun' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/POSTAdhocStatementRunResponse' + examples: + response: + value: + success: true + code: 200 + message: Success + statement_number: STA00000008 + /api/v1/execute: + post: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: createCustomStatementRun + summary: Create a custom statement run + description: | + Create a custom statement run. + tags: + - Statement Generator + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTCustomStatementRun' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/POSTCustomStatementRunResponse' + examples: + response: + value: + success: true + code: 200 + message: Success + execution_number: '2' + report_file: + /api/v1/accounts/{account_id}: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getAccount + summary: Get an account + description: | + Gets details about a particular account. + tags: + - Collections Window + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: The account ID. + example: 2c92c0f86680fd090166a578754812bd + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/CollectionAccount' + examples: + response: + value: + name: Testing Account + zuora_id: 2c92c0f863f2b1680163f579b7e705da + in_collections: true + collections_agent: 2018-01-02T00:00:00.000Z + account_currency: CAD + home_currency: USD + amount_due_account_currency: 15540 + amount_due_home_currency: 800.55 + last_open_invoice_date: '2018-06-12' + average_debt_age: 194.4 days + statuses: + In Collections: true + Pending: false + In Dispute: false + Paid In Full: false + /api/v1/accounts: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getAccounts + summary: Get all accounts + description: | + Gets all accounts that are currently or have been in collection. + tags: + - Collections Window + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETCollectionAccountsResponse' + examples: + response: + value: + accounts: + - name: Testing Account + zuora_id: 2c92c0f863f2b1680163f579b7e705da + in_collections: true + collections_agent: 2018-01-02T00:00:00.000Z + account_currency: CAD + home_currency: USD + amount_due_account_currency: 15540 + amount_due_home_currency: 800.55 + last_open_invoice_date: '2018-06-12' + average_debt_age: 194.4 days + statuses: + In Collections: 0 + Pending: 0 + In Dispute: 0 + Paid In Full: 0 + pagination: + page: 1 + page_length: 20 + next_page: >- + https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20 + /api/v1/users/{email}: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getCollectionsAgent + summary: Get a collections agent by email + description: > + Gets details about a collections agent, including the amount in + collections, and the statuses of the accounts that this agent is + assigned to. + tags: + - Collections Window + parameters: + - in: path + name: email + required: true + schema: + type: string + description: The email of the collections agent. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/CollectionAgent' + examples: + response: + value: + name: Testing User + email: test@zuora.com + zuora_identity_id: 2c92c0f96178a7a901619b10f5d12345 + amount_in_collections: 800.55 + accounts: 2 + account_statuses: + In Collections: 1 + Pending: 0 + In Dispute: 1 + Paid In Full: 0 + /api/v1/users: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getCollectionsAgents + summary: Get all collections agents + description: | + Gets the details of all collections agents. + tags: + - Collections Window + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETCollectionAgentsResponse' + examples: + response: + value: + accounts: + - name: Testing User + email: test@zuora.com + zuora_identity_id: 2c92c0f96178a7a901619b10f5d12345 + amount_in_collections: 800.55 + accounts: 2 + account_statuses: + In Collections: 1 + Pending: 0 + In Dispute: 1 + Paid In Full: 0 + pagination: + page: 1 + page_length: 20 + next_page: >- + https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20 + /api/v1/collections_info: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getCollectionsInfo + summary: Get an overview of collections + description: | + Gets an overview of the collections. + tags: + - Collections Window + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/CollectionsInfo' + examples: + response: + value: + accounts_in_collections: 24 + home_currency: USD + total_debt: '8379.78' + largest_debts: + - Test Account - 12438.00 USD + - Jimmy John - 8000.00 USD + - James Smith - 2450.55 USD + - Bob Roberts - 1000.00 USD + - Jim Reynolds - 829.00 USD + oldest_debts: + - Test Account - 2662 days + - Jimbo - 1494 days + - Steve Smith - 942 days + - Jason Williams - 678 days + - Will Jasons - 365 days + statuses: + In Collections: 24 + Pending: 2 + In Dispute: 5 + Paid in Full: 0 + /api/v1/accounts/{account_id}/update_status: + post: + servers: + - url: https://collections-window.apps.zuora.com + operationId: UpdateAccount + summary: Update account status + description: > + Updates the status of an account. You must use the two query parameters + to specify the status that you want to update, and the new value of the + status. + tags: + - Collections Window + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: The account ID. + example: 2c92c0f86680fd090166a578754812bd + - in: query + name: status + required: true + schema: + type: string + description: The status that you want to update for the specified account. + example: in_dispute + - in: query + name: value + schema: + type: boolean + description: >- + The new value of the status. 0 indicates false, while 1 indicates + true. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Whether the operation is successful. + examples: + response: + value: + success: true + /api/v1/accounts/{account_id}/update_agent: + post: + servers: + - url: https://collections-window.apps.zuora.com + operationId: UpdateAccountAgent + summary: Update account agent + description: > + Updates the collections agent that is displayed within the UI of + Collections Window, and the custom field for the agent displayed in + account details in the Zuora UI. + tags: + - Collections Window + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: The account ID. + example: 2c92c0f86680fd090166a578754812bd + - in: query + name: agent_email + required: true + schema: + type: string + description: The email of the agent. + example: jdoe@company.com + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Whether the operation is successful. + examples: + response: + value: + success: true + /api/v1/payments/active_invoice_cycle_information/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getActiveInvoiceCycle + summary: Get active retry cycles for an invoice + description: > + Gets information of active retry cycles that have not been completed for + an invoice in Configurable Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETActiveInvoiceCycleResponse' + /api/v1/payments/active_debit_memo_cycle_information/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getActiveDebitMemoCycle + summary: Get active retry cycles for a debit memo + description: > + Gets information of active retry cycles that have not been completed for + a debit memo in Configurable Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETActiveDebitMemoCycleResponse' + /api/v1/payments/active_account_cycle_information/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getActiveAccountCycle + summary: Get active retry cycles for an account + description: > + Gets information of active retry cycles that have not been completed for + an account in Configurable Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETActiveAccountCycleResponse' + /api/v1/payments/invoice_cycle_history/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getInvoiceCycleHistory + summary: Get retry cycle history for an invoice + description: > + Gets information of all retry cycles for an invoice in Configurable + Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETInvoiceCycleHistoryResponse' + /api/v1/payments/debit_memo_cycle_history/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getDebitMemoCycleHistory + summary: Get retry cycle history for a debit memo + description: > + Gets information of all retry cycles for a debit memo in Configurable + Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETDebitMemoCycleHistoryResponse' + /api/v1/payments/account_cycle_history/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getAccountCycleHistory + summary: Get retry cycle history for an account + description: > + Gets information of all retry cycles for an account in Configurable + Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETAccountCycleHistoryResponse' + /api/v1/payments/execute_invoice_payment/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: executeExecuteInvoicePayment + summary: Execute invoice payment + description: > + For all active retry cycles associated with an invoice, schedules the + next payment retry attempt to occur in the next hourly payment processor + run. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [290, 291] + /api/v1/payments/execute_debit_memo_payment/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: executeExecuteDebitMemoPayment + summary: Execute debit memo payment + description: > + For all active retry cycles associated with a debit memo, schedules the + next payment retry attempt to occur in the next hourly payment processor + run. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [300] + /api/v1/payments/execute_account_payments/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: executeExecuteAccountPayments + summary: Execute account payments + description: > + For all active retry cycles associated with an account, schedules the + next payment retry attempt to occur in the next hourly payment processor + run. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [310, 311, 312] + /api/v1/payments/execute_payments: + post: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: UpdateExecutePayments + summary: Execute payments + description: > + For all active retry cycles associated with the invoice, debit memo, + and/or account IDs provided, schedules the next payment retry attempt to + occur in the next hourly payment processor run. + tags: + - Configurable Payment Retry + requestBody: + content: + application/json: + schema: + type: object + properties: + account_ids: + type: array + items: + type: string + description: IDs of accounts. + debit_memo_ids: + description: IDs of debit memos. + type: array + items: + type: string + invoice_ids: + type: array + items: + type: string + description: IDs of invoices. + example: + account_ids: + - 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_ids: + - 2c92c0fa7853052701785a38c6622473 + - 2c92c0fa7849b40a01784bc5de0f760f + debit_memo_ids: + - 2c92c0fa7853052701785a38f3bb267f + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [100, 101, 110, 111, 121] + /api/v1/payments/remove_invoice_from_retry_cycle/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: removeRemoveInoviceFromCycle + summary: Remove an invoice from retry cycle + description: | + Stops any active retry cycles associated with the invoice provided. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs have been removed from the + retry cycle: [290, 291] + /api/v1/payments/remove_debit_memo_from_retry_cycle/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: removeDebitMemoFromCycle + summary: Remove a debit memo from retry cycle + description: | + Stops any active retry cycles associated with the debit memo provided. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs have been removed from the + retry cycle: [301] + /api/v1/payments/remove_account_from_retry_cycle/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: removeAccountFromCycle + summary: Remove an account from retry cycle + description: | + Stops any active retry cycles associated with the account provided. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs have been removed from the + retry cycle: [310, 311, 312] + /api/v1/payments/submit_failed_payment: + post: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: UpdateSubmitPaymentToCycle + summary: Submit a payment to retry cycle + description: > + Submit a failed payment into the retry cycle of Configurable Payment + Retry. + tags: + - Configurable Payment Retry + requestBody: + content: + application/json: + schema: + type: object + properties: + payment_id: + type: string + description: ID of a failed payment. + example: + payment_id: 2c92c0867849d42301784bc9ce806c31 + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: Payment entered into retry process + /api/v1/metrics/baseline: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getBaselineMetrics + summary: Get baseline metrics + description: > + Gets baseline metrics for Configurable Payment Retry, including Retry + Success Rate and trend, Document Success Rate and trend, and Average + Days Outstanding and trend. See Response Schema for detailed + descriptions of the metrics. + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETBaselineMetricsResponse' + /api/v1/metrics/amount_recovered: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getAmountRecovered + summary: Get the Amount Recovered metrics + description: > + Gets the Amount Recovered metrics, including the total amount recovered + and the amount recovered over the last 30 days broken down by currency. + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETAmountRecoveredResponse' + /api/v1/metrics/customer_group_over_time: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getDocumentSuccessRateByCustomerGroup + summary: Get the Document Success Rate metrics by customer group + description: > + Gets the Document Success Rate timeseries for each customer group over + the past 6 months. The data of the current month will not be included. + For example, if it is April 15th today, the data for April will not be + included. Data for March and earlier will be shown. + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: >- + #/components/schemas/GETDocumentSuccessRateByCustomerGroupResponse + /api/v1/metrics/customer_group: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getCustomerGroupMetrics + summary: Get the Customer Group metrics + description: > + Gets the following metrics for each customer group that is in the active + status: + - Document Success Rate and trend + - Retry Success Rate + - Average Attempts + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETCustomerGroupMetricsResponse' +components: + schemas: + Customer_Groups: + type: object + properties: + id: + type: integer + name: + type: string + smart_retry: + type: string + document_success_rate: + type: string + document_success_rate_trend: + type: string + retry_success_rate: + type: string + average_attempts: + type: string + Customer_Groups_Detail: + type: array + items: + type: string + + GETCustomerGroupMetricsResponse: + type: object + properties: + customer_groups: + type: array + items: + $ref: '#/components/schemas/Customer_Groups' + description: > + An array containing the following information for each customer + group. + - Customer group ID + - Customer group name + - Whether Smart Retry is enabled for this customer group + - Document Success Rate indicating the percentage of billing documents that are successfully collected + - The trend of change in Document Success Rate over the last 30 days + - Retry Success Rate indicating the percentage of the successful payment attempts + - Average Attempts indicating the average number of attempts required to recover funds + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + customer_groups: + - id: 1 + name: batch22 + smart_retry: false + document_success_rate: '17.17' + document_success_rate_trend: up + retry_success_rate: '21.76' + average_attempts: '4.11' + - id: 2 + name: Smart Retry + smart_retry: true + document_success_rate: '74.17' + document_success_rate_trend: down + retry_success_rate: '81.21' + average_attempts: '1.32' + - id: 4 + name: All Remaining Customers + smart_retry: false + document_success_rate: '16.35' + document_success_rate_trend: up + retry_success_rate: '15.21' + average_attempts: '3.32' + success: true + GETDocumentSuccessRateByCustomerGroupResponse: + type: object + properties: + customer_groups: + type: array + items: + $ref: '#/components/schemas/Customer_Groups_Detail' + description: > + An array containing the Document Success Rate timeseries for each + customer group represented by the customer group ID. + + A timeseries over the past 6 months is present in the format of + `: `. The data of the current + month is not included. For example, if it is April 15th today, the + data for April will not be included. Data for March and earlier will + be shown. + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + customer_groups: + '1': + '05_21': '17.53' + '04_21': '13.21' + '03_21': '14.92' + '02_21': '8.99' + '01_21': '34.25' + '12_20': '12.30' + '2': + '05_21': '11.11' + '04_21': '7.87' + '03_21': '26.00' + '02_21': '11.06' + '01_21': '13.43' + '12_20': '17.92' + '4': + '05_21': '11.13' + '04_21': '9.17' + '03_21': '17.20' + '02_21': '19.06' + '01_21': '12.43' + '12_20': '15.92' + success: true + GETAmountRecoveredResponse: + type: object + properties: + currency: + type: array + items: + type: string + description: > + An array containing the following information for each available + currency. + + If no payment of a given currency has been processed over the last + 30 days, the currency will not appear in the array. + - The total amount recovered to date + - The amount recovered over the last 30 days + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + currency: + USD: + total_amount: '77515.21' + last_30_days: '1100.01' + EUR: + total_amount: '337.19' + last_30_days: '17.17' + CAD: + total_amount: '123954.10' + last_30_days: '5132.87' + success: true + GETBaselineMetricsResponse: + type: object + properties: + retry_success_rate: + type: number + description: > + The percentage of successful payment attempts for all customer + groups on this Configurable Payment Retry instance so far. + + + Retry Success Rate = Number of successful retry payment attempts / + Total number of retry payments attempted + + + Payment attempts here are any payment attempts executed by + Configurable Payment Retry, excluding the initial payment run. + retry_success_rate_trend: + type: string + description: | + The trend of change in Retry Success Rate over the last 30 days. + document_success_rate: + type: number + description: > + The percentage of billing documents that are successfully collected, + for all customer groups on this Configurable Payment Retry instance + so far. + + + Document Success Rate = Number of billing documents collected / + Total number of billing documents attempted + + + Billing documents collected are any invoices and debit memos that + were paid through the payment attempt initiated by Configurable + Payment Retry. + document_success_rate_trend: + type: string + description: | + The trend of change in Document Success Rate over the last 30 days. + average_days_outstanding: + type: number + description: > + The average number of days invoices and debit memos are unpaid + before collection, for all customer groups on this Configurable + Payment Retry instance so far. + average_days_outstanding_trend: + type: string + description: > + The trend of change in Average Days Outstanding over the last 30 + days. + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + retry_success_rate: '11.90' + retry_success_rate_trend: down + document_success_rate: '13.54' + document_success_rate_trend: neutral + average_days_outstanding: '4.76' + average_days_outstanding_trend: up + success: true + GETActiveInvoiceCycleResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETInvoiceCycleElementResponse' + description: > + An array containing information of all active retry cycles for an + invoice. See the schema and example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 + invoice_id: 2c92c0f8778bf8cd017798168cb50e0b + payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 + currency: USD + status: Cycle Incomplete + current_attempt_number: 2 + next_attempt: '2021-04-01T19:27:34.648Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ca076c21 + time_of_execution: '2021-03-19T18:42:20.103Z' + source: PR-00000371 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-04-01T19:27:34.648-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c09c7849d3c101784bce0d0a06d5 + time_of_execution: '2021-03-19T18:52:24.137Z' + source: PR-00000372 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-19T09:53:39.845-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETInvoiceCycleElementResponse: + type: object + title: retry cycle object + properties: + account_id: + type: string + description: | + The ID of the customer account. + invoice_id: + type: string + description: | + The ID of the invoice. + payment_method_id: + type: string + description: | + The ID of the payment method. + currency: + type: string + description: | + The type of the currency used. + status: + type: string + description: | + The status of the retry cycle. + current_attempt_number: + type: number + description: | + The number of the current retry attempt. + next_attempt: + type: string + format: date-time + description: > + The date and time of the next retry attempt, in `yyyy-mm-dd + hh:mm:ss` format. + customer_group: + type: string + description: | + The name of the customer group. + attempts: + type: array + description: > + An array containing information of the retry attempts that have been + made. See the schema and example for details. + items: + $ref: '#/components/schemas/GETCycleElementAttemptResponse' + GETCycleElementAttemptResponse: + type: object + title: retry attempt object + properties: + attempt_number: + type: number + description: | + The number of the retry attempt. + zuora_payment_id: + type: string + description: | + The ID of the payment in Zuora Payments. + time_of_execution: + type: string + format: date-time + description: > + The date and time when the retry attempt was made, in `yyyy-mm-dd + hh:mm:ss` format. + source: + type: string + description: | + The number of the failed payment run. + cpr_generated: + type: boolean + description: > + Indicates whether the first retry attempt was generated by + Configurable Payment Retry. + + + `true` for the cases of the first retry attempt generated by CPR and + the second or later attempt. + + + `false` for the cases that the retry attempt was made by the payment + run or an external source during retry cycles. + success: + type: boolean + description: | + Indicates whether the retry attempt is successful. + amount_collected: + type: number + description: | + The amount collected in this retry attempt. + action_info: + type: object + description: | + Information about the action of the retry attempt. + properties: + action: + type: string + description: | + The action taken in the retry attempt. + retry_info: + type: object + description: | + Information about the next retry attempt. + properties: + next: + type: string + format: date-time + description: > + The date and time of the next retry attempt as determined by + `criteria`, in `yyyy-mm-dd hh:mm:ss` format. + criteria: + type: string + description: > + The criteria defined in the retry configuration in the CPR UI, + to specify whether the next retry will occur in an incremental + time or at a specific time or day. + mapping_info: + type: object + description: | + Information about the response code mapping for the retry attempt. + properties: + label: + type: string + description: > + The response code label, can be `Hard Decline`, `Soft Decline`, + `System Error`, or custom labels. + level: + type: string + description: > + The response code level for the payment gateway, can be `Code` + or `Description`. + customer_group_id: + type: number + description: | + The ID of the customer group. + gateway_info: + type: object + description: | + Information about the payment gateway. + properties: + id: + type: string + description: | + The ID of the payment gateway. + code: + type: string + description: | + The response code from the gateway. + response: + type: string + description: | + The response message from the gateway. + GETActiveDebitMemoCycleResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETDebitMemoCycleElementResponse' + description: > + An array containing information of all active retry cycles for a + debit memo. See the schema and example for details. + example: + cycles: + - account_id: 2c92c0f868e161e70168e25eb51d755f + debit_memo_id: 2c92c0fa7853052701785a38f3bb267f + payment_method_id: 2c92c0f8774f1afe01775f6e533c4c06 + currency: USD + status: Cycle Incomplete + current_attempt_number: 2 + next_attempt: '2021-04-01T10:22:57.464Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a51af791979 + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:30.380-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c0857881cf3e01788ee263b0331c + time_of_execution: '2021-04-01T19:21:55.207Z' + source: PR-00000380 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-04-01T10:22:57.464-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETDebitMemoCycleElementResponse: + type: object + title: retry cycle object + properties: + account_id: + type: string + description: | + The ID of the customer account. + debit_memo_id: + type: string + description: | + The ID of the debit memo. + payment_method_id: + type: string + description: | + The ID of the payment method. + currency: + type: string + description: | + The type of the currency used. + status: + type: string + description: | + The status of the retry cycle. + current_attempt_number: + type: number + description: | + The number of the current retry attempt. + next_attempt: + type: string + format: date-time + description: > + The date and time of the next retry attempt, in `yyyy-mm-dd + hh:mm:ss` format. + customer_group: + type: string + description: | + The name of the customer group. + attempts: + type: array + description: > + An array containing information of the retry attempts that have been + made. See the schema and example for details. + items: + $ref: '#/components/schemas/GETCycleElementAttemptResponse' + GETActiveAccountCycleResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETAccountCycleElementResponse' + description: > + An array containing information of all active retry cycles for an + account. See the schema and example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 + debit_memo_id: 2c92c0fb78532b0001785a38f6427976 + payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 + currency: USD + status: Cycle Incomplete + current_attempt_number: 1 + next_attempt: '2021-04-01T19:27:34.473Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a5199a6192d + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:27.521-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 + invoice_id: 2c92c0fa7853052701785a38c6622473 + payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 + currency: USD + status: Cycle Incomplete + current_attempt_number: 1 + next_attempt: '2021-04-01T19:27:34.436Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a519d85193b + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:28.161-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETAccountCycleElementResponse: + type: object + title: retry cycle object + properties: + account_id: + type: string + description: | + The ID of the customer account. + invoice_id: + type: string + description: | + The ID of the invoice. + debit_memo_id: + type: string + description: | + The ID of the debit memo. + payment_method_id: + type: string + description: | + The ID of the payment method. + currency: + type: string + description: | + The type of the currency used. + status: + type: string + description: | + The status of the retry cycle. + current_attempt_number: + type: number + description: | + The number of the current retry attempt. + next_attempt: + type: string + format: date-time + description: > + The date and time of the next retry attempt, in `yyyy-mm-dd + hh:mm:ss` format. + customer_group: + type: string + description: | + The name of the customer group. + attempts: + type: array + description: > + An array containing information of the retry attempts that have been + made. See the schema and example for details. + items: + $ref: '#/components/schemas/GETCycleElementAttemptResponse' + GETInvoiceCycleHistoryResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETInvoiceCycleElementResponse' + description: > + An array containing information of all completed retry cycles for an + invoice. See the example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Complete + current_attempt_number: 1 + next_attempt: null + customer_group: Testing Group + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 + time_of_execution: '2021-04-01T19:11:21.639Z' + source: PR-00000370 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 5 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Complete + current_attempt_number: 2 + next_attempt: null + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 + time_of_execution: '2021-03-19T18:42:20.103Z' + source: PR-00000371 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-19T09:43:28.670-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c09c7849d3c101784bcdfc010671 + time_of_execution: '2021-03-19T18:52:24.137Z' + source: PR-00000372 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETDebitMemoCycleHistoryResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETDebitMemoCycleElementResponse' + description: > + An array containing information of all completed retry cycles for a + debit memo. See the example for details. + example: + cycles: + - account_id: 2c92c0f868e161e70168e25eb51d755f + debit_memo_id: 2c92c0fa7853052701785a38f3bb267f + payment_method_id: 2c92c0f8774f1afe01775f6e533c4c06 + currency: USD + status: Cycle Complete + current_attempt_number: 2 + next_attempt: null + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a51af791979 + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:30.380-09:00' + criteria: incremental_time + api_updated_retry_time: '2021-03-26T14:27:21.107-04:00' + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c0857881cf3e01788ee263b0331c + time_of_execution: '2021-04-01T19:21:55.207Z' + source: PR-00000378 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETAccountCycleHistoryResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETAccountCycleElementResponse' + description: > + An array containing information of all completed retry cycles for an + account. See the example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Complete + current_attempt_number: 3 + next_attempt: '2021-03-19T18:53:39.641Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 + time_of_execution: '2021-03-19T18:42:20.103Z' + source: PR-00000371 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-19T09:43:28.670-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c09c7849d3c101784bcdfc010671 + time_of_execution: '2021-03-19T18:52:24.137Z' + source: PR-00000372 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fb78532b0f01785a38cede190a + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Incomplete + current_attempt_number: 1 + next_attempt: '2021-03-24T19:34:20.254Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a51aae41969 + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:30.316-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETPaymentRunResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + id: + type: integer + description: | + The ID of the payment run in Advanced Payment Manager. + status: + type: string + description: | + The status of the payment run. + target_date: + type: string + format: date + description: | + The target date of the payment run, in the format of YYYY-MM-DD. + filter: + type: string + description: | + The filter that is used for the payment run. + payment_run_schedule_id: + type: string + description: > + The ID of the payment run schedule. If this is not a scheduled + payment run, the value is **Adhoc**. + invoices_held: + type: object + description: | + Invoices that are held by the payment run for manual processing. + metrics: + type: object + description: | + Metrics of the payment runs after completion. + errors: + type: array + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + items: {} + POSTPaymentRun: + type: object + properties: + target_date: + type: string + format: date + description: > + The target date of the payment run to be created, in the format of + YYYY-MM-DD. + billrun: + type: string + description: > + A bill run name that is used to determine what receivables should be + included in the payment run. Valid only if the custom filter is not + used. + batch: + type: string + description: > + A batch name that is used to determine what receivables should be + included in the payment run. Valid only if the custom filter is not + used. + currency: + type: string + description: > + A three-character currency code that is used to determine what + receivables should be included in the payment run. Valid only if the + custom filter is not used. + payment_gateway: + type: string + description: > + A payment gateway name that is used to determine what receivables + should be included in the payment run. Valid only if the custom + filter is not used. + bill_cycle_day: + type: string + description: > + A bill cycle day value that is used to determine what receivables + should be included in the payment run. Valid only if the custom + filter is not used. + custom: + type: string + description: > + A custom ZOQL query that is used to determine what receivables + should be included in the payment run. It cannot be used with other + filters. + example: + target_date: '2019-02-04' + currency: CAD + POSTPaymentRunResponse: + type: object + properties: + id: + type: integer + description: | + The ID of the payment run in Advanced Payment Manager. + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + items: + type: string + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + GETPaymentRunSchedulesResponse: + type: object + properties: + schedules: + type: array + items: + type: object + description: | + An array containing all available schedules. + size: + type: integer + description: | + The number of schedules retrieved. + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + items: {} + GETPaymentRunScheduleResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + id: + type: integer + description: | + The ID of the payment run schedule in Advanced Payment Manager. + status: + type: string + description: | + The status of the payment run schedule. + filter: + type: string + format: date + description: | + The filter that is defined in the payment run schedule. + schedule: + type: string + description: | + The schedule that is defined for this payment run schedule. + errors: + type: array + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + items: {} + POSTPaymentRunSchedule: + type: object + properties: + frequency: + type: string + description: | + The frequency of payment runs in the schedule. + enum: + - Daily + - Weekly + - Monthly + day: + type: string + description: > + The day of a month when payment runs need to be performed. Required + only if **frequency** is **Monthly**. Allowed values are 1-31 or + **L** (the last day of a month). + day_of_week: + type: array + items: + type: integer + description: > + An array of days in a week when payment runs need to be performed. + Required only if **frequency** is **Weekly**. Allowed integers are + 1-7. 1 stands for Monday. 2 stands for Tuesday, etc. + hour: + type: integer + description: > + The hour of a day when payment runs need to be performed. Allowed + values are 1-23. + billrun: + type: string + description: > + A bill run name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + batch: + type: string + description: > + A batch name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + currency: + type: string + description: > + A three-character currency code that is used to determine what + receivables should be included in payment runs in this schedule. + Valid only if the custom filter is not used. + payment_gateway: + type: string + description: > + A payment gateway name that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + bill_cycle_day: + type: string + description: > + A bill cycle day value that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + custom: + type: string + description: > + A custom ZOQL query that is used to determine what receivables + should be included in payment runs in this schedule. It cannot be + used with other filters. + example: + frequency: Weekly + days_of_week: + - 2 + - 3 + hour: 2 + currency: CAD + PUTPaymentRunSchedule: + type: object + properties: + frequency: + type: string + description: | + The frequency of payment runs in the schedule. + enum: + - Daily + - Weekly + - Monthly + day: + type: string + description: > + The day of a month when payment runs need to be performed. Required + only if **frequency** is **Monthly**. Allowed values are 1-31 or + **L** (the last day of a month). + day_of_week: + type: array + items: + type: integer + description: > + An array of days in a week when payment runs need to be performed. + Required only if **frequency** is **Weekly**. Allowed integers are + 1-7. 1 stands for Monday. 2 stands for Tuesday, etc. + hour: + type: integer + description: > + The hour of a day when payment runs need to be performed. Allowed + values are 1-23. + billrun: + type: string + description: > + A bill run name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + batch: + type: string + description: > + A batch name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + currency: + type: string + description: > + A three-character currency code that is used to determine what + receivables should be included in payment runs in this schedule. + Valid only if the custom filter is not used. + payment_gateway: + type: string + description: > + A payment gateway name that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + bill_cycle_day: + type: string + description: > + A bill cycle day value that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + custom: + type: string + description: > + A custom ZOQL query that is used to determine what receivables + should be included in payment runs in this schedule. It cannot be + used with other filters. + example: + currency: USD + POSTPaymentRunScheduleResponse: + type: object + properties: + id: + type: integer + description: | + The ID of the payment run schedule in Advanced Payment Manager. + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + items: + type: string + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + DELETEPaymentRunScheduleResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + items: + type: string + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + GETStatementsResponse: + type: object + properties: + statements: + type: array + items: + type: object + description: > + An array containing the requested number of statements of the + specified account. Every object contains an Amazon S3 link. You can + click the links to view and download the statements. The links will + expire in 10 minutes. + success: + type: boolean + description: | + Whether the operation is successful. + count: + type: integer + description: | + The number of statements retrieved. + GETStatementSettingsResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + templates: + type: array + items: + type: object + properties: + name: + type: string + description: The name of the template. + description: | + An array containing all available templates. + advanced_ar: + type: boolean + description: | + Whether Invoice Settlement is enabled on the tenant. + default_template: + type: string + description: | + The name of the default template. + default_cycle: + type: string + description: | + The statement cycle being used. + POSTAdhocStatementRun: + type: object + properties: + starting_date: + type: string + format: date + description: > + The starting date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + ending_date: + type: string + format: date + description: > + The ending date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + template_name: + type: string + description: | + The name of the template to be used in the statement run. + advanced_ar: + type: boolean + description: | + Specifies whether Invoice Settlement is enabled on the tenant. + account_id: + type: string + description: | + The ID of the account for which the statement run is created. + attach_to_account: + type: boolean + description: > + Indicates whether the generated statement is attached to the + account. + required: + - starting_date + - ending_date + - template_name + - advanced_ar + - account_id + example: + starting_date: 05-01-2018 + ending_date: 08-01-2018 + template_name: Default Name + advanced_ar: false + account_id: 2c92c0f964eaa3ec0164fad1eab730d6 + attach_to_account: true + POSTAdhocStatementRunResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + code: + type: integer + description: | + The response code. + message: + type: string + description: | + The response message. + statement_number: + type: string + description: | + The number of the statement. + POSTCustomStatementRun: + type: object + properties: + starting_date: + type: string + format: date + description: > + The starting date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + ending_date: + type: string + format: date + description: > + The ending date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + batch: + type: string + description: > + The billing batch of accounts the statements need to be generated + for. + mode: + type: string + description: | + The mode in which the run has to be executed. + enum: + - open_invoices + - open_balance + - no_invoice + - no_invoice_w_balance + - custom + required: + - starting_date + - ending_date + - batch + - mode + example: + starting_date: 05-01-2018 + ending_date: 08-01-2018 + batch: Batch40 + mode: custom + POSTCustomStatementRunResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + code: + type: integer + description: | + The response code. + message: + type: string + description: | + The response message. + execution_number: + type: string + description: | + The serial number of the execution. + report_file: + type: string + description: | + The URL pointing to the report of the run. + NotesObject: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful or not. + data: + type: object + properties: + id: + type: integer + description: The ID of the Notes object. + object: + type: string + description: >- + The type of the object. It can be "Accounts" or "Invoices" for + Collections Window. + notesId: + type: string + description: >- + The ID of the Notes object. It is an account number (32-digit + hex) for Accounts object type, and an invoice number for + Invoices object type. + notesParentId: + type: string + description: >- + The ID of the parent object. For "Accounts" object, this + parameter is the account name that the Notes object is created + for. + createdAt: + type: string + format: time-date + description: The time and date when this Notes object is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the Notes object is updated. + NotesObjectWithComment: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful or not. + data: + type: object + properties: + id: + type: integer + description: The ID of the Notes object. + object: + type: string + description: >- + The type of the object. It can be "Accounts" or "Invoices" for + Collections Window. + notesId: + type: string + description: >- + The ID of the notes object. It is an account number (32-digit + hex) for Accounts object type, and an invoice number for + Invoices object type. + notesParentId: + type: string + description: >- + The ID of the parent object. For "Accounts" object, this + parameter is the account name that the Notes object is created + for. + createdAt: + type: string + format: time-date + description: The time and date when this Notes object is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the Notes object is updated. + comments: + type: array + description: The array of comments for this Notes object. + items: + $ref: '#/components/schemas/NotesComment' + NotesUser: + type: object + properties: + id: + type: integer + description: The ID of the Notes user. + username: + type: string + description: The user name. + connectIdentity: + type: string + description: The connect ID of the user. It must be a 32-digit hex number. + email: + type: string + description: The email address of the user. + firstName: + type: string + description: The first name. + lastName: + type: string + description: The last name. + fullName: + type: string + description: The full name of the user. + platformRole: + type: string + description: The Platform role of the user. + timeZone: + type: string + description: The time zone setting for the user. + createdAt: + type: string + format: time-date + description: The time and date when this user record is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the user record is updated. + escalationUser: + type: string + description: >- + The full name of the user that is configured to handle escalations + for the current user. + escalationUserId: + type: string + description: The ID of the escalation user. It must be a 32-digit hex number. + approvalAmount: + type: number + description: The amount of money that this user is allowed to approve. + avatar: + type: string + description: The link to the avatar image file for the user. + NotesReply: + type: object + properties: + id: + type: integer + description: The ID of the reply. + body: + type: string + description: The body of the reply. + image: + type: string + description: >- + The link to the image file. The value is null if no image files are + available. + attachment: + type: string + description: >- + The link to the attachment. The value is null if no attachments are + available. + createdAt: + type: string + format: time-date + description: The time and date when the reply is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the reply is updated. + user: + $ref: '#/components/schemas/NotesUser' + NotesComment: + type: object + properties: + id: + type: integer + description: The ID of the comment. + body: + type: string + description: The body of the comment. + image: + type: string + description: >- + The link to the image file. The value is null if no image files are + available. + attachment: + type: string + description: >- + The link to the attachment. The value is null if no attachments are + available. + createdAt: + type: string + format: time-date + description: The time and date when this comment is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the comment is updated. + user: + description: The creator of the comment. + $ref: '#/components/schemas/NotesUser' + replies: + type: array + description: An array of replies. + items: + $ref: '#/components/schemas/NotesReply' + NotesTasksResponse: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful. + data: + type: object + description: The actual tasks data. + properties: + tasks: + type: array + items: + type: object + properties: + id: + type: integer + description: The ID of the task. + task: + type: string + description: The title of the task. + description: + type: string + description: Additional details about the task. + dueDate: + type: string + format: time-date + description: The due date and time of the task. + createdAt: + type: string + format: time-date + description: The date and time when this task is created. + updatedAt: + type: string + format: time-date + description: The last date and time when the task is updated. + reminderDate: + type: string + format: time-date + description: >- + The data and time when a reminder about this task needs to + be sent. + notifications: + type: string + description: >- + The message to be sent as notifications. It can be null if + no message is defined. + status: + type: string + description: The status of the task. + comment: + type: string + description: The comment about the task. + autoEscalation: + type: string + description: The automatic escalation setting for the task. + createdBy: + $ref: '#/components/schemas/NotesUser' + assignTo: + $ref: '#/components/schemas/NotesUser' + pagination: + type: object + properties: + page: + type: integer + description: The number of the current page. + per_page: + type: integer + description: The number of results on each page. + total_filtered_records: + type: integer + description: The total number of filtered records. + total_records: + type: integer + description: The total number of records. + NotesTasks: + type: object + properties: + id: + type: integer + description: The ID of the task. + task: + type: string + description: The title of the task. + description: + type: string + description: Additional details about the task. + dueDate: + type: string + format: time-date + description: The due date and time of the task. + createdAt: + type: string + format: time-date + description: The date and time when this task is created. + updatedAt: + type: string + format: time-date + description: The last date and time when the task is updated. + reminderDate: + type: string + format: time-date + description: The data and time when a reminder about this task needs to be sent. + notifications: + type: string + description: >- + The message to be sent as notifications. It can be null if no + message is defined. + status: + type: string + description: The status of the task. + comment: + type: string + description: The comment about the task. + autoEscalation: + type: string + description: The automatic escalation setting for the task. + createdBy: + $ref: '#/components/schemas/NotesUser' + assignTo: + $ref: '#/components/schemas/NotesUser' + NotesGroup: + type: object + properties: + id: + type: integer + description: The ID of the Notes group. + name: + type: string + description: The name of the group. + description: + type: string + description: Additional information about the group. + created_at: + type: string + format: time-date + description: The date and time when the group was created. + updated_at: + type: string + format: time-date + description: The last date and time when the group was updated. + users: + type: array + description: A list of all users in the group. + items: + $ref: '#/components/schemas/NotesUser' + NotesGroupsResponse: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful. + groups: + type: array + items: + $ref: '#/components/schemas/NotesGroup' + NotesCreateGroupBody: + type: object + properties: + name: + type: string + description: The name of the group that you want to create. + description: + type: string + description: Additional information about the group. + NotesUpdateGroupBody: + type: object + properties: + name: + type: string + description: The new name of the group. + description: + type: string + description: The new description about the group. + NotesDeleteGroupBody: + type: object + properties: + name: + type: string + description: The name of the group that has been deleted. + description: + type: string + description: The description of the group. + NotesCreateGroupResponse: + type: object + properties: + success: + type: boolean + description: Whether the operation is successful. + id: + type: integer + description: The ID of the Notes group. + name: + type: string + description: The name of the group. + description: + type: string + description: Additional information about the group. + created_at: + type: string + format: time-date + description: The date and time when the group was created. + updated_at: + type: string + format: time-date + description: The last date and time when the group was updated. + users: + type: array + description: An array of users in the group. + items: + $ref: '#/components/schemas/NotesUser' + ResultsPagination: + type: object + description: The pagination information. + properties: + page: + type: integer + description: The current page. + page_length: + type: integer + description: The number of result on each page. + next_page: + type: string + description: The link to the next page of results. + CollectionAccount: + type: object + properties: + name: + type: string + description: The name of the account. + zuora_id: + type: string + description: The Zuora ID of the account. + in_collections: + type: boolean + description: Whether the account is in collections. + account_currency: + type: string + description: The currency that is currently used by the account. + home_currency: + type: string + description: The home currency of the tenant. + amount_due_account_currency: + type: number + description: The amount that is due for the account in the account currency. + amount_due_home_currency: + type: number + description: The amount that is due for the account in the tenant home currency. + last_open_invoice_date: + type: string + format: date + description: The last open invoice date. + average_debt_age: + type: number + description: The average age of all the debt of the account. + statuses: + $ref: '#/components/schemas/CollectionStatuses' + CollectionStatuses: + type: object + description: The status of the account. + properties: + In Collections: + type: boolean + description: Whether this account is in collections. + Pending: + type: boolean + description: Whether this account is pending. + In Dispute: + type: boolean + description: Whether this account is in dispute. + Paid In Full: + type: boolean + description: Whether this account has paid in full. + CollectionAgent: + type: object + properties: + name: + type: string + description: The name of the agent. + email: + type: string + description: The email of the agent. + zuora_identity_id: + type: string + description: The Zuora ID of the agent. + amount_in_collections: + type: number + description: The total amount of debt for accounts that are assigned to the user. + accounts: + type: integer + description: The number of accounts that are assigned to the user. + account_statuses: + type: object + properties: + In Collections: + type: integer + description: The number of accounts that are in collections. + Pending: + type: integer + description: The number of accounts that are pending. + In Disputes: + type: integer + description: The number of accounts that are in dispute. + Paid in Full: + type: integer + description: The number of accounts that have paid in full. + GETCollectionAgentsResponse: + type: object + properties: + accounts: + $ref: '#/components/schemas/CollectionAgent' + pagination: + $ref: '#/components/schemas/ResultsPagination' + GETCollectionAccountsResponse: + type: object + properties: + accounts: + type: array + description: The array of accounts. + items: + $ref: '#/components/schemas/CollectionAccount' + pagination: + $ref: '#/components/schemas/ResultsPagination' + CollectionsInfo: + type: object + properties: + accounts_in_collections: + type: integer + description: The number of accounts that are in collections. + home_currency: + type: string + description: The home currency of the tenant. + total_debt: + type: number + description: The total debt of all accounts that are in collections. + largest_debts: + type: array + description: The five largest debts that are in collections. + items: + type: string + description: An account number and the amount due for the account. + oldest_debts: + type: array + description: The five oldest debts that are in collections. + items: + type: string + description: An account number and the amount due for the account. + statuses: + type: object + properties: + In Collection: + type: integer + description: The number of accounts that are in collections. + Pending: + type: integer + description: The number of accounts that are in pending status. + In Dispute: + type: integer + description: The number of accounts that are in dispute. + Paid In Full: + type: integer + securitySchemes: + BasicAuth: + type: http + scheme: basic diff --git a/openapi-cli/src/test/resources/testng.xml b/openapi-cli/src/test/resources/testng.xml index a88d59373..5dc0aa029 100644 --- a/openapi-cli/src/test/resources/testng.xml +++ b/openapi-cli/src/test/resources/testng.xml @@ -113,6 +113,7 @@ under the License. + diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java new file mode 100644 index 000000000..ba73620f8 --- /dev/null +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java @@ -0,0 +1,162 @@ +package io.ballerina.openapi.core.generators.client; + +import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.FunctionSignatureNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; +import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode; +import io.ballerina.compiler.syntax.tree.ModulePartNode; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ReturnStatementNode; +import io.ballerina.compiler.syntax.tree.StatementNode; +import io.ballerina.compiler.syntax.tree.SyntaxTree; +import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; +import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages; +import io.ballerina.openapi.core.generators.client.exception.ClientException; +import io.ballerina.openapi.core.generators.client.model.OASClientConfig; +import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; +import io.ballerina.openapi.core.generators.document.ClientDocCommentGenerator; +import io.ballerina.tools.text.TextDocument; +import io.ballerina.tools.text.TextDocuments; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionDefinitionNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createModulePartNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnStatementNode; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.EOF_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_DEFINITION; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURN_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; + +public class AdvanceMockClientGenerator extends BallerinaClientGeneratorWithStatusCodeBinding { + OASClientConfig oasClientConfig; + public AdvanceMockClientGenerator(OASClientConfig oasClientConfig) { + super(oasClientConfig); + this.oasClientConfig = oasClientConfig; + } + + @Override + public FunctionDefinitionNode createInitFunction() { + FunctionSignatureNode functionSignatureNode = super.getInitFunctionSignatureNode(); + NodeList qualifierList = createNodeList(createToken(PUBLIC_KEYWORD), createToken(ISOLATED_KEYWORD)); + IdentifierToken functionName = createIdentifierToken("init"); + List assignmentNodes = new ArrayList<>(); + ReturnStatementNode returnStatementNode = createReturnStatementNode(createToken( + RETURN_KEYWORD), null, createToken(SEMICOLON_TOKEN)); + assignmentNodes.add(returnStatementNode); + NodeList statementList = createNodeList(assignmentNodes); + FunctionBodyBlockNode functionBodyNode = createFunctionBodyBlockNode(createToken(OPEN_BRACE_TOKEN), + null, statementList, createToken(CLOSE_BRACE_TOKEN), null); + return createFunctionDefinitionNode(FUNCTION_DEFINITION, super.getInitDocComment(), qualifierList, + createToken(FUNCTION_KEYWORD), functionName, createEmptyNodeList(), functionSignatureNode, + functionBodyNode); + } + +// //override client function generation +// public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException { +// // Collect members for class definition node +// List memberNodeList = new ArrayList<>(); +// // Add instance variable to class definition node +// memberNodeList.addAll(createClassInstanceVariables()); +// // Add init function to class definition node +// memberNodeList.add(getInitFunction()); +// Map> filteredOperations = filterOperations(); +// //switch resource remote +// List functionDefinitionNodeList = new ArrayList<>(); +// //Mock cleint function generation +// +// for (Map.Entry> operation : filteredOperations.entrySet()) { +// for (Map.Entry operationEntry : operation.getValue().entrySet()) { +//// Optional funDefOptionalNode = createImplFunction(path, operationEntry, +// openAPI, clie); +//// if (funDefOptionalNode.isPresent()) { +//// functionDefinitionNodeList.add(funDefOptionalNode.get()); +//// } +// } +// } +// memberNodeList.addAll(functionDefinitionNodeList); +// // Generate the class combining members +// MetadataNode metadataNode = getClassMetadataNode(); +// IdentifierToken className = createIdentifierToken(GeneratorConstants.CLIENT); +// NodeList classTypeQualifiers = createNodeList( +// createToken(ISOLATED_KEYWORD), createToken(CLIENT_KEYWORD)); +// return createClassDefinitionNode(metadataNode, createToken(PUBLIC_KEYWORD), classTypeQualifiers, +// createToken(CLASS_KEYWORD), className, createToken(OPEN_BRACE_TOKEN), +// createNodeList(memberNodeList), createToken(CLOSE_BRACE_TOKEN), null); +// +// } + + + @Override + protected List getModuleMemberDeclarationNodes() throws BallerinaOpenApiException { + List nodes = new ArrayList<>(); + nodes.add(getSetModuleFunction()); + nodes.add(getModuleInitFunction()); + nodes.add(getClientMethodImplType()); + nodes.add(getMethodImplAnnotation()); + nodes.add(getClientErrorType()); + nodes.addAll(super.getModuleMemberDeclarationNodes()); + return nodes; + } + + @Override + protected void addClientFunctionImpl(Map.Entry> operation, + Map.Entry operationEntry, + List clientFunctionNodes) { + FunctionDefinitionNode clientExternFunction = clientFunctionNodes.get(clientFunctionNodes.size() - 1); + Optional implFunction = createImplFunction(operation.getKey(), operationEntry, openAPI, + authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction, oasClientConfig.isMock()); + if (implFunction.isPresent()) { + clientFunctionNodes.add(implFunction.get()); + } else { + diagnostics.add(new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_112, + operationEntry.getValue().getOperationId())); + clientFunctionNodes.remove(clientFunctionNodes.size() - 1); + } + } + /** + * This method for generate the client syntax tree. + * + * @return return Syntax tree for the ballerina code. + * @throws BallerinaOpenApiException When function fail in process. + */ + public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException { + + // Create `ballerina/http` import declaration node + List importForHttp = getImportDeclarationNodes(); + imports.addAll(importForHttp); + + // Add authentication related records + authConfigGeneratorImp.addAuthRelatedRecords(openAPI); + + List nodes = getModuleMemberDeclarationNodes(); + NodeList importsList = createNodeList(imports); + ModulePartNode modulePartNode = + createModulePartNode(importsList, createNodeList(nodes), createToken(EOF_TOKEN)); + TextDocument textDocument = TextDocuments.from(""); + SyntaxTree syntaxTree = SyntaxTree.from(textDocument); + syntaxTree = syntaxTree.modifyWith(modulePartNode); + //Add comments + ClientDocCommentGenerator clientDocCommentGenerator = new ClientDocCommentGenerator(syntaxTree, openAPI, + oasClientConfig.isResourceMode()); + return clientDocCommentGenerator.updateSyntaxTreeWithDocComments(); + } +} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java index 242b08fa0..5117ab588 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java @@ -268,7 +268,7 @@ private ClassDefinitionNode getClassDefinitionNode() { /** * This function is to filter the operations based on the user given tags and operations. */ - private Map> filterOperations() { + protected Map> filterOperations() { //todo refactor code Map> filteredOperation = new HashMap<>(); List filterTags = filter.getTags(); @@ -308,7 +308,7 @@ private Map> filterOperations() { * * @return {@link MetadataNode} Metadata node of the client class */ - private MetadataNode getClassMetadataNode() { + protected MetadataNode getClassMetadataNode() { List classLevelAnnotationNodes = new ArrayList<>(); if (openAPI.getInfo().getExtensions() != null) { @@ -355,7 +355,7 @@ private MetadataNode getClassMetadataNode() { * @return {@link FunctionDefinitionNode} Class init function * @throws BallerinaOpenApiException When invalid server URL is provided */ - private FunctionDefinitionNode createInitFunction() { + protected FunctionDefinitionNode createInitFunction() { FunctionSignatureNode functionSignatureNode = getInitFunctionSignatureNode(); FunctionBodyNode functionBodyNode = getInitFunctionBodyNode(); @@ -419,7 +419,7 @@ private FunctionBodyNode getInitFunctionBodyNode() { * @return {@link FunctionSignatureNode} * @throws BallerinaOpenApiException When invalid server URL is provided */ - private FunctionSignatureNode getInitFunctionSignatureNode() { + protected FunctionSignatureNode getInitFunctionSignatureNode() { List parameterNodes = new ArrayList<>(); ServerURLGeneratorImp serverURLGeneratorImp = new ServerURLGeneratorImp(openAPI.getServers()); ParameterNode serverURLNode = serverURLGeneratorImp.generateServerURL(); @@ -505,7 +505,7 @@ public static List ascendingOrder(List inputList) { * * @return {@link MetadataNode} Metadata node containing entire function documentation comment. */ - private MetadataNode getInitDocComment() { + protected MetadataNode getInitDocComment() { List docs = new ArrayList<>(); String clientInitDocComment = "Gets invoked to initialize the `connector`.\n"; @@ -544,7 +544,7 @@ private MetadataNode getInitDocComment() { * * @return {@link List} List of instance variables */ - private List createClassInstanceVariables() { + protected List createClassInstanceVariables() { List fieldNodeList = new ArrayList<>(); Token finalKeywordToken = createToken(FINAL_KEYWORD); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java index b35644091..4dafabf21 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java @@ -46,6 +46,7 @@ import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages; +import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.GeneratorConstants; import io.ballerina.openapi.core.generators.common.GeneratorUtils; @@ -114,9 +115,11 @@ * @since 1.9.0 */ public class BallerinaClientGeneratorWithStatusCodeBinding extends BallerinaClientGenerator { + OASClientConfig oasClientConfig; public BallerinaClientGeneratorWithStatusCodeBinding(OASClientConfig oasClientConfig) { super(oasClientConfig); authConfigGeneratorImp = new AuthConfigGeneratorWithStatusCodeBinding(false, false); + this.oasClientConfig = oasClientConfig; } /** @@ -172,12 +175,12 @@ protected QualifiedNameReferenceNode getHttpClientTypeName() { createIdentifierToken(GeneratorConstants.STATUS_CODE_CLIENT)); } - private void addClientFunctionImpl(Map.Entry> operation, + protected void addClientFunctionImpl(Map.Entry> operation, Map.Entry operationEntry, List clientFunctionNodes) { FunctionDefinitionNode clientExternFunction = clientFunctionNodes.get(clientFunctionNodes.size() - 1); Optional implFunction = createImplFunction(operation.getKey(), operationEntry, openAPI, - authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction); + authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction, oasClientConfig.isMock()); if (implFunction.isPresent()) { clientFunctionNodes.add(implFunction.get()); } else { @@ -205,12 +208,13 @@ protected ResourceFunctionGenerator getResourceFunctionGenerator(Map.Entry createImplFunction(String path, + protected Optional createImplFunction(String path, Map.Entry operation, OpenAPI openAPI, AuthConfigGeneratorImp authConfigGeneratorImp, BallerinaUtilGenerator ballerinaUtilGenerator, - FunctionDefinitionNode clientExternFunction) { + FunctionDefinitionNode clientExternFunction, + boolean isMock) { //Create qualifier list NodeList qualifierList = createNodeList(createToken(PRIVATE_KEYWORD), createToken(ISOLATED_KEYWORD)); Token functionKeyWord = createToken(FUNCTION_KEYWORD); @@ -219,15 +223,26 @@ private Optional createImplFunction(String path, ImplFunctionSignatureGenerator signatureGenerator = new ImplFunctionSignatureGenerator(operation.getValue(), openAPI, operation.getKey().toString().toLowerCase(Locale.ROOT), path, clientExternFunction); //Create function body - FunctionBodyGeneratorImp functionBodyGenerator = new ImplFunctionBodyGenerator(path, operation, openAPI, - authConfigGeneratorImp, ballerinaUtilGenerator, imports, signatureGenerator.hasHeaders(), - signatureGenerator.hasDefaultHeaders(), signatureGenerator.hasQueries()); FunctionBodyNode functionBodyNode; - Optional functionBodyNodeResult = functionBodyGenerator.getFunctionBodyNode(); - if (functionBodyNodeResult.isEmpty()) { - return Optional.empty(); + if (isMock) { + MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, + true); + Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); + if (functionBodyOptionalNode.isEmpty()) { + return Optional.empty(); + } + diagnostics.addAll(bodyGenerator.getDiagnostics()); + functionBodyNode = bodyGenerator.getFunctionBodyNode().get(); + } else { + FunctionBodyGeneratorImp functionBodyGenerator = new ImplFunctionBodyGenerator(path, operation, openAPI, + authConfigGeneratorImp, ballerinaUtilGenerator, imports, signatureGenerator.hasHeaders(), + signatureGenerator.hasDefaultHeaders(), signatureGenerator.hasQueries()); + Optional functionBodyNodeResult = functionBodyGenerator.getFunctionBodyNode(); + if (functionBodyNodeResult.isEmpty()) { + return Optional.empty(); + } + functionBodyNode = functionBodyNodeResult.get(); } - functionBodyNode = functionBodyNodeResult.get(); Optional functionSignatureNode = signatureGenerator.generateFunctionSignature(); return functionSignatureNode.map(signatureNode -> @@ -245,7 +260,7 @@ private Optional createImplFunction(String path, * * @return {@link FunctionDefinitionNode} FunctionDefinitionNode */ - private FunctionDefinitionNode getSetModuleFunction() { + FunctionDefinitionNode getSetModuleFunction() { NodeList emptyQualifiers = createEmptyNodeList(); NodeList emptyNodeList = createEmptyNodeList(); SeparatedNodeList emptyParamList = createSeparatedNodeList(); @@ -280,7 +295,7 @@ private FunctionDefinitionNode getSetModuleFunction() { * * @return {@link FunctionDefinitionNode} FunctionDefinitionNode */ - private FunctionDefinitionNode getModuleInitFunction() { + FunctionDefinitionNode getModuleInitFunction() { NodeList emptyQualifiers = createEmptyNodeList(); NodeList emptyNodeList = createEmptyNodeList(); SeparatedNodeList emptyParamList = createSeparatedNodeList(); @@ -308,7 +323,7 @@ private FunctionDefinitionNode getModuleInitFunction() { * * @return {@link TypeDefinitionNode} TypeDefinitionNode */ - private TypeDefinitionNode getClientMethodImplType() { + TypeDefinitionNode getClientMethodImplType() { RecordFieldNode nameFieldNode = createRecordFieldNode(null, null, createIdentifierToken("string"), createIdentifierToken("name"), null, createToken(SEMICOLON_TOKEN)); RecordTypeDescriptorNode recordDescriptor = createRecordTypeDescriptorNode(createToken(RECORD_KEYWORD), @@ -326,7 +341,7 @@ private TypeDefinitionNode getClientMethodImplType() { * * @return {@link AnnotationDeclarationNode} AnnotationDeclarationNode */ - private AnnotationDeclarationNode getMethodImplAnnotation() { + AnnotationDeclarationNode getMethodImplAnnotation() { return createAnnotationDeclarationNode(null, null, null, createToken(ANNOTATION_KEYWORD), createIdentifierToken("ClientMethodImpl"), createIdentifierToken("MethodImpl"), createToken(ON_KEYWORD), createSeparatedNodeList(createToken(FUNCTION_KEYWORD)), @@ -341,7 +356,7 @@ private AnnotationDeclarationNode getMethodImplAnnotation() { * * @return {@link TypeDefinitionNode} TypeDefinitionNode */ - private TypeDefinitionNode getClientErrorType() { + protected TypeDefinitionNode getClientErrorType() { return createTypeDefinitionNode(null, null, createToken(TYPE_KEYWORD), createIdentifierToken("ClientMethodInvocationError"), createQualifiedNameReferenceNode(createIdentifierToken("http"), createToken(COLON_TOKEN), diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java new file mode 100644 index 000000000..34bc8b950 --- /dev/null +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java @@ -0,0 +1,148 @@ +package io.ballerina.openapi.core.generators.client; + +import io.ballerina.compiler.syntax.tree.ClassDefinitionNode; +import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.FunctionSignatureNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; +import io.ballerina.compiler.syntax.tree.MetadataNode; +import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode; +import io.ballerina.compiler.syntax.tree.ModulePartNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ReturnStatementNode; +import io.ballerina.compiler.syntax.tree.StatementNode; +import io.ballerina.compiler.syntax.tree.SyntaxTree; +import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.openapi.core.generators.client.exception.ClientException; +import io.ballerina.openapi.core.generators.client.mock.MockClientFunctionGenerator; +import io.ballerina.openapi.core.generators.client.model.OASClientConfig; +import io.ballerina.openapi.core.generators.common.GeneratorConstants; +import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; +import io.ballerina.openapi.core.generators.document.ClientDocCommentGenerator; +import io.ballerina.tools.text.TextDocument; +import io.ballerina.tools.text.TextDocuments; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createClassDefinitionNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionDefinitionNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createModulePartNode; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnStatementNode; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLASS_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLIENT_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.EOF_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_DEFINITION; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURN_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; + +public class BallerinaMockClientGenerator extends BallerinaClientGenerator { + OASClientConfig oasClientConfig; + public BallerinaMockClientGenerator(OASClientConfig oasClientConfig) { + super(oasClientConfig); + this.oasClientConfig = oasClientConfig; + } + + //override init function generation + public FunctionDefinitionNode getInitFunction() { + FunctionSignatureNode functionSignatureNode = super.getInitFunctionSignatureNode(); + NodeList qualifierList = createNodeList(createToken(PUBLIC_KEYWORD), createToken(ISOLATED_KEYWORD)); + IdentifierToken functionName = createIdentifierToken("init"); + List assignmentNodes = new ArrayList<>(); + ReturnStatementNode returnStatementNode = createReturnStatementNode(createToken( + RETURN_KEYWORD), null, createToken(SEMICOLON_TOKEN)); + assignmentNodes.add(returnStatementNode); + NodeList statementList = createNodeList(assignmentNodes); + FunctionBodyBlockNode functionBodyNode = createFunctionBodyBlockNode(createToken(OPEN_BRACE_TOKEN), + null, statementList, createToken(CLOSE_BRACE_TOKEN), null); + return createFunctionDefinitionNode(FUNCTION_DEFINITION, super.getInitDocComment(), qualifierList, + createToken(FUNCTION_KEYWORD), functionName, createEmptyNodeList(), functionSignatureNode, + functionBodyNode); + } + + //override client function generation + public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException { + // Collect members for class definition node + List memberNodeList = new ArrayList<>(); + // Add instance variable to class definition node + memberNodeList.addAll(createClassInstanceVariables()); + // Add init function to class definition node + memberNodeList.add(getInitFunction()); + Map> filteredOperations = filterOperations(); + //switch resource remote + List functionDefinitionNodeList = new ArrayList<>(); + //Mock cleint function generation + + for (Map.Entry> operation : filteredOperations.entrySet()) { + for (Map.Entry operationEntry : operation.getValue().entrySet()) { + MockClientFunctionGenerator mockClientFunctionGenerator = new MockClientFunctionGenerator( + operation.getKey(), operationEntry, oasClientConfig); + Optional funDefOptionalNode = mockClientFunctionGenerator.generateFunction(); + if (funDefOptionalNode.isPresent()) { + functionDefinitionNodeList.add(funDefOptionalNode.get()); + } + } + } + memberNodeList.addAll(functionDefinitionNodeList); + // Generate the class combining members + MetadataNode metadataNode = getClassMetadataNode(); + IdentifierToken className = createIdentifierToken(GeneratorConstants.CLIENT); + NodeList classTypeQualifiers = createNodeList( + createToken(ISOLATED_KEYWORD), createToken(CLIENT_KEYWORD)); + return createClassDefinitionNode(metadataNode, createToken(PUBLIC_KEYWORD), classTypeQualifiers, + createToken(CLASS_KEYWORD), className, createToken(OPEN_BRACE_TOKEN), + createNodeList(memberNodeList), createToken(CLOSE_BRACE_TOKEN), null); + + } + + @Override + protected List getModuleMemberDeclarationNodes() throws BallerinaOpenApiException { + List nodes = new ArrayList<>(); + nodes.add(getClientFunction()); + return nodes; + } + + /** + * This method for generate the client syntax tree. + * + * @return return Syntax tree for the ballerina code. + * @throws BallerinaOpenApiException When function fail in process. + */ + public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException { + + // Create `ballerina/http` import declaration node + List importForHttp = getImportDeclarationNodes(); + imports.addAll(importForHttp); + + // Add authentication related records + authConfigGeneratorImp.addAuthRelatedRecords(openAPI); + + List nodes = getModuleMemberDeclarationNodes(); + NodeList importsList = createNodeList(imports); + ModulePartNode modulePartNode = + createModulePartNode(importsList, createNodeList(nodes), createToken(EOF_TOKEN)); + TextDocument textDocument = TextDocuments.from(""); + SyntaxTree syntaxTree = SyntaxTree.from(textDocument); + syntaxTree = syntaxTree.modifyWith(modulePartNode); + //Add comments + ClientDocCommentGenerator clientDocCommentGenerator = new ClientDocCommentGenerator(syntaxTree, openAPI, + oasClientConfig.isResourceMode()); + return clientDocCommentGenerator.updateSyntaxTreeWithDocComments(); + } +} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java index dde7bc13d..701958a2b 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java @@ -57,7 +57,9 @@ public enum DiagnosticMessages { " response found for the operation which is not supported with status code binding option", DiagnosticSeverity.WARNING), OAS_CLIENT_115("OAS_CLIENT_115", "the 'default' response for the operation: '%s' is skipped in the client " + - "generation, since it is not supported with status code binding option", DiagnosticSeverity.WARNING); + "generation, since it is not supported with status code binding option", DiagnosticSeverity.WARNING), + OAS_CLIENT_116("OAS_CLIENT_116", "the operation for given path `%s` , method `%s` is skipped in " + + "the mock client function generation since it is not provided with examples", DiagnosticSeverity.WARNING); private final String code; private final String description; private final DiagnosticSeverity severity; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java new file mode 100644 index 000000000..553bcec24 --- /dev/null +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java @@ -0,0 +1,110 @@ +package io.ballerina.openapi.core.generators.client.mock; + +import io.ballerina.compiler.syntax.tree.FunctionBodyNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.FunctionSignatureNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeFactory; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.openapi.core.generators.client.FunctionGenerator; +import io.ballerina.openapi.core.generators.client.ResourceFunctionSignatureGenerator; +import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; +import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; +import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages; +import io.ballerina.openapi.core.generators.client.model.OASClientConfig; +import io.ballerina.openapi.core.generators.common.GeneratorUtils; +import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; +import io.ballerina.tools.diagnostics.Diagnostic; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.RESOURCE_ACCESSOR_DEFINITION; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.RESOURCE_KEYWORD; + +public class MockClientFunctionGenerator implements FunctionGenerator { + String path; + Map.Entry operation; + OpenAPI openAPI; + List diagnostics = new ArrayList<>(); + boolean isResourceFunction; + OASClientConfig oasClientConfig; + public MockClientFunctionGenerator(String path, Map.Entry operation, + OASClientConfig oasClientConfig) { + this.path = path; + this.operation = operation; + this.openAPI = oasClientConfig.getOpenAPI(); + this.isResourceFunction = oasClientConfig.isResourceMode(); + this.oasClientConfig = oasClientConfig; + } + + @Override + public Optional generateFunction() throws BallerinaOpenApiException { + //function signature node, remote, resource + if (isResourceFunction) { + //function signature node, remote, resource + //Create qualifier list + NodeList qualifierList = createNodeList(createToken(RESOURCE_KEYWORD), + createToken(ISOLATED_KEYWORD)); + Token functionKeyWord = createToken(FUNCTION_KEYWORD); + String method = operation.getKey().toString().toLowerCase(Locale.ROOT); + IdentifierToken functionName = createIdentifierToken(method); + + List pathDiagnostics = new ArrayList<>(); + NodeList relativeResourcePath = GeneratorUtils.getRelativeResourcePath(path, operation.getValue(), + openAPI.getComponents(), false, pathDiagnostics); + if (!pathDiagnostics.isEmpty()) { + pathDiagnostics.forEach(diagnostic -> { + if (diagnostic.diagnosticInfo().code().equals("OAS_COMMON_204")) { + DiagnosticMessages message = DiagnosticMessages.OAS_CLIENT_110; + ClientDiagnosticImp clientDiagnostic = new ClientDiagnosticImp(message, path, method); + diagnostics.add(clientDiagnostic); + } + }); + return Optional.empty(); + } + + //create function signature + ResourceFunctionSignatureGenerator signatureGenerator = new ResourceFunctionSignatureGenerator( + operation.getValue(), openAPI, operation.getKey().toString(), path); + Optional signatureNodeOptional = signatureGenerator.generateFunctionSignature(); + diagnostics.addAll(signatureGenerator.getDiagnostics()); + if (signatureNodeOptional.isEmpty()) { + return Optional.empty(); + } + FunctionSignatureNode signatureNode = signatureNodeOptional.get(); + MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, + oasClientConfig.isStatusCodeBinding()); + Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); + if (functionBodyOptionalNode.isEmpty()) { + return Optional.empty(); + } + diagnostics.addAll(bodyGenerator.getDiagnostics()); + FunctionBodyNode functionBodyNode = functionBodyOptionalNode.get(); + return Optional.of(NodeFactory.createFunctionDefinitionNode(RESOURCE_ACCESSOR_DEFINITION, null, + qualifierList, + functionKeyWord, functionName, relativeResourcePath, signatureNode, functionBodyNode)); + } else { + //function signature node, remote, resource + } + return Optional.empty(); + } + + @Override + public List getDiagnostics() { + return null; + } +} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java new file mode 100644 index 000000000..3fbd72a7b --- /dev/null +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java @@ -0,0 +1,113 @@ +package io.ballerina.openapi.core.generators.client.mock; + +import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; +import io.ballerina.compiler.syntax.tree.FunctionBodyNode; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.NodeParser; +import io.ballerina.compiler.syntax.tree.StatementNode; +import io.ballerina.openapi.core.generators.client.FunctionBodyGenerator; +import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; +import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; +import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.examples.Example; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; +import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN; + +/** + * Mock function body generator. + * @since 2.1.0 + */ +public class MockFunctionBodyGenerator implements FunctionBodyGenerator { + String path; + Map.Entry operation; + OpenAPI openAPI; + List diagnostics = new ArrayList<>(); + boolean isAdvanceClient; + + + public MockFunctionBodyGenerator(String path, Map.Entry operation, + OpenAPI openAPI, boolean isAdvanceClient) { + this.path = path; + this.operation = operation; + this.openAPI = openAPI; + this.isAdvanceClient = isAdvanceClient; + } + + @Override + public Optional getFunctionBodyNode() { + + //Check inline example + ApiResponses responses = operation.getValue().getResponses(); + //Get the successful response + ApiResponse successResponse = null; + for (Map.Entry response : responses.entrySet()) { + if (response.getKey().startsWith("2")) { + successResponse = response.getValue(); + break; + } + } + // Here only consider 2xx response + if (successResponse == null || successResponse.getContent() == null) { + return Optional.empty(); + } + // Get the example + Map examples = null; + for (Map.Entry mediaType : successResponse.getContent().entrySet()) { + // handle reference + if (mediaType.getValue().getExamples() != null) { + examples = mediaType.getValue().getExamples(); + } + } + + // check ref example + if (examples == null) { + ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_116, + path, operation.getKey().toString()); + diagnostics.add(diagnosticImp); + return Optional.empty(); + } + Object response = examples.get("response"); + if (response == null) { + ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_116, + path, operation.getKey().toString()); + diagnostics.add(diagnosticImp); + return Optional.empty(); + } + String exampleValue = ((Example) response).getValue().toString(); + String statement; + if (isAdvanceClient) { + statement = "return {\n" + + " body : " + exampleValue + ",\n" + + " headers: {}\n" + + " };"; + } else { + statement = "return " + exampleValue + ";"; + } + StatementNode returnNode = NodeParser.parseStatement(statement); + NodeList statementList = createNodeList(returnNode); + + FunctionBodyBlockNode fBodyBlock = createFunctionBodyBlockNode(createToken(OPEN_BRACE_TOKEN), + null, statementList, createToken(CLOSE_BRACE_TOKEN), null); + return Optional.of(fBodyBlock); + } + + @Override + public List getDiagnostics() { + return diagnostics; + } +} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java new file mode 100644 index 000000000..043f16477 --- /dev/null +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java @@ -0,0 +1,24 @@ +package io.ballerina.openapi.core.generators.client.mock; + +import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; +import io.ballerina.openapi.core.generators.client.AuthConfigGeneratorImp; +import io.ballerina.openapi.core.generators.client.BallerinaUtilGenerator; +import io.ballerina.openapi.core.generators.client.ImplFunctionBodyGenerator; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; + +import java.util.List; +import java.util.Map; + +public class MockImplFunctionBodyGenerator extends ImplFunctionBodyGenerator { + public MockImplFunctionBodyGenerator(String path, Map.Entry operation, + OpenAPI openAPI, AuthConfigGeneratorImp ballerinaAuthConfigGeneratorImp, + BallerinaUtilGenerator ballerinaUtilGenerator, + List imports, boolean hasHeaders, + boolean hasDefaultHeaders, boolean hasQueries) { + super(path, operation, openAPI, ballerinaAuthConfigGeneratorImp, ballerinaUtilGenerator, + imports, hasHeaders, hasDefaultHeaders, hasQueries); + } + +} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java index cc6baed5b..fc10f939a 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java @@ -35,6 +35,7 @@ public class OASClientConfig { private final boolean isPlugin; private final String license; private final boolean statusCodeBinding; + private final boolean isMock; private OASClientConfig(Builder clientConfigBuilder) { @@ -45,6 +46,7 @@ private OASClientConfig(Builder clientConfigBuilder) { this.resourceMode = clientConfigBuilder.resourceMode; this.license = clientConfigBuilder.license; this.statusCodeBinding = clientConfigBuilder.statusCodeBinding; + this.isMock = clientConfigBuilder.isMock; } public OpenAPI getOpenAPI() { @@ -73,6 +75,10 @@ public boolean isStatusCodeBinding() { return statusCodeBinding; } + public boolean isMock() { + return isMock; + } + /** * Client IDL plugin meta data builder class. */ @@ -84,6 +90,7 @@ public static class Builder { private boolean isPlugin = false; private String license = DO_NOT_MODIFY_FILE_HEADER; private boolean statusCodeBinding = false; + private boolean isMock = false; public Builder withOpenAPI(OpenAPI openAPI) { this.openAPI = openAPI; @@ -120,6 +127,11 @@ public Builder withStatusCodeBinding(boolean statusCodeBinding) { return this; } + public Builder withMock(boolean isMock) { + this.isMock = isMock; + return this; + } + public OASClientConfig build() { return new OASClientConfig(this); } diff --git a/openapi-core/src/main/java/module-info.java b/openapi-core/src/main/java/module-info.java index 8565e8664..ccc136505 100644 --- a/openapi-core/src/main/java/module-info.java +++ b/openapi-core/src/main/java/module-info.java @@ -60,4 +60,5 @@ exports io.ballerina.openapi.core.generators.service.response; exports io.ballerina.openapi.core.generators.service.diagnostic; exports io.ballerina.openapi.core.generators.type.diagnostic; + exports io.ballerina.openapi.core.generators.client.mock; } From c4d11d90f19b6e18525a1083d114530dfbf37859 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 28 May 2024 09:51:52 +0530 Subject: [PATCH 02/15] Add mock client generation for build command --- .../ballerina/openapi/bal/tool/Constants.java | 1 + .../bal/tool/OpenAPICodeGeneratorTool.java | 33 +++++++++++++------ .../resources/openapi-options-schema.json | 3 ++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/Constants.java b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/Constants.java index a94ffcb6f..f00eec2e3 100644 --- a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/Constants.java +++ b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/Constants.java @@ -35,6 +35,7 @@ public class Constants { public static final String CLIENT = "client"; public static final String CACHE_FILE = "openapi-cache.txt"; public static final String STATUS_CODE_BINDING = "statusCodeBinding"; + public static final String MOCK = "mock"; /** * Enum class for containing diagnostic messages. diff --git a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java index 9e10a7ab1..68744c988 100644 --- a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java +++ b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java @@ -19,8 +19,10 @@ import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; import io.ballerina.openapi.bal.tool.Constants.DiagnosticMessages; +import io.ballerina.openapi.core.generators.client.AdvanceMockClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGeneratorWithStatusCodeBinding; +import io.ballerina.openapi.core.generators.client.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; import io.ballerina.openapi.core.generators.client.exception.ClientException; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; @@ -296,6 +298,9 @@ public static ImmutablePair extractOptionDe case STATUS_CODE_BINDING: clientMetaDataBuilder.withStatusCodeBinding(value.contains(TRUE)); break; + case MODE: + clientMetaDataBuilder.withMock(value.contains(TRUE)); + break; default: break; } @@ -330,8 +335,7 @@ private void generateClient(ToolContext toolContext, ImmutablePair sources = generateClientFiles(clientConfig, toolContext, location, - codeGeneratorConfig.getLeft().isStatusCodeBinding()); + List sources = generateClientFiles(clientConfig, toolContext, location); Path outputPath = toolContext.outputPath(); writeGeneratedSources(sources, outputPath); // Update the cache file @@ -453,7 +457,8 @@ private static String getHashValue(OASClientConfig clientConfig, String targetPa .append(clientConfig.isResourceMode()) .append(clientConfig.getLicense()) .append(clientConfig.isNullable()) - .append(clientConfig.isStatusCodeBinding()); + .append(clientConfig.isStatusCodeBinding()) + .append(clientConfig.isMock()); List tags = clientConfig.getFilter().getTags(); tags.sort(String.CASE_INSENSITIVE_ORDER); for (String str : tags) { @@ -472,7 +477,7 @@ private static String getHashValue(OASClientConfig clientConfig, String targetPa * This will return list of (client.bal, util.bal, types.bal) {@code GenSrcFile}. */ private static List generateClientFiles(OASClientConfig oasClientConfig, ToolContext toolContext, - Location location, boolean statusCodeBinding) throws + Location location) throws BallerinaOpenApiException, IOException, FormatterException, ClientException { List sourceFiles = new ArrayList<>(); @@ -480,7 +485,7 @@ private static List generateClientFiles(OASClientConfig oasClientCon // Generate ballerina client files. TypeHandler.createInstance(oasClientConfig.getOpenAPI(), oasClientConfig.isNullable()); String licenseContent = oasClientConfig.getLicense(); - BallerinaClientGenerator ballerinaClientGenerator = getClientGenerator(oasClientConfig, statusCodeBinding); + BallerinaClientGenerator ballerinaClientGenerator = getClientGenerator(oasClientConfig); String mainContent = Formatter.format(ballerinaClientGenerator.generateSyntaxTree()).toString(); List clientDiagnostic = ballerinaClientGenerator.getDiagnostics(); @@ -526,12 +531,20 @@ private static List generateClientFiles(OASClientConfig oasClientCon return sourceFiles; } - private static BallerinaClientGenerator getClientGenerator(OASClientConfig oasClientConfig, - boolean statusCodeBinding) { - if (!statusCodeBinding) { - return new BallerinaClientGenerator(oasClientConfig); + private static BallerinaClientGenerator getClientGenerator(OASClientConfig oasClientConfig) { + boolean statusCodeBinding = oasClientConfig.isStatusCodeBinding(); + boolean isMock = oasClientConfig.isMock(); + + if (statusCodeBinding && isMock) { + return new AdvanceMockClientGenerator(oasClientConfig); + } + if (statusCodeBinding) { + return new BallerinaClientGeneratorWithStatusCodeBinding(oasClientConfig); + } + if (isMock) { + return new BallerinaMockClientGenerator(oasClientConfig); } - return new BallerinaClientGeneratorWithStatusCodeBinding(oasClientConfig); + return new BallerinaClientGenerator(oasClientConfig); } /** diff --git a/openapi-bal-task-plugin/src/main/resources/openapi-options-schema.json b/openapi-bal-task-plugin/src/main/resources/openapi-options-schema.json index 796d1f01f..e525592fa 100644 --- a/openapi-bal-task-plugin/src/main/resources/openapi-options-schema.json +++ b/openapi-bal-task-plugin/src/main/resources/openapi-options-schema.json @@ -28,6 +28,9 @@ }, "statusCodeBinding": { "type": "boolean" + }, + "mock": { + "type": "boolean" } }, "additionalProperties": false From 55157d8873fe5a30f2b65bc31703059038904e55 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 28 May 2024 11:06:57 +0530 Subject: [PATCH 03/15] [Automated] Update the toml files for client native tests --- openapi-client-native/ballerina-tests/Dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi-client-native/ballerina-tests/Dependencies.toml b/openapi-client-native/ballerina-tests/Dependencies.toml index f25a62a50..c7db50130 100644 --- a/openapi-client-native/ballerina-tests/Dependencies.toml +++ b/openapi-client-native/ballerina-tests/Dependencies.toml @@ -55,7 +55,7 @@ dependencies = [ [[package]] org = "ballerina" name = "crypto" -version = "2.7.0" +version = "2.7.1" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} From 54746a05a97f1753bcb6ef6bb460c8437699bf48 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 28 May 2024 11:32:51 +0530 Subject: [PATCH 04/15] Fix checkstyle issues --- .../bal/tool/OpenAPICodeGeneratorTool.java | 3 +- .../openapi/cmd/BallerinaCodeGenerator.java | 4 +- .../io/ballerina/openapi/cmd/OpenApiCmd.java | 2 +- .../ballerina/openapi/CodeGeneratorTest.java | 34 +++++++---- .../client/AdvanceMockClientGenerator.java | 61 ++++++++----------- .../client/BallerinaClientGenerator.java | 2 + ...aClientGeneratorWithStatusCodeBinding.java | 5 +- .../client/BallerinaMockClientGenerator.java | 21 +------ .../mock/MockClientFunctionGenerator.java | 56 +++++++++++++++-- .../mock/MockFunctionBodyGenerator.java | 54 +++++++++++++--- .../mock/MockImplFunctionBodyGenerator.java | 24 -------- 11 files changed, 154 insertions(+), 112 deletions(-) delete mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java diff --git a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java index 68744c988..ed3f1583a 100644 --- a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java +++ b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java @@ -79,6 +79,7 @@ import static io.ballerina.openapi.bal.tool.Constants.CLIENT; import static io.ballerina.openapi.bal.tool.Constants.CLIENT_METHODS; import static io.ballerina.openapi.bal.tool.Constants.LICENSE; +import static io.ballerina.openapi.bal.tool.Constants.MOCK; import static io.ballerina.openapi.bal.tool.Constants.MODE; import static io.ballerina.openapi.bal.tool.Constants.NULLABLE; import static io.ballerina.openapi.bal.tool.Constants.OPERATIONS; @@ -298,7 +299,7 @@ public static ImmutablePair extractOptionDe case STATUS_CODE_BINDING: clientMetaDataBuilder.withStatusCodeBinding(value.contains(TRUE)); break; - case MODE: + case MOCK: clientMetaDataBuilder.withMock(value.contains(TRUE)); break; default: diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java index adda01304..dfd290373 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java @@ -234,14 +234,14 @@ public static Predicate distinctByKey( * @throws BallerinaOpenApiException when code generator fails */ public void generateClient(String definitionPath, String outPath, Filter filter, boolean nullable, - boolean isResource, boolean statusCodeBinding) + boolean isResource, boolean statusCodeBinding, boolean isMock) throws IOException, FormatterException, BallerinaOpenApiException, OASTypeGenException { Path srcPath = Paths.get(outPath); Path implPath = getImplPath(srcPackage, srcPath); List genFiles = null; try { genFiles = generateClientFiles(Paths.get(definitionPath), filter, nullable, isResource, statusCodeBinding, - true); + isMock); if (!genFiles.isEmpty()) { writeGeneratedSources(genFiles, srcPath, implPath, GEN_CLIENT); } diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java index 9b28eb3ad..4e8ba83ee 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java @@ -410,7 +410,7 @@ private void generatesClientFile(BallerinaCodeGenerator generator, Path resource boolean resourceMode, boolean statusCodeBinding) { try { generator.generateClient(resourcePath.toString(), targetOutputPath.toString(), filter, baseCmd.nullable, - resourceMode, statusCodeBinding); + resourceMode, statusCodeBinding, mock); } catch (IOException | FormatterException | BallerinaOpenApiException | OASTypeGenException e) { if (e.getLocalizedMessage() != null) { diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/CodeGeneratorTest.java b/openapi-cli/src/test/java/io/ballerina/openapi/CodeGeneratorTest.java index 1ba21a66b..0917cd946 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/CodeGeneratorTest.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/CodeGeneratorTest.java @@ -99,7 +99,7 @@ public void generateClient() { try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "generate_client.bal"); generator.generateClient(definitionPath, resourcePath.toString(), filter, - false, false, false); + false, false, false, false); if (Files.exists(resourcePath.resolve("client.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "client.bal"); generatedClient = (generatedClient.trim()).replaceAll("\\s+", ""); @@ -152,7 +152,8 @@ public void generateClientForOAS2() { try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "petstore_client_swagger.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, false, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, false, false, + false, false); if (Files.exists(resourcePath.resolve("client.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "client.bal"); generatedClient = (generatedClient.trim()).replaceAll("\\s+", ""); @@ -204,7 +205,8 @@ public void generateClientWithInitDocComments() { BallerinaCodeGenerator generator = new BallerinaCodeGenerator(); try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "x_init_description.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, false, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, false, false, + false, false); if (Files.exists(resourcePath.resolve("client.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "client.bal"); @@ -228,7 +230,8 @@ public void generateTypesWithNullableFields() { BallerinaCodeGenerator generator = new BallerinaCodeGenerator(); try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "nullable_types.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, + false, false); if (Files.exists(resourcePath.resolve("types.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "types.bal"); @@ -252,7 +255,8 @@ public void generateTypesWithNullableFieldsAndGlobalNullableTrue() { BallerinaCodeGenerator generator = new BallerinaCodeGenerator(); try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "nullable_false_types.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, + false, false); if (Files.exists(resourcePath.resolve("types.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "types.bal"); @@ -276,7 +280,8 @@ public void generateUtilsFile() { BallerinaCodeGenerator generator = new BallerinaCodeGenerator(); try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "utils.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, + false, false); if (Files.exists(resourcePath.resolve("utils.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "utils.bal"); @@ -301,7 +306,8 @@ public void generateConfigFile() { try { String expectedConfigContent = getStringFromGivenBalFile(expectedDirPath, "api_key_config.toml"); generator.setIncludeTestFiles(true); - generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, true, false, + false, false); if (Files.exists(resourcePath.resolve("tests/Config.toml"))) { String generateConfigContent = getStringFromGivenBalFile(resourcePath, "tests/Config.toml"); @@ -331,7 +337,7 @@ public void generateFilteredClient() { String expectedSchemaContent = getStringFromGivenBalFile(expectedDirPath, "type_filtered_by_tags.bal"); generator.generateClient(definitionPath, resourcePath.toString(), filterCustom, - false, false, false); + false, false, false, false); if (Files.exists(resourcePath.resolve("client.bal")) && Files.exists(resourcePath.resolve("types.bal"))) { String generatedSchema = getStringFromGivenBalFile(resourcePath, "types.bal"); @@ -356,7 +362,8 @@ public void generateClientwithRequestBody() { try { String expectedClientContent = getStringFromGivenBalFile(expectedDirPath, "generate_client_requestbody.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, false, false, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, false, false, + false, false); if (Files.exists(resourcePath.resolve("client.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "client.bal"); @@ -441,7 +448,8 @@ public void generateClientForResourceWithCatchAllPath() { try { String expectedClientContent = getStringFromGivenBalFile( expectedDirPath, "petstore_catch_all_path_client.bal"); - generator.generateClient(definitionPath, resourcePath.toString(), filter, false, true, false); + generator.generateClient(definitionPath, resourcePath.toString(), filter, false, true, false, + false); if (Files.exists(resourcePath.resolve("client.bal"))) { String generatedClient = getStringFromGivenBalFile(resourcePath, "client.bal"); generatedClient = (generatedClient.trim()).replaceAll("\\s+", ""); @@ -698,7 +706,8 @@ public void testForInvalidDefinition() throws IOException, BallerinaOpenApiExcep FormatterException { String definitionPath = RES_DIR.resolve("invalid_petstore.yaml").toString(); BallerinaCodeGenerator generator = new BallerinaCodeGenerator(); - generator.generateClient(definitionPath, "", filter, false, false, false); + generator.generateClient(definitionPath, "", filter, false, false, + false, false); } @Test(description = "Functionality tests when swagger 1.2 contract is given as input", @@ -709,7 +718,8 @@ public void testGenerationForUnsupportedOpenAPIVersion() throws IOException, Bal OASTypeGenException, FormatterException { String definitionPath = RES_DIR.resolve("petstore_swagger_1.2.json").toString(); BallerinaCodeGenerator generator = new BallerinaCodeGenerator(); - generator.generateClient(definitionPath, "", filter, false, false, false); + generator.generateClient(definitionPath, "", filter, false, false, + false, false); } @Test diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java index ba73620f8..0512915d8 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package io.ballerina.openapi.core.generators.client; import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; @@ -46,11 +64,13 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURN_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; +/** + * This class iss contain the advance client generation when the client generation enable with status code bindings. + * @since 2.1.0 + */ public class AdvanceMockClientGenerator extends BallerinaClientGeneratorWithStatusCodeBinding { - OASClientConfig oasClientConfig; public AdvanceMockClientGenerator(OASClientConfig oasClientConfig) { super(oasClientConfig); - this.oasClientConfig = oasClientConfig; } @Override @@ -70,41 +90,6 @@ public FunctionDefinitionNode createInitFunction() { functionBodyNode); } -// //override client function generation -// public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException { -// // Collect members for class definition node -// List memberNodeList = new ArrayList<>(); -// // Add instance variable to class definition node -// memberNodeList.addAll(createClassInstanceVariables()); -// // Add init function to class definition node -// memberNodeList.add(getInitFunction()); -// Map> filteredOperations = filterOperations(); -// //switch resource remote -// List functionDefinitionNodeList = new ArrayList<>(); -// //Mock cleint function generation -// -// for (Map.Entry> operation : filteredOperations.entrySet()) { -// for (Map.Entry operationEntry : operation.getValue().entrySet()) { -//// Optional funDefOptionalNode = createImplFunction(path, operationEntry, -// openAPI, clie); -//// if (funDefOptionalNode.isPresent()) { -//// functionDefinitionNodeList.add(funDefOptionalNode.get()); -//// } -// } -// } -// memberNodeList.addAll(functionDefinitionNodeList); -// // Generate the class combining members -// MetadataNode metadataNode = getClassMetadataNode(); -// IdentifierToken className = createIdentifierToken(GeneratorConstants.CLIENT); -// NodeList classTypeQualifiers = createNodeList( -// createToken(ISOLATED_KEYWORD), createToken(CLIENT_KEYWORD)); -// return createClassDefinitionNode(metadataNode, createToken(PUBLIC_KEYWORD), classTypeQualifiers, -// createToken(CLASS_KEYWORD), className, createToken(OPEN_BRACE_TOKEN), -// createNodeList(memberNodeList), createToken(CLOSE_BRACE_TOKEN), null); -// -// } - - @Override protected List getModuleMemberDeclarationNodes() throws BallerinaOpenApiException { List nodes = new ArrayList<>(); @@ -132,12 +117,14 @@ protected void addClientFunctionImpl(Map.Entry imports = new ArrayList<>(); private List apiKeyNameList = new ArrayList<>(); @@ -173,6 +174,7 @@ public BallerinaClientGenerator(OASClientConfig oasClientConfig) { this.remoteFunctionNameList = new ArrayList<>(); this.authConfigGeneratorImp = new AuthConfigGeneratorImp(false, false); this.resourceMode = oasClientConfig.isResourceMode(); + this.oasClientConfig = oasClientConfig; } /** diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java index 4dafabf21..a512d3a97 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java @@ -115,11 +115,10 @@ * @since 1.9.0 */ public class BallerinaClientGeneratorWithStatusCodeBinding extends BallerinaClientGenerator { - OASClientConfig oasClientConfig; + public BallerinaClientGeneratorWithStatusCodeBinding(OASClientConfig oasClientConfig) { super(oasClientConfig); authConfigGeneratorImp = new AuthConfigGeneratorWithStatusCodeBinding(false, false); - this.oasClientConfig = oasClientConfig; } /** @@ -228,10 +227,10 @@ protected Optional createImplFunction(String path, MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, true); Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); + diagnostics.addAll(bodyGenerator.getDiagnostics()); if (functionBodyOptionalNode.isEmpty()) { return Optional.empty(); } - diagnostics.addAll(bodyGenerator.getDiagnostics()); functionBodyNode = bodyGenerator.getFunctionBodyNode().get(); } else { FunctionBodyGeneratorImp functionBodyGenerator = new ImplFunctionBodyGenerator(path, operation, openAPI, diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java index 34bc8b950..971658d02 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java @@ -53,10 +53,8 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; public class BallerinaMockClientGenerator extends BallerinaClientGenerator { - OASClientConfig oasClientConfig; public BallerinaMockClientGenerator(OASClientConfig oasClientConfig) { super(oasClientConfig); - this.oasClientConfig = oasClientConfig; } //override init function generation @@ -78,29 +76,22 @@ public FunctionDefinitionNode getInitFunction() { //override client function generation public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException { - // Collect members for class definition node List memberNodeList = new ArrayList<>(); - // Add instance variable to class definition node memberNodeList.addAll(createClassInstanceVariables()); - // Add init function to class definition node memberNodeList.add(getInitFunction()); Map> filteredOperations = filterOperations(); - //switch resource remote List functionDefinitionNodeList = new ArrayList<>(); - //Mock cleint function generation - + //Mock client function generation for (Map.Entry> operation : filteredOperations.entrySet()) { for (Map.Entry operationEntry : operation.getValue().entrySet()) { MockClientFunctionGenerator mockClientFunctionGenerator = new MockClientFunctionGenerator( operation.getKey(), operationEntry, oasClientConfig); Optional funDefOptionalNode = mockClientFunctionGenerator.generateFunction(); - if (funDefOptionalNode.isPresent()) { - functionDefinitionNodeList.add(funDefOptionalNode.get()); - } + funDefOptionalNode.ifPresent(functionDefinitionNodeList::add); + diagnostics.addAll(mockClientFunctionGenerator.getDiagnostics()); } } memberNodeList.addAll(functionDefinitionNodeList); - // Generate the class combining members MetadataNode metadataNode = getClassMetadataNode(); IdentifierToken className = createIdentifierToken(GeneratorConstants.CLIENT); NodeList classTypeQualifiers = createNodeList( @@ -125,14 +116,9 @@ protected List getModuleMemberDeclarationNodes() th * @throws BallerinaOpenApiException When function fail in process. */ public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException { - - // Create `ballerina/http` import declaration node List importForHttp = getImportDeclarationNodes(); imports.addAll(importForHttp); - - // Add authentication related records authConfigGeneratorImp.addAuthRelatedRecords(openAPI); - List nodes = getModuleMemberDeclarationNodes(); NodeList importsList = createNodeList(imports); ModulePartNode modulePartNode = @@ -140,7 +126,6 @@ public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientE TextDocument textDocument = TextDocuments.from(""); SyntaxTree syntaxTree = SyntaxTree.from(textDocument); syntaxTree = syntaxTree.modifyWith(modulePartNode); - //Add comments ClientDocCommentGenerator clientDocCommentGenerator = new ClientDocCommentGenerator(syntaxTree, openAPI, oasClientConfig.isResourceMode()); return clientDocCommentGenerator.updateSyntaxTreeWithDocComments(); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java index 553bcec24..89d7c2c67 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package io.ballerina.openapi.core.generators.client.mock; import io.ballerina.compiler.syntax.tree.FunctionBodyNode; @@ -9,6 +27,7 @@ import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.Token; import io.ballerina.openapi.core.generators.client.FunctionGenerator; +import io.ballerina.openapi.core.generators.client.RemoteFunctionSignatureGenerator; import io.ballerina.openapi.core.generators.client.ResourceFunctionSignatureGenerator; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; @@ -27,14 +46,21 @@ import java.util.Map; import java.util.Optional; +import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.OBJECT_METHOD_DEFINITION; +import static io.ballerina.compiler.syntax.tree.SyntaxKind.REMOTE_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.RESOURCE_ACCESSOR_DEFINITION; import static io.ballerina.compiler.syntax.tree.SyntaxKind.RESOURCE_KEYWORD; +/** + * Mock client function generator. + * @since 2.1.0 + */ public class MockClientFunctionGenerator implements FunctionGenerator { String path; Map.Entry operation; @@ -89,22 +115,44 @@ public Optional generateFunction() throws BallerinaOpenA MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, oasClientConfig.isStatusCodeBinding()); Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); + diagnostics.addAll(bodyGenerator.getDiagnostics()); if (functionBodyOptionalNode.isEmpty()) { return Optional.empty(); } - diagnostics.addAll(bodyGenerator.getDiagnostics()); FunctionBodyNode functionBodyNode = functionBodyOptionalNode.get(); return Optional.of(NodeFactory.createFunctionDefinitionNode(RESOURCE_ACCESSOR_DEFINITION, null, qualifierList, functionKeyWord, functionName, relativeResourcePath, signatureNode, functionBodyNode)); } else { - //function signature node, remote, resource + //Create qualifier list + NodeList qualifierList = createNodeList(createToken(REMOTE_KEYWORD), createToken(ISOLATED_KEYWORD)); + Token functionKeyWord = createToken(FUNCTION_KEYWORD); + IdentifierToken functionName = createIdentifierToken(operation.getValue().getOperationId()); + + RemoteFunctionSignatureGenerator signatureGenerator = new RemoteFunctionSignatureGenerator( + operation.getValue(), openAPI, operation.getKey().toString().toLowerCase(Locale.ENGLISH), path); + diagnostics.addAll(signatureGenerator.getDiagnostics()); + Optional signatureNodeOptional = signatureGenerator.generateFunctionSignature(); + if (signatureNodeOptional.isEmpty()) { + return Optional.empty(); + } + FunctionSignatureNode functionSignatureNode = signatureNodeOptional.get(); + MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, + oasClientConfig.isStatusCodeBinding()); + Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); + diagnostics.addAll(bodyGenerator.getDiagnostics()); + if (functionBodyOptionalNode.isEmpty()) { + return Optional.empty(); + } + FunctionBodyNode functionBodyNode = functionBodyOptionalNode.get(); + return Optional.of(NodeFactory.createFunctionDefinitionNode(OBJECT_METHOD_DEFINITION, null, + qualifierList, functionKeyWord, functionName, createEmptyNodeList(), functionSignatureNode, + functionBodyNode)); } - return Optional.empty(); } @Override public List getDiagnostics() { - return null; + return diagnostics; } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java index 3fbd72a7b..39fb0d893 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java @@ -1,3 +1,21 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package io.ballerina.openapi.core.generators.client.mock; import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; @@ -9,6 +27,8 @@ import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages; +import io.ballerina.openapi.core.generators.common.GeneratorUtils; +import io.ballerina.openapi.core.generators.common.exception.InvalidReferenceException; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -18,6 +38,7 @@ import io.swagger.v3.oas.models.responses.ApiResponses; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -30,6 +51,7 @@ /** * Mock function body generator. + * * @since 2.1.0 */ public class MockFunctionBodyGenerator implements FunctionBodyGenerator { @@ -66,29 +88,41 @@ public Optional getFunctionBodyNode() { return Optional.empty(); } // Get the example - Map examples = null; + Map examples = new HashMap<>(); for (Map.Entry mediaType : successResponse.getContent().entrySet()) { // handle reference if (mediaType.getValue().getExamples() != null) { examples = mediaType.getValue().getExamples(); } + if (mediaType.getValue().getExample() != null) { + Example example = (Example) mediaType.getValue().getExample(); + examples.put("response", example); + } } - // check ref example - if (examples == null) { + if (examples.isEmpty()) { ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_116, path, operation.getKey().toString()); diagnostics.add(diagnosticImp); return Optional.empty(); } - Object response = examples.get("response"); - if (response == null) { - ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_116, - path, operation.getKey().toString()); - diagnostics.add(diagnosticImp); - return Optional.empty(); + + Example example = examples.get("response"); + if (example == null) { + //when the example has key value which is not capture via response + example = examples.values().iterator().next(); + } + + if (example.get$ref() != null) { + try { + String exampleName = GeneratorUtils.extractReferenceType(example.get$ref()); + Map exampleMap = openAPI.getComponents().getExamples(); + example = exampleMap.get(exampleName); + } catch (InvalidReferenceException e) { + return Optional.empty(); + } } - String exampleValue = ((Example) response).getValue().toString(); + String exampleValue = example.getValue().toString(); String statement; if (isAdvanceClient) { statement = "return {\n" + diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java deleted file mode 100644 index 043f16477..000000000 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockImplFunctionBodyGenerator.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.ballerina.openapi.core.generators.client.mock; - -import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; -import io.ballerina.openapi.core.generators.client.AuthConfigGeneratorImp; -import io.ballerina.openapi.core.generators.client.BallerinaUtilGenerator; -import io.ballerina.openapi.core.generators.client.ImplFunctionBodyGenerator; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; - -import java.util.List; -import java.util.Map; - -public class MockImplFunctionBodyGenerator extends ImplFunctionBodyGenerator { - public MockImplFunctionBodyGenerator(String path, Map.Entry operation, - OpenAPI openAPI, AuthConfigGeneratorImp ballerinaAuthConfigGeneratorImp, - BallerinaUtilGenerator ballerinaUtilGenerator, - List imports, boolean hasHeaders, - boolean hasDefaultHeaders, boolean hasQueries) { - super(path, operation, openAPI, ballerinaAuthConfigGeneratorImp, ballerinaUtilGenerator, - imports, hasHeaders, hasDefaultHeaders, hasQueries); - } - -} From e308eb21c006c3b8f8476b3364db9653b43041d1 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 29 May 2024 08:32:07 +0530 Subject: [PATCH 05/15] Add more tests --- .../client/MockClientGenerationTests.java | 86 +- .../client/mock/basic_response_example.yaml | 66 - .../mock_client_for_advance_return_type.bal | 276 ++ .../client/mock/mock_client_for_remote.bal | 145 + .../generators/client/mock/ref_example.json | 2437 +++++++++++++++++ .../client/mock/reference_example.bal | 88 + .../client/BallerinaMockClientGenerator.java | 22 + .../client/model/OASClientConfig.java | 2 +- 8 files changed, 3042 insertions(+), 80 deletions(-) create mode 100644 openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal create mode 100644 openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal create mode 100644 openapi-cli/src/test/resources/generators/client/mock/ref_example.json create mode 100644 openapi-cli/src/test/resources/generators/client/mock/reference_example.bal diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java index c7b310fa1..30ce99c9b 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java @@ -1,12 +1,36 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package io.ballerina.openapi.generators.client; import io.ballerina.compiler.syntax.tree.FunctionBodyNode; +import io.ballerina.compiler.syntax.tree.SyntaxTree; +import io.ballerina.openapi.core.generators.client.AdvanceMockClientGenerator; +import io.ballerina.openapi.core.generators.client.BallerinaMockClientGenerator; +import io.ballerina.openapi.core.generators.client.exception.ClientException; import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator; +import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.TypeHandler; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; +import org.testng.Assert; import org.testng.annotations.Test; import java.io.IOException; @@ -17,8 +41,12 @@ import java.util.Optional; import java.util.Set; +import static io.ballerina.openapi.generators.common.GeneratorTestUtils.compareGeneratedSyntaxTreeWithExpectedSyntaxTree; import static io.ballerina.openapi.generators.common.GeneratorTestUtils.getOpenAPI; +/** + * Test for mock client generation. + */ public class MockClientGenerationTests { private static final Path RES_DIR = Paths.get("src/test/resources/generators/client/mock").toAbsolutePath(); @Test @@ -36,25 +64,57 @@ public void mockClientTest() throws IOException, BallerinaOpenApiException { false); Optional functionBodyNode = mockFunctionBodyGenerator.getFunctionBodyNode(); FunctionBodyNode body = functionBodyNode.get(); - String string = body.toString(); + String node = body.toString(); + Assert.assertEquals("{return {\"success\":true,\"size\":3,\"schedules\":[{\"id\":6,\"status\":\"Active\",\"filter\":\"Account.BillCycleDay = 8\",\"schedule\":\"At 6:00 AM, only on Monday and Tuesday\"}]};}", node); } @Test - public void mockClientTestWithReferenceExample() throws IOException, BallerinaOpenApiException { - Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); + public void mockClientTestWithReferenceExample() throws IOException, BallerinaOpenApiException, ClientException { + Path definitionPath = RES_DIR.resolve("ref_example.json"); + Path expectedPath = RES_DIR.resolve("file_provider/ballerina/reference_example.bal"); OpenAPI openapi = getOpenAPI(definitionPath); TypeHandler.createInstance(openapi, false); - String path = "/api/v1/payment_run_schedules"; - Set> pathItem = openapi.getPaths().get(path). - readOperationsMap().entrySet(); - Iterator> iterator = pathItem.iterator(); - Map.Entry operation = iterator.next(); + OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); + OASClientConfig oasClientConfig = clientMetaDataBuilder + .withPlugin(false) + .withOpenAPI(openapi) + .withMock(true).build(); + BallerinaMockClientGenerator mockClientGenerator = new BallerinaMockClientGenerator(oasClientConfig); + SyntaxTree syntaxTree = mockClientGenerator.generateSyntaxTree(); + compareGeneratedSyntaxTreeWithExpectedSyntaxTree(expectedPath, syntaxTree); + } - MockFunctionBodyGenerator mockFunctionBodyGenerator = new MockFunctionBodyGenerator(path, operation, openapi, - false); - Optional functionBodyNode = mockFunctionBodyGenerator.getFunctionBodyNode(); - FunctionBodyNode body = functionBodyNode.get(); - String string = body.toString(); + @Test + public void mockClientForRemoteFunction() throws IOException, BallerinaOpenApiException, ClientException { + Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); + Path expectedPath = RES_DIR.resolve("file_provider/ballerina/mock_client_for_remote.bal"); + OpenAPI openapi = getOpenAPI(definitionPath); + TypeHandler.createInstance(openapi, false); + OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); + OASClientConfig oasClientConfig = clientMetaDataBuilder + .withPlugin(false) + .withOpenAPI(openapi) + .withResourceMode(false) + .withMock(true).build(); + BallerinaMockClientGenerator mockClientGenerator = new BallerinaMockClientGenerator(oasClientConfig); + SyntaxTree syntaxTree = mockClientGenerator.generateSyntaxTree(); + compareGeneratedSyntaxTreeWithExpectedSyntaxTree(expectedPath, syntaxTree); + } + @Test + public void advanceMockClientGenerator() throws IOException, BallerinaOpenApiException, ClientException { + Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); + Path expectedPath = RES_DIR.resolve("file_provider/ballerina/mock_client_for_advance_return_type.bal"); + OpenAPI openapi = getOpenAPI(definitionPath); + TypeHandler.createInstance(openapi, false); + OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); + OASClientConfig oasClientConfig = clientMetaDataBuilder + .withPlugin(false) + .withOpenAPI(openapi) + .withMock(true).build(); + AdvanceMockClientGenerator mockClientGenerator = new AdvanceMockClientGenerator(oasClientConfig); + SyntaxTree syntaxTree = mockClientGenerator.generateSyntaxTree(); + compareGeneratedSyntaxTreeWithExpectedSyntaxTree(expectedPath, syntaxTree); } + } diff --git a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml index 4bc4ef534..e98720a08 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml +++ b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml @@ -2,78 +2,12 @@ openapi: 3.0.0 info: version: 2021-08 title: 'API Reference: Collections' - x-logo: - url: >- - https://www.zuora.com/wp-content/uploads/2016/10/zuora-dev-logo-api-ref.svg - description: > - This is a generated connector for [Zuora Collections API V1](https://www.zuora.com/developer/collect-api/#) OpenAPI specification. - - This reference provides detailed descriptions about functions, requests, and responses of - the APIs for the following two component apps. Rest APIs for other component - apps will be included in this reference when they are released. - - - Advanced Payment Manager - - - Collections Window - - - Configurable Payment Retry - - - Statement Generator - x-ballerina-init-description: > - The connector initialization requires setting the API credentials. - - Create a [Zuora account](https://www.zuora.com/) and obtain tokens by following [this guide](https://www.zuora.com/developer/collect-api/#section/Authentication). - x-ballerina-display: - label: Zuora Collection - iconPath: "icon.png" tags: - name: Advanced Payment Manager - description: > - Advanced Payment Manager APIs use basic authentication. The user name is - the email address that you use for logging in Zuora. The password is the - API token that is shown in the settings of Advanced Payment Manager. - - Before you use the APIs, ensure that you have completed the initial - configurations of Advanced Payment Manager. To learn more about the - configuration and usage of Advanced Payment Manager, see [Advanced Payment - Manager](https://knowledgecenter.zuora.com/CE_Collect/CA_Advanced_Payment_Manager). - name: Collections Window - description: > - Collections Window APIs use basic authentication. The user name is the - email address that you use for logging in Zuora. The password is the API - token that is shown in the settings of Collections Window. - - To learn more about the configuration and usage of Collections Window, see - [Collections - Window](https://knowledgecenter.zuora.com/CE_Collect/Collections_Window). - name: Configurable Payment Retry - description: > - Configurable Payment Retry APIs use basic authentication. The user name is - the email address that you use for logging in Zuora. The password is the - API token that is shown in the settings of Configurable Payment Retry. - - To learn more about the configuration and usage of Configurable Payment - Retry, see [Configurable Payment - Retry](https://knowledgecenter.zuora.com/CE_Collect/Configurable_Payment_Retry). - name: Notes - description: > - Notes APIs use API-token only for authentication. You need to use - "API-Token" as the header key and the api token that is shown in the - Setting of Notes as the value. - - To learn more about the configuration and usage of Notes, see - [Notes](https://knowledgecenter.zuora.com/CE_Collect/Notes). - name: Statement Generator - description: > - - Statement Generator APIs use basic authentication. The user name is the - email address that you use for logging in Zuora. The password is the API - token that is shown in the settings of Statement Generator. - - To learn more about the configuration and usage of Statement Generator, - see [Statement - Generator](https://knowledgecenter.zuora.com/CE_Collect/Statement_Generator). - description: The number of accounts that have paid in full. security: - BasicAuth: [] paths: diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal new file mode 100644 index 000000000..71070c5d5 --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal @@ -0,0 +1,276 @@ +import ballerina/http; +import ballerina/jballerina.java; + +function setModule() = @java:Method {'class: "io.ballerina.openapi.client.ModuleUtils"} external; + +function init() { + setModule(); +} + +type ClientMethodImpl record {| + string name; +|}; + +annotation ClientMethodImpl MethodImpl on function; + +type ClientMethodInvocationError http:ClientError; + +function setModule() = @java:Method {'class: "io.ballerina.openapi.client.ModuleUtils"} external; + +function init() { + setModule(); +} + +type ClientMethodImpl record {| + string name; +|}; + +annotation ClientMethodImpl MethodImpl on function; + +type ClientMethodInvocationError http:ClientError; + +@display {label: "Zuora Collection", iconPath: "icon.png"} +public isolated client class Client { + final http:StatusCodeClient clientEp; + # Gets invoked to initialize the `connector`. + # The connector initialization requires setting the API credentials. + # Create a [Zuora account](https://www.zuora.com/) and obtain tokens by following [this guide](https://www.zuora.com/developer/collect-api/#section/Authentication). + # + # + config - The configurations to be used when initializing the `connector` + # + serviceUrl - URL of the target service + # + return - An error if connector initialization failed + public isolated function init(ConnectionConfig config, string serviceUrl) returns error? { + return; + } + + # Update account agent + # + # + account_id - The account ID. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + @MethodImpl {name: "UpdateAccountAgentImpl"} + resource isolated function post api/v1/accounts/[string account_id]/update_agent(map headers = {}, typedesc targetType = <>, *UpdateAccountAgentQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Update account status + # + # + account_id - The account ID. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + @MethodImpl {name: "UpdateAccountImpl"} + resource isolated function post api/v1/accounts/[string account_id]/update_status(map headers = {}, typedesc targetType = <>, *UpdateAccountQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Create an ad hoc statement run + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "createAdhocStatementRunImpl"} + resource isolated function post api/v1/run(POSTAdhocStatementRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Create a custom statement run + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "createCustomStatementRunImpl"} + resource isolated function post api/v1/execute(POSTCustomStatementRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Create a payment run + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "createPaymentRunImpl"} + resource isolated function post api/v1/subscription_payment_runs(POSTPaymentRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Create a payment run schedule + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "createPaymentRunScheduleImpl"} + resource isolated function post api/v1/payment_run_schedules(POSTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Cancel a payment run schedule + # + # + schedule_id - The schedule ID + # + headers - Headers to be sent with the request + @MethodImpl {name: "deletePaymentRunScheduleImpl"} + resource isolated function delete api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get an account + # + # + account_id - The account ID. + # + headers - Headers to be sent with the request + @MethodImpl {name: "getAccountImpl"} + resource isolated function get api/v1/accounts/[string account_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get all accounts + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getAccountsImpl"} + resource isolated function get api/v1/accounts(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Get a collections agent by email + # + # + email - The email of the collections agent. + # + headers - Headers to be sent with the request + @MethodImpl {name: "getCollectionsAgentImpl"} + resource isolated function get api/v1/users/[string email](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get all collections agents + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getCollectionsAgentsImpl"} + resource isolated function get api/v1/users(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Get an overview of collections + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getCollectionsInfoImpl"} + resource isolated function get api/v1/collections_info(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Get a payment run + # + # + payment_run_id - The payment run ID. A payment run id in Advanced Payment Manager is different from a payment run id in Zuora. + # + headers - Headers to be sent with the request + @MethodImpl {name: "getPaymentRunImpl"} + resource isolated function get api/v1/subscription_payment_runs/[int payment_run_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get a payment run schedule + # + # + schedule_id - The schedule ID + # + headers - Headers to be sent with the request + @MethodImpl {name: "getPaymentRunScheduleImpl"} + resource isolated function get api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get all payment run schedules + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getPaymentRunSchedulesImpl"} + resource isolated function get api/v1/payment_run_schedules(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Get Statement Generator settings + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getSettingsImpl"} + resource isolated function get api/v1/fetch_settings(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Update a payment run schedule + # + # + schedule_id - The schedule ID + # + headers - Headers to be sent with the request + @MethodImpl {name: "updatePaymentRunScheduleImpl"} + resource isolated function put api/v1/payment_run_schedules/[int schedule_id](PUTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + private isolated function UpdateAccountAgentImpl(string account_id, map headers, typedesc targetType, *UpdateAccountAgentQueries queries) returns OkInline_response_200|error { + return { + body: {"success": true}, + headers: {} + }; + } + + private isolated function UpdateAccountImpl(string account_id, map headers, typedesc targetType, *UpdateAccountQueries queries) returns OkInline_response_200|error { + return { + body: {"success": true}, + headers: {} + }; + } + + private isolated function createAdhocStatementRunImpl(POSTAdhocStatementRun payload, map headers, typedesc targetType) returns OkPOSTAdhocStatementRunResponse|error { + return { + body: {"success": true, "code": 200, "message": "Success", "statement_number": "STA00000008"}, + headers: {} + }; + } + + private isolated function createCustomStatementRunImpl(POSTCustomStatementRun payload, map headers, typedesc targetType) returns OkPOSTCustomStatementRunResponse|error { + return { + body: {"success": true, "code": 200, "message": "Success", "execution_number": "2", "report_file": ""}, + headers: {} + }; + } + + private isolated function createPaymentRunImpl(POSTPaymentRun payload, map headers, typedesc targetType) returns OkPostpaymentrunresponseJson|error { + return { + body: {"id": 6, "success": "true"}, + headers: {} + }; + } + + private isolated function createPaymentRunScheduleImpl(POSTPaymentRunSchedule payload, map headers, typedesc targetType) returns OkPostpaymentrunscheduleresponseJson|error { + return { + body: {"id": 6, "success": "true"}, + headers: {} + }; + } + + private isolated function deletePaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns OkDELETEPaymentRunScheduleResponse|error { + return { + body: {"success": true}, + headers: {} + }; + } + + private isolated function getAccountImpl(string account_id, map headers, typedesc targetType) returns OkCollectionAccount|error { + return { + body: {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}}, + headers: {} + }; + } + + private isolated function getAccountsImpl(map headers, typedesc targetType) returns OkGETCollectionAccountsResponse|error { + return { + body: {"accounts": [{"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": 0, "Pending": 0, "In Dispute": 0, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20"}}, + headers: {} + }; + } + + private isolated function getCollectionsAgentImpl(string email, map headers, typedesc targetType) returns OkCollectionAgent|error { + return { + body: {"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}, + headers: {} + }; + } + + private isolated function getCollectionsAgentsImpl(map headers, typedesc targetType) returns OkGETCollectionAgentsResponse|error { + return { + body: {"accounts": [{"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20"}}, + headers: {} + }; + } + + private isolated function getCollectionsInfoImpl(map headers, typedesc targetType) returns OkCollectionsInfo|error { + return { + body: {"accounts_in_collections": 24, "home_currency": "USD", "total_debt": "8379.78", "largest_debts": ["Test Account - 12438.00 USD", "Jimmy John - 8000.00 USD", "James Smith - 2450.55 USD", "Bob Roberts - 1000.00 USD", "Jim Reynolds - 829.00 USD"], "oldest_debts": ["Test Account - 2662 days", "Jimbo - 1494 days", "Steve Smith - 942 days", "Jason Williams - 678 days", "Will Jasons - 365 days"], "statuses": {"In Collections": 24, "Pending": 2, "In Dispute": 5, "Paid in Full": 0}}, + headers: {} + }; + } + + private isolated function getPaymentRunImpl(int payment_run_id, map headers, typedesc targetType) returns OkGETPaymentRunResponse|error { + return { + body: {"success": true, "id": 6, "status": "Complete", "target_date": "2018-01-02T00:00:00.000Z", "filter": "Account.Currency = 'CAD'", "payment_run_schedule_id": "Adhoc", "invoices_held": {}, "metrics": {"documents": 0, "payments": 0, "failed": 0, "skipped": 0, "amount": 0, "credit": 0}}, + headers: {} + }; + } + + private isolated function getPaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns OkGETPaymentRunScheduleResponse|error { + return { + body: {"success": true, "id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}, + headers: {} + }; + } + + private isolated function getPaymentRunSchedulesImpl(map headers, typedesc targetType) returns OkGETPaymentRunSchedulesResponse|error { + return { + body: {"success": true, "size": 3, "schedules": [{"id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}]}, + headers: {} + }; + } + + private isolated function getSettingsImpl(map headers, typedesc targetType) returns OkGETStatementSettingsResponse|error { + return { + body: {"success": true, "templates": [{"name": "Default Template"}, {"name": "Template for end consumers"}], "default_template": "Default Template", "default_cycle": "Month"}, + headers: {} + }; + } + + private isolated function updatePaymentRunScheduleImpl(int schedule_id, PUTPaymentRunSchedule payload, map headers, typedesc targetType) returns OkPOSTPaymentRunScheduleResponse|error { + return { + body: {"id": 6, "success": true}, + headers: {} + }; + } +} diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal new file mode 100644 index 000000000..db6461540 --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal @@ -0,0 +1,145 @@ +import ballerina/http; + +@display {label: "Zuora Collection", iconPath: "icon.png"} +public isolated client class Client { + final http:Client clientEp; + # Gets invoked to initialize the `connector`. + # The connector initialization requires setting the API credentials. + # Create a [Zuora account](https://www.zuora.com/) and obtain tokens by following [this guide](https://www.zuora.com/developer/collect-api/#section/Authentication). + # + # + config - The configurations to be used when initializing the `connector` + # + serviceUrl - URL of the target service + # + return - An error if connector initialization failed + public isolated function init(ConnectionConfig config, string serviceUrl) returns error? { + return; + } + + # Update account status + # + # + account_id - The account ID. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + remote isolated function UpdateAccount(string account_id, map headers = {}, *UpdateAccountQueries queries) returns inline_response_200|error { + return {"success": true}; + } + + # Update account agent + # + # + account_id - The account ID. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + remote isolated function UpdateAccountAgent(string account_id, map headers = {}, *UpdateAccountAgentQueries queries) returns inline_response_200|error { + return {"success": true}; + } + + # Create an ad hoc statement run + # + # + headers - Headers to be sent with the request + remote isolated function createAdhocStatementRun(POSTAdhocStatementRun payload, map headers = {}) returns POSTAdhocStatementRunResponse|error { + return {"success": true, "code": 200, "message": "Success", "statement_number": "STA00000008"}; + } + + # Create a custom statement run + # + # + headers - Headers to be sent with the request + remote isolated function createCustomStatementRun(POSTCustomStatementRun payload, map headers = {}) returns POSTCustomStatementRunResponse|error { + return {"success": true, "code": 200, "message": "Success", "execution_number": "2", "report_file": ""}; + } + + # Create a payment run + # + # + headers - Headers to be sent with the request + remote isolated function createPaymentRun(POSTPaymentRun payload, map headers = {}) returns POSTPaymentRunResponse|error { + return {"id": 6, "success": "true"}; + } + + # Create a payment run schedule + # + # + headers - Headers to be sent with the request + remote isolated function createPaymentRunSchedule(POSTPaymentRunSchedule payload, map headers = {}) returns POSTPaymentRunScheduleResponse|error { + return {"id": 6, "success": "true"}; + } + + # Cancel a payment run schedule + # + # + schedule_id - The schedule ID + # + headers - Headers to be sent with the request + remote isolated function deletePaymentRunSchedule(int schedule_id, map headers = {}) returns DELETEPaymentRunScheduleResponse|error { + return {"success": true}; + } + + # Get an account + # + # + account_id - The account ID. + # + headers - Headers to be sent with the request + remote isolated function getAccount(string account_id, map headers = {}) returns CollectionAccount|error { + return {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}}; + } + + # Get all accounts + # + # + headers - Headers to be sent with the request + remote isolated function getAccounts(map headers = {}) returns GETCollectionAccountsResponse|error { + return {"accounts": [{"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": 0, "Pending": 0, "In Dispute": 0, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20"}}; + } + + # Get a collections agent by email + # + # + email - The email of the collections agent. + # + headers - Headers to be sent with the request + remote isolated function getCollectionsAgent(string email, map headers = {}) returns CollectionAgent|error { + return {"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}; + } + + # Get all collections agents + # + # + headers - Headers to be sent with the request + remote isolated function getCollectionsAgents(map headers = {}) returns GETCollectionAgentsResponse|error { + return {"accounts": [{"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20"}}; + } + + # Get an overview of collections + # + # + headers - Headers to be sent with the request + remote isolated function getCollectionsInfo(map headers = {}) returns CollectionsInfo|error { + return {"accounts_in_collections": 24, "home_currency": "USD", "total_debt": "8379.78", "largest_debts": ["Test Account - 12438.00 USD", "Jimmy John - 8000.00 USD", "James Smith - 2450.55 USD", "Bob Roberts - 1000.00 USD", "Jim Reynolds - 829.00 USD"], "oldest_debts": ["Test Account - 2662 days", "Jimbo - 1494 days", "Steve Smith - 942 days", "Jason Williams - 678 days", "Will Jasons - 365 days"], "statuses": {"In Collections": 24, "Pending": 2, "In Dispute": 5, "Paid in Full": 0}}; + } + + # Get a payment run + # + # + payment_run_id - The payment run ID. A payment run id in Advanced Payment Manager is different from a payment run id in Zuora. + # + headers - Headers to be sent with the request + remote isolated function getPaymentRun(int payment_run_id, map headers = {}) returns GETPaymentRunResponse|error { + return {"success": true, "id": 6, "status": "Complete", "target_date": "2018-01-02T00:00:00.000Z", "filter": "Account.Currency = 'CAD'", "payment_run_schedule_id": "Adhoc", "invoices_held": {}, "metrics": {"documents": 0, "payments": 0, "failed": 0, "skipped": 0, "amount": 0, "credit": 0}}; + } + + # Get a payment run schedule + # + # + schedule_id - The schedule ID + # + headers - Headers to be sent with the request + remote isolated function getPaymentRunSchedule(int schedule_id, map headers = {}) returns GETPaymentRunScheduleResponse|error { + return {"success": true, "id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}; + } + + # Get all payment run schedules + # + # + headers - Headers to be sent with the request + remote isolated function getPaymentRunSchedules(map headers = {}) returns GETPaymentRunSchedulesResponse|error { + return {"success": true, "size": 3, "schedules": [{"id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}]}; + } + + # Get Statement Generator settings + # + # + headers - Headers to be sent with the request + remote isolated function getSettings(map headers = {}) returns GETStatementSettingsResponse|error { + return {"success": true, "templates": [{"name": "Default Template"}, {"name": "Template for end consumers"}], "default_template": "Default Template", "default_cycle": "Month"}; + } + + # Update a payment run schedule + # + # + schedule_id - The schedule ID + # + headers - Headers to be sent with the request + remote isolated function updatePaymentRunSchedule(int schedule_id, PUTPaymentRunSchedule payload, map headers = {}) returns POSTPaymentRunScheduleResponse|error { + return {"id": 6, "success": true}; + } +} diff --git a/openapi-cli/src/test/resources/generators/client/mock/ref_example.json b/openapi-cli/src/test/resources/generators/client/mock/ref_example.json new file mode 100644 index 000000000..ee48f78c4 --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/ref_example.json @@ -0,0 +1,2437 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Opendatasoft's Explore API Reference Documentation", + "version": "v2.1", + "contact": { + "email": "support@opendatasoft.com" + }, + "license": { + "name": "Copyright Opendatasoft" + } + }, + "servers": [ + { + "url": "https://documentation-resources.opendatasoft.com/api/explore/v2.1", + "description": "Portal that hosts example datasets" + } + ], + "security": [ + { + "apikey": [] + } + ], + "tags": [ + { + "name": "Catalog", + "description": "API to enumerate datasets" + }, + { + "name": "Dataset", + "description": "API to work on records" + } + ], + "paths": { + "/catalog/datasets": { + "get": { + "summary": "Query catalog datasets", + "operationId": "getDatasets", + "tags": [ + "Catalog" + ], + "description": "Retrieve available datasets.", + "parameters": [ + { + "$ref": "#/components/parameters/select" + }, + { + "$ref": "#/components/parameters/where" + }, + { + "$ref": "#/components/parameters/order_by" + }, + { + "$ref": "#/components/parameters/limit" + }, + { + "$ref": "#/components/parameters/offset" + }, + { + "$ref": "#/components/parameters/refine" + }, + { + "$ref": "#/components/parameters/exclude" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + }, + { + "$ref": "#/components/parameters/group_by" + }, + { + "$ref": "#/components/parameters/include_links" + }, + { + "$ref": "#/components/parameters/include_app_metas" + } + ], + "responses": { + "200": { + "description": "A list of available datasets", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/results_dataset-v2.1" + }, + "examples": { + "datasets": { + "$ref": "#/components/examples/datasets-v2.1" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/exports": { + "get": { + "summary": "List export formats", + "operationId": "listExportFormats", + "tags": [ + "Catalog" + ], + "description": "List available export formats", + "responses": { + "200": { + "description": "A list of available export formats", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/exports/{format}": { + "get": { + "summary": "Export a catalog", + "operationId": "exportDatasets", + "tags": [ + "Catalog" + ], + "description": "Export a catalog in the desired format.", + "parameters": [ + { + "$ref": "#/components/parameters/format-catalog-v2.1" + }, + { + "$ref": "#/components/parameters/select" + }, + { + "$ref": "#/components/parameters/where" + }, + { + "$ref": "#/components/parameters/order_by" + }, + { + "$ref": "#/components/parameters/group_by" + }, + { + "$ref": "#/components/parameters/limit_export" + }, + { + "$ref": "#/components/parameters/offset" + }, + { + "$ref": "#/components/parameters/refine" + }, + { + "$ref": "#/components/parameters/exclude" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + } + ], + "responses": { + "200": { + "description": "Return a file" + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/exports/csv": { + "get": { + "summary": "Export a catalog in CSV", + "operationId": "exportCatalogCSV", + "tags": [ + "Catalog" + ], + "description": "Export a catalog in CSV (Comma Separated Values). Specific parameters are described here", + "parameters": [ + { + "name": "delimiter", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + ";", + ",", + "\t", + "|" + ], + "default": ";" + }, + "description": "Sets the field delimiter of the CSV export" + }, + { + "name": "list_separator", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "," + }, + "description": "Sets the separator character used for multivalued strings" + }, + { + "name": "quote_all", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false + }, + "description": "Set it to true to force quoting all strings, i.e. surrounding all strings with quote characters" + }, + { + "name": "with_bom", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": true + }, + "description": "Set it to true to force the first characters of the CSV file to be a Unicode Byte Order Mask (0xFEFF). It usually makes Excel correctly open the output CSV file without warning.\n**Warning:** the default value of this parameter is `false` in v2.0 and `true` starting with v2.1" + } + ], + "responses": { + "200": { + "description": "Return a file" + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/exports/dcat{dcat_ap_format}": { + "get": { + "summary": "Export a catalog in RDF/XML (DCAT)", + "operationId": "exportCatalogDCAT", + "tags": [ + "Catalog" + ], + "description": "Export a catalog in RDF/XML described with DCAT (Data Catalog Vocabulary). Specific parameters are described here", + "parameters": [ + { + "$ref": "#/components/parameters/dcat_format" + }, + { + "name": "include_exports", + "in": "query", + "required": false, + "schema": { + "$ref": "#/components/schemas/enum-format-datasets-v2.1" + }, + "description": "Sets the datasets exports exposed in the DCAT export. By default, all exports are exposed.", + "examples": { + "legacy": { + "summary": "Only expose csv, json and geojson datasets exports", + "value": "csv,json,geojson" + } + } + } + ], + "responses": { + "200": { + "description": "Return a file" + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/facets": { + "get": { + "summary": "List facet values", + "operationId": "getDatasetsFacets", + "tags": [ + "Catalog" + ], + "description": "Enumerate facet values for datasets and returns a list of values for each facet.\nCan be used to implement guided navigation in large result sets.", + "parameters": [ + { + "$ref": "#/components/parameters/facet" + }, + { + "$ref": "#/components/parameters/refine" + }, + { + "$ref": "#/components/parameters/exclude" + }, + { + "$ref": "#/components/parameters/where" + }, + { + "$ref": "#/components/parameters/timezone" + } + ], + "responses": { + "200": { + "description": "An enumeration of facets", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "facets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/facet_enumeration" + } + } + } + }, + "examples": { + "catalog_facets": { + "$ref": "#/components/examples/catalog_facets" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/records": { + "get": { + "summary": "Query dataset records", + "operationId": "getRecords", + "tags": [ + "Dataset" + ], + "description": "Perform a query on dataset records.", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "$ref": "#/components/parameters/select" + }, + { + "$ref": "#/components/parameters/where" + }, + { + "$ref": "#/components/parameters/group_by" + }, + { + "$ref": "#/components/parameters/order_by" + }, + { + "$ref": "#/components/parameters/limit" + }, + { + "$ref": "#/components/parameters/offset" + }, + { + "$ref": "#/components/parameters/refine" + }, + { + "$ref": "#/components/parameters/exclude" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + }, + { + "$ref": "#/components/parameters/include_links" + }, + { + "$ref": "#/components/parameters/include_app_metas" + } + ], + "responses": { + "200": { + "description": "Records", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/results-v2.1" + }, + "examples": { + "records": { + "$ref": "#/components/examples/records-v2.1" + }, + "group_by_country": { + "$ref": "#/components/examples/group_by_country-v2.1" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/exports": { + "get": { + "summary": "List export formats", + "operationId": "listDatasetExportFormats", + "tags": [ + "Dataset" + ], + "description": "List available export formats", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + } + ], + "responses": { + "200": { + "description": "A list of available export formats", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/exports/{format}": { + "get": { + "summary": "Export a dataset", + "operationId": "exportRecords", + "tags": [ + "Dataset" + ], + "description": "Export a dataset in the desired format.\n**Note:** The `group_by` parameter is only available on exports starting with the v2.1", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "$ref": "#/components/parameters/format-datasets-v2.1" + }, + { + "$ref": "#/components/parameters/select" + }, + { + "$ref": "#/components/parameters/where" + }, + { + "$ref": "#/components/parameters/order_by" + }, + { + "$ref": "#/components/parameters/group_by" + }, + { + "$ref": "#/components/parameters/limit_export" + }, + { + "$ref": "#/components/parameters/refine" + }, + { + "$ref": "#/components/parameters/exclude" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + }, + { + "$ref": "#/components/parameters/use_labels" + }, + { + "$ref": "#/components/parameters/epsg" + } + ], + "responses": { + "200": { + "description": "Return a file" + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/exports/csv": { + "get": { + "summary": "Export a dataset in CSV", + "operationId": "exportRecordsCSV", + "tags": [ + "Dataset" + ], + "description": "Export a dataset in CSV (Comma Separated Values). Specific parameters are described here", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "name": "delimiter", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": [ + ";", + ",", + "\t", + "|" + ], + "default": ";" + }, + "description": "Sets the field delimiter of the CSV export" + }, + { + "name": "list_separator", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "," + }, + "description": "Sets the separator character used for multivalued strings" + }, + { + "name": "quote_all", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": false + }, + "description": "Set it to true to force quoting all strings, i.e. surrounding all strings with quote characters" + }, + { + "name": "with_bom", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": true + }, + "description": "Set it to true to force the first characters of the CSV file to be a Unicode Byte Order Mask (0xFEFF). It usually makes Excel correctly open the output CSV file without warning.\n**Warning:** the default value of this parameter is `false` in v2.0 and `true` starting with v2.1" + } + ], + "responses": { + "200": { + "description": "Return a file" + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/exports/gpx": { + "get": { + "summary": "Export a dataset in GPX", + "operationId": "exportRecordsGPX", + "tags": [ + "Dataset" + ], + "description": "Export a dataset in GPX. Specific parameters are described here", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "name": "name_field", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Sets the field that is used as the 'name' attribute in the GPX output" + }, + { + "name": "description_field_list", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Sets the fields to use in the 'description' attribute of the GPX output" + }, + { + "name": "use_extension", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "default": true + }, + "description": "Set it to true to use the `` tag for attributes (as GDAL does). Set it to false to use the `` tag for attributes.\n**Warning:** the default value of this parameter is `false` in v2.0 and `true` starting with v2.1" + } + ], + "responses": { + "200": { + "description": "Return a file" + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}": { + "get": { + "summary": "Show dataset information", + "operationId": "getDataset", + "tags": [ + "Catalog" + ], + "description": "Returns a list of available endpoints for the specified dataset, with metadata and endpoints.\n\nThe response includes the following links:\n* the attachments endpoint\n* the files endpoint\n* the records endpoint\n* the catalog endpoint.", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "$ref": "#/components/parameters/select" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + }, + { + "$ref": "#/components/parameters/include_links" + }, + { + "$ref": "#/components/parameters/include_app_metas" + } + ], + "responses": { + "200": { + "description": "The dataset", + "content": { + "application/json; charset=utf-8json": { + "schema": { + "$ref": "#/components/schemas/dataset-v2.1" + }, + "examples": { + "dataset": { + "$ref": "#/components/examples/dataset-v2.1" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/facets": { + "get": { + "summary": "List dataset facets", + "operationId": "getRecordsFacets", + "tags": [ + "Dataset" + ], + "description": "Enumerates facet values for records and returns a list of values for each facet.\nCan be used to implement guided navigation in large result sets.\n", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "$ref": "#/components/parameters/where" + }, + { + "$ref": "#/components/parameters/refine" + }, + { + "$ref": "#/components/parameters/exclude" + }, + { + "$ref": "#/components/parameters/facet" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + } + ], + "responses": { + "200": { + "description": "Facets enumeration", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "facets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/facet_enumeration" + } + } + } + }, + "examples": { + "facets": { + "$ref": "#/components/examples/facets" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/attachments": { + "get": { + "summary": "List dataset attachments", + "operationId": "getDatasetAttachments", + "tags": [ + "Dataset" + ], + "description": "Returns a list of all available attachments for a dataset.\n", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + } + ], + "responses": { + "200": { + "description": "List of all available attachments", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/attachment" + } + } + } + }, + "examples": { + "attachments": { + "$ref": "#/components/examples/attachments" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, + "/catalog/datasets/{dataset_id}/records/{record_id}": { + "get": { + "summary": "Read a dataset record", + "operationId": "getRecord", + "tags": [ + "Dataset" + ], + "description": "Reads a single dataset record based on its identifier.\n", + "parameters": [ + { + "$ref": "#/components/parameters/dataset_id" + }, + { + "$ref": "#/components/parameters/record_id" + }, + { + "$ref": "#/components/parameters/select" + }, + { + "$ref": "#/components/parameters/lang" + }, + { + "$ref": "#/components/parameters/timezone" + } + ], + "responses": { + "200": { + "description": "A single record", + "content": { + "application/json; charset=utf-8": { + "schema": { + "$ref": "#/components/schemas/record-v2.1" + }, + "examples": { + "record": { + "$ref": "#/components/examples/record-v2.1" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/bad_request" + }, + "401": { + "description": "Unauthorized" + }, + "429": { + "$ref": "#/components/responses/quota" + }, + "500": { + "description": "Internal Server Error" + } + } + } + } + }, + "components": { + "securitySchemes": { + "apikey": { + "type": "apiKey", + "description": "API key to make authenticated requests.", + "name": "apikey", + "in": "query" + } + }, + "parameters": { + "select": { + "name": "select", + "in": "query", + "description": "Examples:\n- `select=size` - Example of select, which only return the \"size\" field.\n- `select=size * 2 as bigger_size` - Example of a complex expression with a label, which returns a new field named \"bigger_size\" and containing the double of size field value.\n- `select=dataset_id, fields` - Example of a select in catalog ODSQL query to only retrieve dataset_id and schema of datasets.\n\nA select expression can be used to add, remove or change the fields to return.\nAn expression can be:\n - a wildcard ('*'): all fields are returned.\n - A field name: only the specified field is returned.\n - An include/exclude function: All fields matching the include or exclude expression are included or excluded. This expression can contain wildcard.\n - A complex expression. The result of the expression is returned. A label can be set for this expression, and in that case, the field will be named after this label.", + "schema": { + "type": "string" + } + }, + "where": { + "name": "where", + "in": "query", + "description": "A `where` filter is a text expression performing a simple full-text search that can also include logical operations\n(NOT, AND, OR...) and lots of other functions to perform complex and precise search operations.\n\nFor more information, see [Opendatasoft Query Language (ODSQL)]() reference documentation.", + "schema": { + "type": "string" + } + }, + "order_by": { + "name": "order_by", + "in": "query", + "description": "Example: `order_by=sum(age) desc, name asc`\n\nA comma-separated list of field names or aggregations to sort on, followed by an order (`asc` or `desc`).\n\nResults are sorted in ascending order by default. To sort results in descending order, use the `desc` keyword.", + "style": "form", + "explode": false, + "schema": { + "type": "string" + } + }, + "limit": { + "name": "limit", + "in": "query", + "description": "Number of items to return.\n\nTo use with the `offset` parameter to implement pagination.\n\nThe maximum possible value depends on whether the query contains a `group_by` clause or not.\n\nFor a query **without** a `group_by`:\n - the maximum value for `limit` is 100,\n - `offset+limit` should be less than 10000\n\nFor a query **with** a `group_by`:\n - the maximum value for `limit` is 20000,\n - `offset+limit` should be less than 20000\n\n**Note:** If you need more results, please use the /exports endpoint.\n", + "schema": { + "maximum": 100, + "minimum": -1, + "type": "integer", + "default": 10 + } + }, + "offset": { + "name": "offset", + "in": "query", + "description": "Index of the first item to return (starting at 0).\n\nTo use with the `limit` parameter to implement pagination.\n\n**Note:** the maximum value depends on the type of query, see the note on `limit` for the details\n", + "schema": { + "minimum": 0, + "type": "integer", + "default": 0 + } + }, + "refine": { + "name": "refine", + "in": "query", + "description": "Example: `refine=modified:2020` - Return only the value `2020` from the `modified` facet.\n\nA facet filter used to limit the result set.\nUsing this parameter, you can refine your query to display only the selected facet value in the response.\n\nRefinement uses the following syntax: `refine=:`\n\nFor date, and other hierarchical facets, when refining on one value, all second-level values related to that entry will appear in facets enumeration. For example, after refining on the year 2019, the related second-level month will appear. And when refining on August 2019, the third-level day will appear.\n\n**`refine` must not be confused with a `where` filter. Refining with a facet is equivalent to selecting an entry in the left navigation panel.**", + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "exclude": { + "name": "exclude", + "in": "query", + "description": "Examples:\n- `exclude=city:Paris` - Exclude the value `Paris` from the `city` facet. Facets enumeration will display `Paris` as `excluded` without any count information.\n- `exclude=modified:2019/12` - Exclude the value `2019/12` from the `modified` facet. Facets enumeration will display `2020` as `excluded` without any count information.\n\nA facet filter used to exclude a facet value from the result set.\nUsing this parameter, you can filter your query to exclude the selected facet value in the response.\n\n`exclude` uses the following syntax: `exclude=:`\n\n**`exclude` must not be confused with a `where` filter. Excluding a facet value is equivalent to removing an entry in the left navigation panel.**", + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "lang": { + "name": "lang", + "in": "query", + "description": "A language value.\n\nIf specified, the `lang` value override the default language, which is \"fr\".\nThe language is used to format string, for example in the `date_format` function.", + "schema": { + "type": "string", + "enum": [ + "en", + "fr", + "nl", + "pt", + "it", + "ar", + "de", + "es", + "ca", + "eu", + "sv" + ] + }, + "style": "form" + }, + "timezone": { + "name": "timezone", + "in": "query", + "description": "Set the timezone for datetime fields.\n\nTimezone IDs are defined by the [Unicode CLDR project](https://github.com/unicode-org/cldr). The list of timezone IDs is available in [timezone.xml](https://github.com/unicode-org/cldr/blob/master/common/bcp47/timezone.xml).", + "schema": { + "type": "string", + "default": "UTC" + }, + "examples": { + "UTC": { + "summary": "UTC timezone", + "value": "UTC" + }, + "Europe/Paris": { + "summary": "Paris timezone", + "value": "Europe/Paris" + }, + "US/Eastern": { + "summary": "Eastern timezone", + "value": "US/Eastern" + }, + "Europe/London": { + "summary": "London timezone", + "value": "Europe/London" + }, + "Europe/Berlin": { + "summary": "Berlin timezone", + "value": "Europe/Berlin" + } + } + }, + "group_by": { + "name": "group_by", + "in": "query", + "description": "Example: `group_by=city_field as city`\n\nA group by expression defines a grouping function for an aggregation.\nIt can be:\n - a field name: group result by each value of this field\n - a range function: group result by range\n - a date function: group result by date\n\nIt is possible to specify a custom name with the 'as name' notation.", + "style": "form", + "explode": false, + "schema": { + "type": "string" + } + }, + "include_links": { + "name": "include_links", + "in": "query", + "description": "If set to `true`, this parameter will add HATEOAS links in the response.\n", + "schema": { + "type": "boolean", + "default": false + } + }, + "include_app_metas": { + "name": "include_app_metas", + "in": "query", + "description": "If set to `true`, this parameter will add application metadata to the response.\n", + "schema": { + "type": "boolean", + "default": false + } + }, + "format-catalog-v2.1": { + "name": "format", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "csv", + "data.json", + "dcat", + "dcat_ap_ch", + "dcat_ap_de", + "dcat_ap_se", + "dcat_ap_sp", + "dcat_ap_it", + "dcat_ap_vl", + "dcat_ap_benap", + "json", + "rdf", + "rss", + "ttl", + "xlsx" + ], + "description": "Format specifier for the catalog export.\n`dcat_ap_*` formats are only available upon activation.\nSee [here](#tag/Catalog/operation/listExportFormats) to get the list of available export formats" + }, + "style": "simple" + }, + "limit_export": { + "name": "limit", + "in": "query", + "description": "Number of items to return in export.\n\nUse -1 (default) to retrieve all records\n", + "schema": { + "minimum": -1, + "type": "integer", + "default": -1 + } + }, + "dcat_format": { + "name": "dcat_ap_format", + "in": "path", + "required": true, + "schema": { + "type": "string", + "enum": [ + "_ap_ch", + "_ap_de", + "_ap_se", + "_ap_sp", + "_ap_it", + "_ap_vl", + "_ap_benap" + ], + "description": "DCAT format specifier for the catalog export.\n`dcat_ap_*` formats are only available upon activation." + }, + "style": "simple" + }, + "facet": { + "name": "facet", + "in": "query", + "description": "A facet is a field used for simple filtering (through the `refine` and `exclude` parameters) or exploration (with the `/facets` endpoint).\n\nFacets can be configured in the back-office or with this parameter.\n", + "style": "form", + "explode": true, + "schema": { + "type": "string" + } + }, + "dataset_id": { + "name": "dataset_id", + "in": "path", + "description": "The identifier of the dataset to be queried.\n\nYou can find it in the \"Information\" tab of the dataset page or in the dataset URL, right after `/datasets/`.", + "required": true, + "schema": { + "type": "string" + } + }, + "format-datasets-v2.1": { + "name": "format", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/enum-format-datasets-v2.1" + }, + "style": "simple" + }, + "use_labels": { + "name": "use_labels", + "in": "query", + "description": "If set to `true`, this parameter will make exports output the label of each field rather than its name.\n\nThis parameter only makes sense for formats that contain a list of the fields in their output.\n", + "schema": { + "type": "boolean", + "default": false + } + }, + "epsg": { + "name": "epsg", + "in": "query", + "description": "This parameter sets the EPSG code to project shapes into for formats that support geometric features.\n", + "schema": { + "type": "integer", + "default": 4326 + } + }, + "record_id": { + "name": "record_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Record identifier" + } + }, + "schemas": { + "links": { + "type": "object", + "properties": { + "href": { + "type": "string", + "format": "uri" + }, + "rel": { + "type": "string", + "enum": [ + "self", + "first", + "last", + "next", + "dataset", + "catalog" + ] + } + } + }, + "dataset-v2.1": { + "type": "object", + "properties": { + "_links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "dataset_id": { + "type": "string" + }, + "dataset_uid": { + "type": "string", + "readOnly": true + }, + "attachments": { + "type": "array", + "items": { + "type": "object", + "properties": { + "mimetype": { + "type": "string" + }, + "url": { + "type": "string" + }, + "id": { + "type": "string" + }, + "title": { + "type": "string" + } + } + } + }, + "has_records": { + "type": "boolean" + }, + "data_visible": { + "type": "boolean" + }, + "features": { + "type": "array", + "description": "A map of available features for a dataset, with the fields they apply to.\n", + "items": { + "type": "string" + } + }, + "metas": { + "type": "object" + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "label": { + "type": "string" + }, + "type": { + "type": "string" + }, + "annotations": { + "type": "object" + }, + "description": { + "type": "string", + "nullable": true + } + } + } + }, + "additionalProperties": {} + } + }, + "results_dataset-v2.1": { + "type": "object", + "properties": { + "total_count": { + "type": "integer" + }, + "_links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/dataset-v2.1" + } + } + } + }, + "enum-format-datasets-v2.1": { + "type": "string", + "enum": [ + "csv", + "fgb", + "geojson", + "gpx", + "json", + "jsonl", + "jsonld", + "kml", + "n3", + "ov2", + "parquet", + "rdfxml", + "shp", + "turtle", + "xlsx" + ] + }, + "facet_value_enumeration": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "count": { + "type": "integer" + }, + "value": { + "type": "string" + }, + "state": { + "type": "string" + } + } + }, + "facet_enumeration": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "facets": { + "type": "array", + "items": { + "$ref": "#/components/schemas/facet_value_enumeration" + } + } + } + }, + "record-v2.1": { + "type": "object", + "properties": { + "_id": { + "type": "string" + }, + "_timestamp": { + "type": "string", + "format": "dateTime" + }, + "_size": { + "type": "integer", + "format": "int64" + }, + "_links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "field1": { + "type": "string" + }, + "field2": { + "type": "integer" + } + } + }, + "results-v2.1": { + "type": "object", + "properties": { + "total_count": { + "type": "integer" + }, + "_links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/links" + } + }, + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/record-v2.1" + } + } + } + }, + "attachment": { + "type": "object", + "properties": { + "href": { + "type": "string" + }, + "metas": { + "type": "object", + "properties": { + "mime-type": { + "type": "string" + }, + "title": { + "type": "string" + }, + "url": { + "type": "string" + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "examples": { + "datasets-v2.1": { + "value": { + "total_count": 19, + "results": [ + { + "dataset_id": "world-administrative-boundaries-countries-and-territories", + "dataset_uid": "da_6kvv9v", + "attachments": [], + "has_records": true, + "data_visible": true, + "fields": [ + { + "annotations": {}, + "description": null, + "type": "geo_point_2d", + "name": "geo_point_2d", + "label": "Geo Point" + }, + { + "annotations": {}, + "description": null, + "type": "geo_shape", + "name": "geo_shape", + "label": "Geo Shape" + }, + { + "description": null, + "label": "Status", + "type": "text", + "name": "status", + "annotations": { + "facet": [] + } + }, + { + "description": "ISO 3 code of the country to which the territory belongs", + "label": "ISO 3 country code", + "type": "text", + "name": "color_code", + "annotations": { + "facet": [] + } + }, + { + "description": null, + "label": "Region of the territory", + "type": "text", + "name": "region", + "annotations": { + "facet": [] + } + }, + { + "description": null, + "label": "ISO 3 territory code", + "type": "text", + "name": "iso3", + "annotations": { + "sortable": [] + } + }, + { + "description": null, + "label": "Continent of the territory", + "type": "text", + "name": "continent", + "annotations": { + "facet": [] + } + }, + { + "description": "Name of the territory", + "label": "English Name", + "type": "text", + "name": "name", + "annotations": { + "sortable": [] + } + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "iso_3166_1_alpha_2_codes", + "label": "ISO 3166-1 Alpha 2-Codes" + }, + { + "annotations": {}, + "label": "French Name", + "type": "text", + "name": "french_short", + "description": "French term, when it is available in https://data.opendatasoft.com/explore/dataset/countries-territories-taxonomy-mvp-ct-taxonomy-with-hxl-tags1@public/table/, English name otherwise" + } + ], + "metas": { + "default": { + "records_count": 256, + "modified": "2021-06-23T14:59:57+00:00", + "source_domain_address": null, + "references": "https://geonode.wfp.org/layers/geonode:wld_bnd_adm0_wfp", + "keyword": [ + "United Nation", + "ISO-3 code", + "Countries", + "Territories", + "Shape", + "Boundaries" + ], + "source_domain_title": null, + "geographic_reference": [ + "world" + ], + "timezone": null, + "title": "World Administrative Boundaries - Countries and Territories", + "parent_domain": null, + "theme": [ + "Administration, Government, Public finances, Citizenship" + ], + "modified_updates_on_data_change": false, + "metadata_processed": "2021-06-23T15:00:02.656000+00:00", + "data_processed": "2019-05-15T07:49:01+00:00", + "territory": [ + "World" + ], + "description": "

This dataset displays level 0 world administrative boundaries. It contains countries as well as non-sovereign territories (like, for instance, French overseas). 

", + "modified_updates_on_metadata_change": false, + "shared_catalog": null, + "source_domain": null, + "attributions": null, + "geographic_area_mode": null, + "geographic_reference_auto": true, + "geographic_area": null, + "publisher": "World Food Programme (UN agency)", + "language": "en", + "license": "Open Government Licence v3.0", + "source_dataset": null, + "metadata_languages": [ + "en" + ], + "oauth_scope": null, + "federated": true, + "license_url": "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" + } + }, + "features": [ + "analyze", + "geo" + ] + }, + { + "dataset_id": "geonames-all-cities-with-a-population-1000", + "dataset_uid": "da_5m8ykr", + "attachments": [ + { + "mimetype": "application/zip", + "url": "odsfile://cities1000.zip", + "id": "cities1000_zip", + "title": "cities1000.zip" + } + ], + "has_records": true, + "data_visible": true, + "fields": [ + { + "description": null, + "label": "Geoname ID", + "type": "text", + "name": "geoname_id", + "annotations": { + "facetsort": [ + "-count" + ], + "id": [] + } + }, + { + "description": null, + "label": "Name", + "type": "text", + "name": "name", + "annotations": { + "sortable": [] + } + }, + { + "description": null, + "label": "ASCII Name", + "type": "text", + "name": "ascii_name", + "annotations": {} + }, + { + "description": null, + "label": "Alternate Names", + "type": "text", + "name": "alternate_names", + "annotations": { + "multivalued": [ + "," + ] + } + }, + { + "description": "see http://www.geonames.org/export/codes.html", + "label": "Feature Class", + "type": "text", + "name": "feature_class", + "annotations": {} + }, + { + "description": "see http://www.geonames.org/export/codes.html", + "label": "Feature Code", + "type": "text", + "name": "feature_code", + "annotations": {} + }, + { + "description": null, + "label": "Country Code", + "type": "text", + "name": "country_code", + "annotations": {} + }, + { + "description": null, + "label": "Country name EN", + "type": "text", + "name": "cou_name_en", + "annotations": { + "facet": [], + "facetsort": [ + "alphanum" + ], + "disjunctive": [] + } + }, + { + "description": null, + "label": "Country Code 2", + "type": "text", + "name": "country_code_2", + "annotations": {} + }, + { + "description": null, + "label": "Admin1 Code", + "type": "text", + "name": "admin1_code", + "annotations": {} + }, + { + "description": null, + "label": "Admin2 Code", + "type": "text", + "name": "admin2_code", + "annotations": { + "facetsort": [ + "-count" + ] + } + }, + { + "description": null, + "label": "Admin3 Code", + "type": "text", + "name": "admin3_code", + "annotations": {} + }, + { + "description": null, + "label": "Admin4 Code", + "type": "text", + "name": "admin4_code", + "annotations": {} + }, + { + "description": null, + "label": "Population", + "type": "int", + "name": "population", + "annotations": {} + }, + { + "description": null, + "label": "Elevation", + "type": "text", + "name": "elevation", + "annotations": {} + }, + { + "description": null, + "label": "DIgital Elevation Model", + "type": "int", + "name": "dem", + "annotations": {} + }, + { + "description": null, + "label": "Timezone", + "type": "text", + "name": "timezone", + "annotations": { + "facet": [], + "hierarchical": [ + "/" + ] + } + }, + { + "description": null, + "label": "Modification date", + "type": "date", + "name": "modification_date", + "annotations": {} + }, + { + "description": null, + "label": "LABEL EN", + "type": "text", + "name": "label_en", + "annotations": {} + }, + { + "description": null, + "label": "Coordinates", + "type": "geo_point_2d", + "name": "coordinates", + "annotations": { + "facetsort": [ + "-count" + ] + } + } + ], + "metas": { + "default": { + "records_count": 137609, + "modified": "2021-06-23T14:37:45+00:00", + "source_domain_address": null, + "references": null, + "keyword": null, + "source_domain_title": null, + "geographic_reference": [ + "world" + ], + "timezone": null, + "title": "Geonames - All Cities with a population > 1000", + "parent_domain": null, + "theme": null, + "modified_updates_on_data_change": false, + "metadata_processed": "2021-06-23T14:49:23.198000+00:00", + "data_processed": "2021-06-23T14:49:23+00:00", + "territory": [ + "World" + ], + "description": null, + "modified_updates_on_metadata_change": false, + "shared_catalog": null, + "source_domain": null, + "attributions": null, + "geographic_area_mode": null, + "geographic_reference_auto": true, + "geographic_area": null, + "publisher": null, + "language": "en", + "license": null, + "source_dataset": null, + "metadata_languages": [ + "en" + ], + "oauth_scope": null, + "federated": false, + "license_url": null + } + }, + "features": [ + "geo", + "analyze", + "timeserie" + ] + } + ] + } + }, + "catalog_facets": { + "value": { + "links": [], + "facets": [ + { + "name": "publisher", + "facets": [ + { + "count": 2, + "state": "displayed", + "name": "Opendatasoft", + "value": "Opendatasoft" + }, + { + "count": 2, + "state": "displayed", + "name": "Opendatasoft - Data Team", + "value": "Opendatasoft - Data Team" + } + ] + }, + { + "name": "features", + "facets": [ + { + "count": 19, + "state": "displayed", + "name": "analyze", + "value": "analyze" + }, + { + "count": 13, + "state": "displayed", + "name": "timeserie", + "value": "timeserie" + } + ] + }, + { + "name": "language", + "facets": [ + { + "count": 17, + "state": "displayed", + "name": "en", + "value": "en" + }, + { + "count": 4, + "state": "displayed", + "name": "fr", + "value": "fr" + } + ] + } + ] + } + }, + "records-v2.1": { + "value": { + "total_count": 137611, + "results": [ + { + "admin1_code": "27", + "elevation": null, + "name": "Saint-Leu", + "modification_date": "2019-03-26", + "alternate_names": [ + "Saint-Leu" + ], + "feature_class": "P", + "admin3_code": "711", + "cou_name_en": "France", + "coordinates": { + "lat": 46.7306, + "lon": 4.50083 + }, + "country_code_2": null, + "geoname_id": "2978771", + "feature_code": "PPL", + "label_en": "France", + "dem": 366, + "country_code": "FR", + "ascii_name": "Saint-Leu", + "timezone": "Europe/Paris", + "admin2_code": "71", + "admin4_code": "71436", + "population": 29278 + }, + { + "admin1_code": "32", + "elevation": null, + "name": "Saint-Léger-lès-Domart", + "modification_date": "2016-02-18", + "alternate_names": [ + "Saint-Leger", + "Saint-Leger-les-Domart", + "Saint-Léger", + "Saint-Léger-lès-Domart" + ], + "feature_class": "P", + "admin3_code": "802", + "cou_name_en": "France", + "coordinates": { + "lat": 50.05208, + "lon": 2.14067 + }, + "country_code_2": null, + "geoname_id": "2978817", + "feature_code": "PPL", + "label_en": "France", + "dem": 31, + "country_code": "FR", + "ascii_name": "Saint-Leger-les-Domart", + "timezone": "Europe/Paris", + "admin2_code": "80", + "admin4_code": "80706", + "population": 1781 + } + ] + } + }, + "group_by_country-v2.1": { + "value": { + "results": [ + { + "count": 16729, + "cou_name_en": "United States" + }, + { + "count": 9945, + "cou_name_en": "Italy" + }, + { + "count": 8981, + "cou_name_en": "Mexico" + } + ] + } + }, + "dataset-v2.1": { + "value": { + "dataset_id": "geonames-all-cities-with-a-population-1000", + "dataset_uid": "da_s2n5ed", + "attachments": [], + "has_records": true, + "data_visible": true, + "fields": [ + { + "description": null, + "label": "Geoname ID", + "type": "text", + "name": "geoname_id", + "annotations": { + "facetsort": [ + "-count" + ], + "id": [] + } + }, + { + "description": null, + "label": "Name", + "type": "text", + "name": "name", + "annotations": { + "sortable": [] + } + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "ascii_name", + "label": "ASCII Name" + }, + { + "description": null, + "label": "Alternate Names", + "type": "text", + "name": "alternate_names", + "annotations": { + "multivalued": [ + "," + ] + } + }, + { + "annotations": {}, + "label": "Feature Class", + "type": "text", + "name": "feature_class", + "description": "see http://www.geonames.org/export/codes.html" + }, + { + "annotations": {}, + "label": "Feature Code", + "type": "text", + "name": "feature_code", + "description": "see http://www.geonames.org/export/codes.html" + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "country_code", + "label": "Country Code" + }, + { + "description": null, + "label": "Country name EN", + "type": "text", + "name": "cou_name_en", + "annotations": { + "facet": [], + "facetsort": [ + "alphanum" + ], + "disjunctive": [] + } + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "country_code_2", + "label": "Country Code 2" + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "admin1_code", + "label": "Admin1 Code" + }, + { + "description": null, + "label": "Admin2 Code", + "type": "text", + "name": "admin2_code", + "annotations": { + "facetsort": [ + "-count" + ] + } + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "admin3_code", + "label": "Admin3 Code" + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "admin4_code", + "label": "Admin4 Code" + }, + { + "annotations": {}, + "description": null, + "type": "int", + "name": "population", + "label": "Population" + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "elevation", + "label": "Elevation" + }, + { + "annotations": {}, + "description": null, + "type": "int", + "name": "dem", + "label": "DIgital Elevation Model" + }, + { + "description": null, + "label": "Timezone", + "type": "text", + "name": "timezone", + "annotations": { + "facet": [], + "hierarchical": [ + "/" + ] + } + }, + { + "annotations": {}, + "description": null, + "type": "date", + "name": "modification_date", + "label": "Modification date" + }, + { + "annotations": {}, + "description": null, + "type": "text", + "name": "label_en", + "label": "LABEL EN" + }, + { + "description": null, + "label": "Coordinates", + "type": "geo_point_2d", + "name": "coordinates", + "annotations": { + "facetsort": [ + "-count" + ] + } + } + ], + "metas": { + "default": { + "records_count": 137611, + "modified": "2021-06-23T07:50:20+00:00", + "source_domain_address": null, + "references": "https://download.geonames.org/export/dump/", + "keyword": [ + "Geonames", + "city", + "world" + ], + "source_domain_title": null, + "geographic_reference": [ + "world" + ], + "timezone": null, + "title": "Geonames - All Cities with a population > 1000", + "parent_domain": null, + "theme": [ + "Administration, Government, Public finances, Citizenship" + ], + "modified_updates_on_data_change": true, + "metadata_processed": "2021-06-23T07:50:26.162000+00:00", + "data_processed": "2021-06-22T08:47:08+00:00", + "territory": [ + "World" + ], + "description": "

All cities with a population > 1000 or seats of adm div (ca 80.000)

Sources and Contributions

  • Sources : GeoNames is aggregating over hundred different data sources. \t
  • Ambassadors : GeoNames Ambassadors help in many countries. \t
  • Wiki : A wiki allows to view the data and quickly fix error and add missing places. \t
  • Donations and Sponsoring : Costs for running GeoNames are covered by donations and sponsoring.

Enrichment:

  • add country name
", + "modified_updates_on_metadata_change": false, + "shared_catalog": null, + "source_domain": null, + "attributions": [ + "https://www.geonames.org/about.html" + ], + "geographic_area_mode": null, + "geographic_reference_auto": true, + "geographic_area": null, + "publisher": "GeoNames", + "language": "en", + "license": "CC BY 4.0", + "source_dataset": null, + "metadata_languages": [ + "en" + ], + "oauth_scope": null, + "federated": true, + "license_url": "https://creativecommons.org/licenses/by/4.0/" + } + }, + "features": [ + "geo", + "analyze", + "timeserie" + ] + } + }, + "facets": { + "value": { + "links": [], + "facets": [ + { + "facets": [ + { + "count": 68888, + "state": "displayed", + "name": "Europe", + "value": "Europe" + }, + { + "count": 36276, + "state": "displayed", + "name": "America", + "value": "America" + } + ], + "name": "timezone" + }, + { + "facets": [ + { + "count": 313, + "state": "displayed", + "name": "Afghanistan", + "value": "Afghanistan" + }, + { + "count": 356, + "state": "displayed", + "name": "Albania", + "value": "Albania" + } + ], + "name": "cou_name_en" + } + ] + } + }, + "attachments": { + "value": { + "links": [], + "attachments": [ + { + "href": "https://documentation-resources.opendatasoft.com/api/v2/catalog/datasets/geonames-all-cities-with-a-population-1000/attachments/cities1000_zip", + "metas": { + "mime-type": "application/zip", + "title": "cities1000.zip" + } + } + ] + } + }, + "record-v2.1": { + "value": { + "timezone": "Europe/Brussels", + "elevation": null, + "name": "Fraire", + "modification_date": "2020-04-05", + "dem": 238, + "cou_name_en": "Belgium", + "feature_class": "P", + "admin3_code": "93", + "alternate_names": [ + "Fraire" + ], + "coordinates": { + "lat": 50.26127, + "lon": 4.5076 + }, + "country_code_2": null, + "geoname_id": "2798031", + "feature_code": "PPL", + "label_en": "Belgium", + "admin4_code": "93088", + "country_code": "BE", + "ascii_name": "Fraire", + "admin1_code": "WAL", + "admin2_code": "WNA", + "population": 1492 + } + } + }, + "responses": { + "bad_request": { + "description": "Bad Request", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "minLength": 1 + }, + "error_code": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "message", + "error_code" + ] + }, + "examples": { + "invalid_odsql": { + "value": { + "message": "ODSQL query is malformed: invalid_function() Clause(s) containing the error(s): select.", + "error_code": "ODSQLError" + } + } + } + } + } + }, + "quota": { + "description": "Too many requests", + "content": { + "application/json; charset=utf-8": { + "schema": { + "type": "object", + "properties": { + "errorcode": { + "type": "number" + }, + "reset_time": { + "type": "string", + "minLength": 1 + }, + "limit_time_unit": { + "type": "string", + "minLength": 1 + }, + "call_limit": { + "type": "number" + }, + "error": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "errorcode", + "reset_time", + "limit_time_unit", + "call_limit", + "error" + ] + }, + "examples": { + "quota_exceeded": { + "value": { + "errorcode": 10002, + "reset_time": "2021-01-26T00:00:00Z", + "limit_time_unit": "day", + "call_limit": 10000, + "error": "Too many requests on the domain. Please contact the domain administrator." + } + } + } + } + } + } + } + } +} diff --git a/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal b/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal new file mode 100644 index 000000000..da852245d --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal @@ -0,0 +1,88 @@ +import ballerina/http; + +public isolated client class Client { + final http:Client clientEp; + final readonly & ApiKeysConfig apiKeyConfig; + # Gets invoked to initialize the `connector`. + # + # + apiKeyConfig - API keys for authorization + # + config - The configurations to be used when initializing the `connector` + # + serviceUrl - URL of the target service + # + return - An error if connector initialization failed + public isolated function init(ApiKeysConfig apiKeyConfig, ConnectionConfig config = {}, string serviceUrl = "https://documentation-resources.opendatasoft.com/api/explore/v2.1") returns error? { + return; + } + + # Query catalog datasets + # + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - A list of available datasets + resource isolated function get catalog/datasets(map headers = {}, *GetDatasetsQueries queries) returns json|error { + return {"total_count": 19, "results": [{"dataset_id": "world-administrative-boundaries-countries-and-territories", "dataset_uid": "da_6kvv9v", "attachments": [], "has_records": true, "data_visible": true, "fields": [{"annotations": {}, "description": null, "type": "geo_point_2d", "name": "geo_point_2d", "label": "Geo Point"}, {"annotations": {}, "description": null, "type": "geo_shape", "name": "geo_shape", "label": "Geo Shape"}, {"description": null, "label": "Status", "type": "text", "name": "status", "annotations": {"facet": []}}, {"description": "ISO 3 code of the country to which the territory belongs", "label": "ISO 3 country code", "type": "text", "name": "color_code", "annotations": {"facet": []}}, {"description": null, "label": "Region of the territory", "type": "text", "name": "region", "annotations": {"facet": []}}, {"description": null, "label": "ISO 3 territory code", "type": "text", "name": "iso3", "annotations": {"sortable": []}}, {"description": null, "label": "Continent of the territory", "type": "text", "name": "continent", "annotations": {"facet": []}}, {"description": "Name of the territory", "label": "English Name", "type": "text", "name": "name", "annotations": {"sortable": []}}, {"annotations": {}, "description": null, "type": "text", "name": "iso_3166_1_alpha_2_codes", "label": "ISO 3166-1 Alpha 2-Codes"}, {"annotations": {}, "label": "French Name", "type": "text", "name": "french_short", "description": "French term, when it is available in https://data.opendatasoft.com/explore/dataset/countries-territories-taxonomy-mvp-ct-taxonomy-with-hxl-tags1@public/table/, English name otherwise"}], "metas": {"default": {"records_count": 256, "modified": "2021-06-23T14:59:57+00:00", "source_domain_address": null, "references": "https://geonode.wfp.org/layers/geonode:wld_bnd_adm0_wfp", "keyword": ["United Nation", "ISO-3 code", "Countries", "Territories", "Shape", "Boundaries"], "source_domain_title": null, "geographic_reference": ["world"], "timezone": null, "title": "World Administrative Boundaries - Countries and Territories", "parent_domain": null, "theme": ["Administration, Government, Public finances, Citizenship"], "modified_updates_on_data_change": false, "metadata_processed": "2021-06-23T15:00:02.656000+00:00", "data_processed": "2019-05-15T07:49:01+00:00", "territory": ["World"], "description": "

This dataset displays level 0 world administrative boundaries. It contains countries as well as non-sovereign territories (like, for instance, French overseas). 

", "modified_updates_on_metadata_change": false, "shared_catalog": null, "source_domain": null, "attributions": null, "geographic_area_mode": null, "geographic_reference_auto": true, "geographic_area": null, "publisher": "World Food Programme (UN agency)", "language": "en", "license": "Open Government Licence v3.0", "source_dataset": null, "metadata_languages": ["en"], "oauth_scope": null, "federated": true, "license_url": "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/"}}, "features": ["analyze", "geo"]}, {"dataset_id": "geonames-all-cities-with-a-population-1000", "dataset_uid": "da_5m8ykr", "attachments": [{"mimetype": "application/zip", "url": "odsfile://cities1000.zip", "id": "cities1000_zip", "title": "cities1000.zip"}], "has_records": true, "data_visible": true, "fields": [{"description": null, "label": "Geoname ID", "type": "text", "name": "geoname_id", "annotations": {"facetsort": ["-count"], "id": []}}, {"description": null, "label": "Name", "type": "text", "name": "name", "annotations": {"sortable": []}}, {"description": null, "label": "ASCII Name", "type": "text", "name": "ascii_name", "annotations": {}}, {"description": null, "label": "Alternate Names", "type": "text", "name": "alternate_names", "annotations": {"multivalued": [","]}}, {"description": "see http://www.geonames.org/export/codes.html", "label": "Feature Class", "type": "text", "name": "feature_class", "annotations": {}}, {"description": "see http://www.geonames.org/export/codes.html", "label": "Feature Code", "type": "text", "name": "feature_code", "annotations": {}}, {"description": null, "label": "Country Code", "type": "text", "name": "country_code", "annotations": {}}, {"description": null, "label": "Country name EN", "type": "text", "name": "cou_name_en", "annotations": {"facet": [], "facetsort": ["alphanum"], "disjunctive": []}}, {"description": null, "label": "Country Code 2", "type": "text", "name": "country_code_2", "annotations": {}}, {"description": null, "label": "Admin1 Code", "type": "text", "name": "admin1_code", "annotations": {}}, {"description": null, "label": "Admin2 Code", "type": "text", "name": "admin2_code", "annotations": {"facetsort": ["-count"]}}, {"description": null, "label": "Admin3 Code", "type": "text", "name": "admin3_code", "annotations": {}}, {"description": null, "label": "Admin4 Code", "type": "text", "name": "admin4_code", "annotations": {}}, {"description": null, "label": "Population", "type": "int", "name": "population", "annotations": {}}, {"description": null, "label": "Elevation", "type": "text", "name": "elevation", "annotations": {}}, {"description": null, "label": "DIgital Elevation Model", "type": "int", "name": "dem", "annotations": {}}, {"description": null, "label": "Timezone", "type": "text", "name": "timezone", "annotations": {"facet": [], "hierarchical": ["/"]}}, {"description": null, "label": "Modification date", "type": "date", "name": "modification_date", "annotations": {}}, {"description": null, "label": "LABEL EN", "type": "text", "name": "label_en", "annotations": {}}, {"description": null, "label": "Coordinates", "type": "geo_point_2d", "name": "coordinates", "annotations": {"facetsort": ["-count"]}}], "metas": {"default": {"records_count": 137609, "modified": "2021-06-23T14:37:45+00:00", "source_domain_address": null, "references": null, "keyword": null, "source_domain_title": null, "geographic_reference": ["world"], "timezone": null, "title": "Geonames - All Cities with a population > 1000", "parent_domain": null, "theme": null, "modified_updates_on_data_change": false, "metadata_processed": "2021-06-23T14:49:23.198000+00:00", "data_processed": "2021-06-23T14:49:23+00:00", "territory": ["World"], "description": null, "modified_updates_on_metadata_change": false, "shared_catalog": null, "source_domain": null, "attributions": null, "geographic_area_mode": null, "geographic_reference_auto": true, "geographic_area": null, "publisher": null, "language": "en", "license": null, "source_dataset": null, "metadata_languages": ["en"], "oauth_scope": null, "federated": false, "license_url": null}}, "features": ["geo", "analyze", "timeserie"]}]}; + } + + # Show dataset information + # + # + dataset_id - The identifier of the dataset to be queried. + # You can find it in the "Information" tab of the dataset page or in the dataset URL, right after `/datasets/`. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - The dataset + resource isolated function get catalog/datasets/[string dataset_id](map headers = {}, *GetDatasetQueries queries) returns json|error { + return {"dataset_id": "geonames-all-cities-with-a-population-1000", "dataset_uid": "da_s2n5ed", "attachments": [], "has_records": true, "data_visible": true, "fields": [{"description": null, "label": "Geoname ID", "type": "text", "name": "geoname_id", "annotations": {"facetsort": ["-count"], "id": []}}, {"description": null, "label": "Name", "type": "text", "name": "name", "annotations": {"sortable": []}}, {"annotations": {}, "description": null, "type": "text", "name": "ascii_name", "label": "ASCII Name"}, {"description": null, "label": "Alternate Names", "type": "text", "name": "alternate_names", "annotations": {"multivalued": [","]}}, {"annotations": {}, "label": "Feature Class", "type": "text", "name": "feature_class", "description": "see http://www.geonames.org/export/codes.html"}, {"annotations": {}, "label": "Feature Code", "type": "text", "name": "feature_code", "description": "see http://www.geonames.org/export/codes.html"}, {"annotations": {}, "description": null, "type": "text", "name": "country_code", "label": "Country Code"}, {"description": null, "label": "Country name EN", "type": "text", "name": "cou_name_en", "annotations": {"facet": [], "facetsort": ["alphanum"], "disjunctive": []}}, {"annotations": {}, "description": null, "type": "text", "name": "country_code_2", "label": "Country Code 2"}, {"annotations": {}, "description": null, "type": "text", "name": "admin1_code", "label": "Admin1 Code"}, {"description": null, "label": "Admin2 Code", "type": "text", "name": "admin2_code", "annotations": {"facetsort": ["-count"]}}, {"annotations": {}, "description": null, "type": "text", "name": "admin3_code", "label": "Admin3 Code"}, {"annotations": {}, "description": null, "type": "text", "name": "admin4_code", "label": "Admin4 Code"}, {"annotations": {}, "description": null, "type": "int", "name": "population", "label": "Population"}, {"annotations": {}, "description": null, "type": "text", "name": "elevation", "label": "Elevation"}, {"annotations": {}, "description": null, "type": "int", "name": "dem", "label": "DIgital Elevation Model"}, {"description": null, "label": "Timezone", "type": "text", "name": "timezone", "annotations": {"facet": [], "hierarchical": ["/"]}}, {"annotations": {}, "description": null, "type": "date", "name": "modification_date", "label": "Modification date"}, {"annotations": {}, "description": null, "type": "text", "name": "label_en", "label": "LABEL EN"}, {"description": null, "label": "Coordinates", "type": "geo_point_2d", "name": "coordinates", "annotations": {"facetsort": ["-count"]}}], "metas": {"default": {"records_count": 137611, "modified": "2021-06-23T07:50:20+00:00", "source_domain_address": null, "references": "https://download.geonames.org/export/dump/", "keyword": ["Geonames", "city", "world"], "source_domain_title": null, "geographic_reference": ["world"], "timezone": null, "title": "Geonames - All Cities with a population > 1000", "parent_domain": null, "theme": ["Administration, Government, Public finances, Citizenship"], "modified_updates_on_data_change": true, "metadata_processed": "2021-06-23T07:50:26.162000+00:00", "data_processed": "2021-06-22T08:47:08+00:00", "territory": ["World"], "description": "

All cities with a population > 1000 or seats of adm div (ca 80.000)

Sources and Contributions

  • Sources : GeoNames is aggregating over hundred different data sources. \t
  • Ambassadors : GeoNames Ambassadors help in many countries. \t
  • Wiki : A wiki allows to view the data and quickly fix error and add missing places. \t
  • Donations and Sponsoring : Costs for running GeoNames are covered by donations and sponsoring.

Enrichment:

  • add country name
", "modified_updates_on_metadata_change": false, "shared_catalog": null, "source_domain": null, "attributions": ["https://www.geonames.org/about.html"], "geographic_area_mode": null, "geographic_reference_auto": true, "geographic_area": null, "publisher": "GeoNames", "language": "en", "license": "CC BY 4.0", "source_dataset": null, "metadata_languages": ["en"], "oauth_scope": null, "federated": true, "license_url": "https://creativecommons.org/licenses/by/4.0/"}}, "features": ["geo", "analyze", "timeserie"]}; + } + + # List dataset attachments + # + # + dataset_id - The identifier of the dataset to be queried. + # You can find it in the "Information" tab of the dataset page or in the dataset URL, right after `/datasets/`. + # + headers - Headers to be sent with the request + # + return - List of all available attachments + resource isolated function get catalog/datasets/[string dataset_id]/attachments(map headers = {}) returns inline_response_200_2|error { + return {"links": [], "attachments": [{"href": "https://documentation-resources.opendatasoft.com/api/v2/catalog/datasets/geonames-all-cities-with-a-population-1000/attachments/cities1000_zip", "metas": {"mime-type": "application/zip", "title": "cities1000.zip"}}]}; + } + + # List dataset facets + # + # + dataset_id - The identifier of the dataset to be queried. + # You can find it in the "Information" tab of the dataset page or in the dataset URL, right after `/datasets/`. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - Facets enumeration + resource isolated function get catalog/datasets/[string dataset_id]/facets(map headers = {}, *GetRecordsFacetsQueries queries) returns inline_response_200_1|error { + return {"links": [], "facets": [{"facets": [{"count": 68888, "state": "displayed", "name": "Europe", "value": "Europe"}, {"count": 36276, "state": "displayed", "name": "America", "value": "America"}], "name": "timezone"}, {"facets": [{"count": 313, "state": "displayed", "name": "Afghanistan", "value": "Afghanistan"}, {"count": 356, "state": "displayed", "name": "Albania", "value": "Albania"}], "name": "cou_name_en"}]}; + } + + # Query dataset records + # + # + dataset_id - The identifier of the dataset to be queried. + # You can find it in the "Information" tab of the dataset page or in the dataset URL, right after `/datasets/`. + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - Records + resource isolated function get catalog/datasets/[string dataset_id]/records(map headers = {}, *GetRecordsQueries queries) returns results\-v2\.1|error { + return {"total_count": 137611, "results": [{"admin1_code": "27", "elevation": null, "name": "Saint-Leu", "modification_date": "2019-03-26", "alternate_names": ["Saint-Leu"], "feature_class": "P", "admin3_code": "711", "cou_name_en": "France", "coordinates": {"lat": 46.7306, "lon": 4.50083}, "country_code_2": null, "geoname_id": "2978771", "feature_code": "PPL", "label_en": "France", "dem": 366, "country_code": "FR", "ascii_name": "Saint-Leu", "timezone": "Europe/Paris", "admin2_code": "71", "admin4_code": "71436", "population": 29278}, {"admin1_code": "32", "elevation": null, "name": "Saint-Léger-lès-Domart", "modification_date": "2016-02-18", "alternate_names": ["Saint-Leger", "Saint-Leger-les-Domart", "Saint-Léger", "Saint-Léger-lès-Domart"], "feature_class": "P", "admin3_code": "802", "cou_name_en": "France", "coordinates": {"lat": 50.05208, "lon": 2.14067}, "country_code_2": null, "geoname_id": "2978817", "feature_code": "PPL", "label_en": "France", "dem": 31, "country_code": "FR", "ascii_name": "Saint-Leger-les-Domart", "timezone": "Europe/Paris", "admin2_code": "80", "admin4_code": "80706", "population": 1781}]}; + } + + # Read a dataset record + # + # + dataset_id - The identifier of the dataset to be queried. + # You can find it in the "Information" tab of the dataset page or in the dataset URL, right after `/datasets/`. + # + record_id - Record identifier + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - A single record + resource isolated function get catalog/datasets/[string dataset_id]/records/[string record_id](map headers = {}, *GetRecordQueries queries) returns record\-v2\.1|error { + return {"timezone": "Europe/Brussels", "elevation": null, "name": "Fraire", "modification_date": "2020-04-05", "dem": 238, "cou_name_en": "Belgium", "feature_class": "P", "admin3_code": "93", "alternate_names": ["Fraire"], "coordinates": {"lat": 50.26127, "lon": 4.5076}, "country_code_2": null, "geoname_id": "2798031", "feature_code": "PPL", "label_en": "Belgium", "admin4_code": "93088", "country_code": "BE", "ascii_name": "Fraire", "admin1_code": "WAL", "admin2_code": "WNA", "population": 1492}; + } + + # List facet values + # + # + headers - Headers to be sent with the request + # + queries - Queries to be sent with the request + # + return - An enumeration of facets + resource isolated function get catalog/facets(map headers = {}, *GetDatasetsFacetsQueries queries) returns inline_response_200_1|error { + return {"links": [], "facets": [{"name": "publisher", "facets": [{"count": 2, "state": "displayed", "name": "Opendatasoft", "value": "Opendatasoft"}, {"count": 2, "state": "displayed", "name": "Opendatasoft - Data Team", "value": "Opendatasoft - Data Team"}]}, {"name": "features", "facets": [{"count": 19, "state": "displayed", "name": "analyze", "value": "analyze"}, {"count": 13, "state": "displayed", "name": "timeserie", "value": "timeserie"}]}, {"name": "language", "facets": [{"count": 17, "state": "displayed", "name": "en", "value": "en"}, {"count": 4, "state": "displayed", "name": "fr", "value": "fr"}]}]}; + } +} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java index 971658d02..b433671c6 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package io.ballerina.openapi.core.generators.client; import io.ballerina.compiler.syntax.tree.ClassDefinitionNode; @@ -52,6 +69,11 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURN_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; +/** + * This generator class for generate the mock clients. + * + * @since 2.1.0 + */ public class BallerinaMockClientGenerator extends BallerinaClientGenerator { public BallerinaMockClientGenerator(OASClientConfig oasClientConfig) { super(oasClientConfig); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java index fc10f939a..5c0c9e8ea 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/model/OASClientConfig.java @@ -84,7 +84,7 @@ public boolean isMock() { */ public static class Builder { private OpenAPI openAPI; - private Filter filter; + private Filter filter = new Filter(); private boolean nullable = false; private boolean resourceMode = true; private boolean isPlugin = false; From 8f3edf14de04b7b7c6ed3fba0aab84b443f9814d Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 29 May 2024 10:17:59 +0530 Subject: [PATCH 06/15] Refactor filtering code --- .../client/MockClientGenerationTests.java | 4 +- .../client/BallerinaClientGenerator.java | 66 +++++++++++-------- .../mock/MockClientFunctionGenerator.java | 6 +- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java index 30ce99c9b..2bab7b2d9 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java @@ -65,7 +65,9 @@ public void mockClientTest() throws IOException, BallerinaOpenApiException { Optional functionBodyNode = mockFunctionBodyGenerator.getFunctionBodyNode(); FunctionBodyNode body = functionBodyNode.get(); String node = body.toString(); - Assert.assertEquals("{return {\"success\":true,\"size\":3,\"schedules\":[{\"id\":6,\"status\":\"Active\",\"filter\":\"Account.BillCycleDay = 8\",\"schedule\":\"At 6:00 AM, only on Monday and Tuesday\"}]};}", node); + Assert.assertEquals("{return {\"success\":true,\"size\":3,\"schedules\":[{\"id\":6,\"status\":\"Active\"" + + ",\"filter\":\"Account.BillCycleDay = 8\",\"schedule\":\"At 6:00 AM, only on Monday and" + + " Tuesday\"}]};}", node); } @Test diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java index 9a506cacb..69db8774a 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java @@ -271,39 +271,53 @@ private ClassDefinitionNode getClassDefinitionNode() { * This function is to filter the operations based on the user given tags and operations. */ protected Map> filterOperations() { - //todo refactor code - Map> filteredOperation = new HashMap<>(); + Map> filteredOperations = new HashMap<>(); List filterTags = filter.getTags(); List filterOperations = filter.getOperations(); - Set> pathsItems = openAPI.getPaths().entrySet(); - for (Map.Entry path : pathsItems) { + for (Map.Entry pathEntry : openAPI.getPaths().entrySet()) { Map operations = new HashMap<>(); - if (!path.getValue().readOperationsMap().isEmpty()) { - Map operationMap = path.getValue().readOperationsMap(); - for (Map.Entry operation : operationMap.entrySet()) { - List operationTags = operation.getValue().getTags(); - String operationId = operation.getValue().getOperationId(); - if (!filterTags.isEmpty() || !filterOperations.isEmpty()) { - // Generate remote function only if it is available in tag filter or operation filter or both - if (operationTags != null || ((!filterOperations.isEmpty()) && (operationId != null))) { - if (isaFilteredOperation(filterTags, filterOperations, operationTags, operationId)) { - operations.put(operation.getKey(), operation.getValue()); - } - } - } else { - operations.put(operation.getKey(), operation.getValue()); - } - } - if (!operations.isEmpty()) { - filteredOperation.put(path.getKey(), operations); + Map operationMap = pathEntry.getValue().readOperationsMap(); + if (operationMap.isEmpty()) { + continue; + } + for (Map.Entry operationEntry : operationMap.entrySet()) { + Operation operation = operationEntry.getValue(); + List operationTags = operation.getTags(); + String operationId = operation.getOperationId(); + + if (shouldFilterOperation(filterTags, filterOperations, operationTags, operationId)) { + operations.put(operationEntry.getKey(), operation); } } + if (!operations.isEmpty()) { + filteredOperations.put(pathEntry.getKey(), operations); + } } - return filteredOperation; + + return filteredOperations; + } + + /** + * This includes the filtering logic. + */ + private boolean shouldFilterOperation(List filterTags, List filterOperations, + List operationTags, String operationId) { + boolean hasFilterTags = !filterTags.isEmpty(); + boolean hasFilterOperations = !filterOperations.isEmpty(); + boolean hasOperationTags = operationTags != null; + boolean hasOperationId = operationId != null; + + if (!hasFilterTags && !hasFilterOperations) { + return true; + } + + return (hasFilterTags && hasOperationTags && !Collections.disjoint(filterTags, operationTags)) || + (hasFilterOperations && hasOperationId && filterOperations.contains(operationId)); } + /** * Generate metadata node of the class including documentation and display annotation. Content of the documentation * will be taken from the `description` section inside the `info` section in OpenAPI definition. @@ -570,12 +584,6 @@ protected QualifiedNameReferenceNode getHttpClientTypeName() { createIdentifierToken(GeneratorConstants.CLIENT)); } - private static boolean isaFilteredOperation(List filterTags, List filterOperations, - List operationTags, String operationId) { - return (operationTags != null && GeneratorUtils.hasTags(operationTags, filterTags)) || - ((operationId != null) && filterOperations.contains(operationId.trim())); - } - private List createRemoteFunctions(Map> filteredOperations) { List remoteFunctionNodes = new ArrayList<>(); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java index 89d7c2c67..5af0089ab 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java @@ -79,10 +79,7 @@ public MockClientFunctionGenerator(String path, Map.Entry generateFunction() throws BallerinaOpenApiException { - //function signature node, remote, resource if (isResourceFunction) { - //function signature node, remote, resource - //Create qualifier list NodeList qualifierList = createNodeList(createToken(RESOURCE_KEYWORD), createToken(ISOLATED_KEYWORD)); Token functionKeyWord = createToken(FUNCTION_KEYWORD); @@ -102,7 +99,6 @@ public Optional generateFunction() throws BallerinaOpenA }); return Optional.empty(); } - //create function signature ResourceFunctionSignatureGenerator signatureGenerator = new ResourceFunctionSignatureGenerator( operation.getValue(), openAPI, operation.getKey().toString(), path); @@ -112,6 +108,7 @@ public Optional generateFunction() throws BallerinaOpenA return Optional.empty(); } FunctionSignatureNode signatureNode = signatureNodeOptional.get(); + // function body generator MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, oasClientConfig.isStatusCodeBinding()); Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); @@ -128,7 +125,6 @@ public Optional generateFunction() throws BallerinaOpenA NodeList qualifierList = createNodeList(createToken(REMOTE_KEYWORD), createToken(ISOLATED_KEYWORD)); Token functionKeyWord = createToken(FUNCTION_KEYWORD); IdentifierToken functionName = createIdentifierToken(operation.getValue().getOperationId()); - RemoteFunctionSignatureGenerator signatureGenerator = new RemoteFunctionSignatureGenerator( operation.getValue(), openAPI, operation.getKey().toString().toLowerCase(Locale.ENGLISH), path); diagnostics.addAll(signatureGenerator.getDiagnostics()); From d49315e072be739899f3bb089378105bf17729ed Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 29 May 2024 12:16:45 +0530 Subject: [PATCH 07/15] Add tests for example in schema --- .../openapi/cmd/BallerinaCodeGenerator.java | 6 +- .../io/ballerina/openapi/cmd/BaseCmd.java | 5 + .../io/ballerina/openapi/cmd/OpenApiCmd.java | 8 +- .../client/MockClientGenerationTests.java | 33 +- .../client/mock/basic_response_example.bal | 29 + .../client/mock/basic_response_example.yaml | 3151 +--------------- .../client/mock/basic_response_examples.yaml | 3158 +++++++++++++++++ .../mock_client_for_advance_return_type.bal | 201 +- .../client/mock/mock_client_for_remote.bal | 141 +- openapi-core/build.gradle | 1 + .../client/AdvanceMockClientGenerator.java | 24 +- .../client/BallerinaClientGenerator.java | 2 +- ...aClientGeneratorWithStatusCodeBinding.java | 2 +- .../client/BallerinaMockClientGenerator.java | 4 +- .../client/diagnostic/DiagnosticMessages.java | 5 +- .../mock/MockClientFunctionGenerator.java | 1 + .../mock/MockFunctionBodyGenerator.java | 59 +- openapi-core/src/main/java/module-info.java | 2 +- 18 files changed, 3635 insertions(+), 3197 deletions(-) create mode 100644 openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal create mode 100644 openapi-cli/src/test/resources/generators/client/mock/basic_response_examples.yaml diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java index dfd290373..53bbe817b 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java @@ -449,11 +449,9 @@ private static BallerinaClientGenerator getBallerinaClientGenerator(OASClientCon boolean statusCodeBinding, boolean isMock) { if (statusCodeBinding && isMock) { return new AdvanceMockClientGenerator(oasClientConfig); - } - if (statusCodeBinding) { + } else if (statusCodeBinding) { return new BallerinaClientGeneratorWithStatusCodeBinding(oasClientConfig); - } - if (isMock) { + } else if (isMock) { return new BallerinaMockClientGenerator(oasClientConfig); } return new BallerinaClientGenerator(oasClientConfig); diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BaseCmd.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BaseCmd.java index 330fa6cc3..7385b68bd 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BaseCmd.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BaseCmd.java @@ -54,4 +54,9 @@ public class BaseCmd { @CommandLine.Option(names = {"--status-code-binding"}, description = "Generate the client methods with " + "status code response binding") public boolean statusCodeBinding; + + + @CommandLine.Option(names = {"--mock"}, hidden = true, + description = "Generate mock client with given response example") + public boolean mock; } diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java index 4e8ba83ee..e97c79c64 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java @@ -121,10 +121,6 @@ public class OpenApiCmd implements BLauncherCmd { description = "Generate service without data binding") private boolean generateWithoutDataBinding; - @CommandLine.Option(names = {"--mock"}, hidden = true, - description = "Generate service without data binding") - private boolean mock; - @CommandLine.Parameters private List argList; @@ -410,7 +406,7 @@ private void generatesClientFile(BallerinaCodeGenerator generator, Path resource boolean resourceMode, boolean statusCodeBinding) { try { generator.generateClient(resourcePath.toString(), targetOutputPath.toString(), filter, baseCmd.nullable, - resourceMode, statusCodeBinding, mock); + resourceMode, statusCodeBinding, baseCmd.mock); } catch (IOException | FormatterException | BallerinaOpenApiException | OASTypeGenException e) { if (e.getLocalizedMessage() != null) { @@ -455,7 +451,7 @@ private void generateBothFiles(BallerinaCodeGenerator generator, String fileName assert resourcePath != null; generator.generateClientAndService(resourcePath.toString(), fileName, targetOutputPath.toString(), filter, baseCmd.nullable, generateClientResourceFunctions, generateServiceType, generateWithoutDataBinding, - statusCodeBinding, mock); + statusCodeBinding, baseCmd.mock); } catch (BallerinaOpenApiException e) { outStream.println(e.getMessage()); exitError(this.exitWhenFinish); diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java index 2bab7b2d9..91447ea55 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java @@ -49,9 +49,10 @@ */ public class MockClientGenerationTests { private static final Path RES_DIR = Paths.get("src/test/resources/generators/client/mock").toAbsolutePath(); + @Test - public void mockClientTest() throws IOException, BallerinaOpenApiException { - Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); + public void mockClientTestForExamplesAttribute() throws IOException, BallerinaOpenApiException { + Path definitionPath = RES_DIR.resolve("basic_response_examples.yaml"); OpenAPI openapi = getOpenAPI(definitionPath); TypeHandler.createInstance(openapi, false); String path = "/api/v1/payment_run_schedules"; @@ -73,7 +74,7 @@ public void mockClientTest() throws IOException, BallerinaOpenApiException { @Test public void mockClientTestWithReferenceExample() throws IOException, BallerinaOpenApiException, ClientException { Path definitionPath = RES_DIR.resolve("ref_example.json"); - Path expectedPath = RES_DIR.resolve("file_provider/ballerina/reference_example.bal"); + Path expectedPath = RES_DIR.resolve("reference_example.bal"); OpenAPI openapi = getOpenAPI(definitionPath); TypeHandler.createInstance(openapi, false); OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); @@ -87,9 +88,9 @@ public void mockClientTestWithReferenceExample() throws IOException, BallerinaOp } @Test - public void mockClientForRemoteFunction() throws IOException, BallerinaOpenApiException, ClientException { - Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); - Path expectedPath = RES_DIR.resolve("file_provider/ballerina/mock_client_for_remote.bal"); + public void mockClientTestForRemoteFunction() throws IOException, BallerinaOpenApiException, ClientException { + Path definitionPath = RES_DIR.resolve("basic_response_examples.yaml"); + Path expectedPath = RES_DIR.resolve("mock_client_for_remote.bal"); OpenAPI openapi = getOpenAPI(definitionPath); TypeHandler.createInstance(openapi, false); OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); @@ -104,9 +105,25 @@ public void mockClientForRemoteFunction() throws IOException, BallerinaOpenApiEx } @Test - public void advanceMockClientGenerator() throws IOException, BallerinaOpenApiException, ClientException { + public void mockClientTestForExampleAttribute() throws IOException, BallerinaOpenApiException, ClientException { Path definitionPath = RES_DIR.resolve("basic_response_example.yaml"); - Path expectedPath = RES_DIR.resolve("file_provider/ballerina/mock_client_for_advance_return_type.bal"); + Path expectedPath = RES_DIR.resolve("basic_response_example.bal"); + OpenAPI openapi = getOpenAPI(definitionPath); + TypeHandler.createInstance(openapi, false); + OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); + OASClientConfig oasClientConfig = clientMetaDataBuilder + .withPlugin(false) + .withOpenAPI(openapi) + .withMock(true).build(); + BallerinaMockClientGenerator mockClientGenerator = new BallerinaMockClientGenerator(oasClientConfig); + SyntaxTree syntaxTree = mockClientGenerator.generateSyntaxTree(); + compareGeneratedSyntaxTreeWithExpectedSyntaxTree(expectedPath, syntaxTree); + } + + @Test + public void advanceMockClientTest() throws IOException, BallerinaOpenApiException, ClientException { + Path definitionPath = RES_DIR.resolve("basic_response_examples.yaml"); + Path expectedPath = RES_DIR.resolve("mock_client_for_advance_return_type.bal"); OpenAPI openapi = getOpenAPI(definitionPath); TypeHandler.createInstance(openapi, false); OASClientConfig.Builder clientMetaDataBuilder = new OASClientConfig.Builder(); diff --git a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal new file mode 100644 index 000000000..05390ea12 --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal @@ -0,0 +1,29 @@ +import ballerina/http; + +public isolated client class Client { + final http:Client clientEp; + # Gets invoked to initialize the `connector`. + # + # + config - The configurations to be used when initializing the `connector` + # + serviceUrl - URL of the target service + # + return - An error if connector initialization failed + public isolated function init(string serviceUrl, ConnectionConfig config = {}) returns error? { + return; + } + + # Get user + # + # + headers - Headers to be sent with the request + # + return - OK + resource isolated function get user(map headers = {}) returns ABC|error { + return {"id": 10, "name": "Jessica Smith"}; + } + + # Get a user + # + # + headers - Headers to be sent with the request + # + return - OK + resource isolated function get users(map headers = {}) returns inline_response_200|error { + return {"id": 10, "name": "Sam Smith"}; + } +} diff --git a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml index e98720a08..b6c12ef61 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml +++ b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.yaml @@ -2,3157 +2,44 @@ openapi: 3.0.0 info: version: 2021-08 title: 'API Reference: Collections' -tags: - - name: Advanced Payment Manager - - name: Collections Window - - name: Configurable Payment Retry - - name: Notes - - name: Statement Generator -security: - - BasicAuth: [] paths: - /api/v1/subscription_payment_runs/{payment_run_id}: + /user: get: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - operationId: getPaymentRun - summary: Get a payment run - description: > - Gets details about a particular payment run based on a payment run id in - Advanced Payment Manager. - tags: - - Advanced Payment Manager - parameters: - - in: path - name: payment_run_id - required: true - schema: - type: integer - description: >- - The payment run ID. A payment run id in Advanced Payment Manager is - different from a payment run id in Zuora. + summary: Get user responses: '200': - description: '' + description: OK content: application/json: - schema: - $ref: '#/components/schemas/GETPaymentRunResponse' - examples: - response: - value: - success: true - id: 6 - status: Complete - target_date: 2018-01-02T00:00:00.000Z - filter: Account.Currency = 'CAD' - payment_run_schedule_id: Adhoc - invoices_held: {} - metrics: - documents: 0 - payments: 0 - failed: 0 - skipped: 0 - amount: 0 - credit: 0 - /api/v1/subscription_payment_runs: - post: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - description: > - Creates a payment run to be executed immediately. You must specify the - **target_date** field. You can specify one or more filters to determine - which receivables are to be paid in the payment run. - - - If you use a custom filter, you cannot use other filters. - summary: Create a payment run - operationId: createPaymentRun - tags: - - Advanced Payment Manager - requestBody: - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/POSTPaymentRun' - required: true - responses: - '200': - description: '' - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/POSTPaymentRunResponse' - application/json: - examples: - response: - value: - id: 6 - success: 'true' - /api/v1/payment_run_schedules: - get: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - operationId: getPaymentRunSchedules - summary: Get all payment run schedules - description: | - Retrieves all payment run schedules in Advanced Payment Manager. - tags: - - Advanced Payment Manager - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETPaymentRunSchedulesResponse' - examples: - response: - value: - success: true - size: 3 - schedules: - - id: 6 - status: Active - filter: Account.BillCycleDay = 8 - schedule: At 6:00 AM, only on Monday and Tuesday - post: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - description: | - Creates a payment run schedule. - summary: Create a payment run schedule - operationId: createPaymentRunSchedule - tags: - - Advanced Payment Manager - requestBody: - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/POSTPaymentRunSchedule' - required: true - responses: - '200': - description: '' - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/POSTPaymentRunScheduleResponse' - application/json: - examples: - response: - value: - id: 6 - success: 'true' - /api/v1/payment_run_schedules/{schedule_id}: - get: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - operationId: getPaymentRunSchedule - summary: Get a payment run schedule - description: | - Gets details about a particular payment run schedule. - tags: - - Advanced Payment Manager - parameters: - - in: path - name: schedule_id - required: true - schema: - type: integer - description: The schedule ID - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETPaymentRunScheduleResponse' - examples: - response: - value: - success: true - id: 6 - status: Active - filter: Account.BillCycleDay = 8 - schedule: At 6:00 AM, only on Monday and Tuesday - put: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - operationId: updatePaymentRunSchedule - summary: Update a payment run schedule - description: | - Updates details about a particular payment run schedule. - tags: - - Advanced Payment Manager - parameters: - - in: path - name: schedule_id - required: true - schema: - type: integer - description: The schedule ID - requestBody: - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/PUTPaymentRunSchedule' - required: true - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/POSTPaymentRunScheduleResponse' - examples: - response: - value: - id: 6 - success: true - delete: - servers: - - url: https://advanced-payment-manager.apps.zuora.com - operationId: deletePaymentRunSchedule - summary: Cancel a payment run schedule - description: | - Cancels a payment run schedule. - tags: - - Advanced Payment Manager - parameters: - - in: path - name: schedule_id - required: true - schema: - type: integer - description: The schedule ID - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/DELETEPaymentRunScheduleResponse' - examples: - response: - value: - success: true - /api/v1/fetch_statement?statement_number={statement_number}: + schema: # Request body contents + $ref: "#/components/schemas/ABC" + example: # Sample object + id: 10 + name: "Jessica Smith" + /users: get: - servers: - - url: https://statement-generator.apps.zuora.com - operationId: getStatement - summary: Get a statement - description: > - Gets details about a particular statement. The statement will be - available for download in the response. - tags: - - Statement Generator - parameters: - - in: path - name: statement_number - required: true - schema: - type: integer - description: The statement number + summary: Get a user responses: '200': - description: '' - /api/v1/fetch_settings: - get: - servers: - - url: https://statement-generator.apps.zuora.com - operationId: getSettings - summary: Get Statement Generator settings - description: > - Gets several key settings of Statement Generator, including the - available templates, whether Invoice Settlement is enabled on the - tenant, the name of the default template, and the statement cycle being - used. - tags: - - Statement Generator - responses: - '200': - description: '' + description: "OK" content: application/json: - schema: - $ref: '#/components/schemas/GETStatementSettingsResponse' - examples: - response: - value: - success: true - templates: - - name: Default Template - - name: Template for end consumers - default_template: Default Template - default_cycle: Month - /api/v1/run: - post: - servers: - - url: https://statement-generator.apps.zuora.com - operationId: createAdhocStatementRun - summary: Create an ad hoc statement run - description: | - Create an ad hoc statement run. - tags: - - Statement Generator - requestBody: - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/POSTAdhocStatementRun' - required: true - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/POSTAdhocStatementRunResponse' - examples: - response: - value: - success: true - code: 200 - message: Success - statement_number: STA00000008 - /api/v1/execute: - post: - servers: - - url: https://statement-generator.apps.zuora.com - operationId: createCustomStatementRun - summary: Create a custom statement run - description: | - Create a custom statement run. - tags: - - Statement Generator - requestBody: - content: - application/json; charset=utf-8: - schema: - $ref: '#/components/schemas/POSTCustomStatementRun' - required: true - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/POSTCustomStatementRunResponse' - examples: - response: - value: - success: true - code: 200 - message: Success - execution_number: '2' - report_file: - /api/v1/accounts/{account_id}: - get: - servers: - - url: https://collections-window.apps.zuora.com - operationId: getAccount - summary: Get an account - description: | - Gets details about a particular account. - tags: - - Collections Window - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: The account ID. - example: 2c92c0f86680fd090166a578754812bd - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/CollectionAccount' - examples: - response: - value: - name: Testing Account - zuora_id: 2c92c0f863f2b1680163f579b7e705da - in_collections: true - collections_agent: 2018-01-02T00:00:00.000Z - account_currency: CAD - home_currency: USD - amount_due_account_currency: 15540 - amount_due_home_currency: 800.55 - last_open_invoice_date: '2018-06-12' - average_debt_age: 194.4 days - statuses: - In Collections: true - Pending: false - In Dispute: false - Paid In Full: false - /api/v1/accounts: - get: - servers: - - url: https://collections-window.apps.zuora.com - operationId: getAccounts - summary: Get all accounts - description: | - Gets all accounts that are currently or have been in collection. - tags: - - Collections Window - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETCollectionAccountsResponse' - examples: - response: - value: - accounts: - - name: Testing Account - zuora_id: 2c92c0f863f2b1680163f579b7e705da - in_collections: true - collections_agent: 2018-01-02T00:00:00.000Z - account_currency: CAD - home_currency: USD - amount_due_account_currency: 15540 - amount_due_home_currency: 800.55 - last_open_invoice_date: '2018-06-12' - average_debt_age: 194.4 days - statuses: - In Collections: 0 - Pending: 0 - In Dispute: 0 - Paid In Full: 0 - pagination: - page: 1 - page_length: 20 - next_page: >- - https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20 - /api/v1/users/{email}: - get: - servers: - - url: https://collections-window.apps.zuora.com - operationId: getCollectionsAgent - summary: Get a collections agent by email - description: > - Gets details about a collections agent, including the amount in - collections, and the statuses of the accounts that this agent is - assigned to. - tags: - - Collections Window - parameters: - - in: path - name: email - required: true - schema: - type: string - description: The email of the collections agent. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/CollectionAgent' - examples: - response: - value: - name: Testing User - email: test@zuora.com - zuora_identity_id: 2c92c0f96178a7a901619b10f5d12345 - amount_in_collections: 800.55 - accounts: 2 - account_statuses: - In Collections: 1 - Pending: 0 - In Dispute: 1 - Paid In Full: 0 - /api/v1/users: - get: - servers: - - url: https://collections-window.apps.zuora.com - operationId: getCollectionsAgents - summary: Get all collections agents - description: | - Gets the details of all collections agents. - tags: - - Collections Window - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETCollectionAgentsResponse' - examples: - response: - value: - accounts: - - name: Testing User - email: test@zuora.com - zuora_identity_id: 2c92c0f96178a7a901619b10f5d12345 - amount_in_collections: 800.55 - accounts: 2 - account_statuses: - In Collections: 1 - Pending: 0 - In Dispute: 1 - Paid In Full: 0 - pagination: - page: 1 - page_length: 20 - next_page: >- - https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20 - /api/v1/collections_info: - get: - servers: - - url: https://collections-window.apps.zuora.com - operationId: getCollectionsInfo - summary: Get an overview of collections - description: | - Gets an overview of the collections. - tags: - - Collections Window - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/CollectionsInfo' - examples: - response: - value: - accounts_in_collections: 24 - home_currency: USD - total_debt: '8379.78' - largest_debts: - - Test Account - 12438.00 USD - - Jimmy John - 8000.00 USD - - James Smith - 2450.55 USD - - Bob Roberts - 1000.00 USD - - Jim Reynolds - 829.00 USD - oldest_debts: - - Test Account - 2662 days - - Jimbo - 1494 days - - Steve Smith - 942 days - - Jason Williams - 678 days - - Will Jasons - 365 days - statuses: - In Collections: 24 - Pending: 2 - In Dispute: 5 - Paid in Full: 0 - /api/v1/accounts/{account_id}/update_status: - post: - servers: - - url: https://collections-window.apps.zuora.com - operationId: UpdateAccount - summary: Update account status - description: > - Updates the status of an account. You must use the two query parameters - to specify the status that you want to update, and the new value of the - status. - tags: - - Collections Window - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: The account ID. - example: 2c92c0f86680fd090166a578754812bd - - in: query - name: status - required: true - schema: - type: string - description: The status that you want to update for the specified account. - example: in_dispute - - in: query - name: value - schema: - type: boolean - description: >- - The new value of the status. 0 indicates false, while 1 indicates - true. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Whether the operation is successful. - examples: - response: - value: - success: true - /api/v1/accounts/{account_id}/update_agent: - post: - servers: - - url: https://collections-window.apps.zuora.com - operationId: UpdateAccountAgent - summary: Update account agent - description: > - Updates the collections agent that is displayed within the UI of - Collections Window, and the custom field for the agent displayed in - account details in the Zuora UI. - tags: - - Collections Window - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: The account ID. - example: 2c92c0f86680fd090166a578754812bd - - in: query - name: agent_email - required: true - schema: - type: string - description: The email of the agent. - example: jdoe@company.com - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Whether the operation is successful. - examples: - response: - value: - success: true - /api/v1/payments/active_invoice_cycle_information/: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getActiveInvoiceCycle - summary: Get active retry cycles for an invoice - description: > - Gets information of active retry cycles that have not been completed for - an invoice in Configurable Payment Retry. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: invoice_id - required: true - schema: - type: string - description: ID of an invoice. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETActiveInvoiceCycleResponse' - /api/v1/payments/active_debit_memo_cycle_information/: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getActiveDebitMemoCycle - summary: Get active retry cycles for a debit memo - description: > - Gets information of active retry cycles that have not been completed for - a debit memo in Configurable Payment Retry. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: debit_memo_id - required: true - schema: - type: string - description: ID of a debit memo. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETActiveDebitMemoCycleResponse' - /api/v1/payments/active_account_cycle_information/: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getActiveAccountCycle - summary: Get active retry cycles for an account - description: > - Gets information of active retry cycles that have not been completed for - an account in Configurable Payment Retry. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: ID of an account. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETActiveAccountCycleResponse' - /api/v1/payments/invoice_cycle_history/: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getInvoiceCycleHistory - summary: Get retry cycle history for an invoice - description: > - Gets information of all retry cycles for an invoice in Configurable - Payment Retry. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: invoice_id - required: true - schema: - type: string - description: ID of an invoice. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETInvoiceCycleHistoryResponse' - /api/v1/payments/debit_memo_cycle_history/: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getDebitMemoCycleHistory - summary: Get retry cycle history for a debit memo - description: > - Gets information of all retry cycles for a debit memo in Configurable - Payment Retry. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: debit_memo_id - required: true - schema: - type: string - description: ID of a debit memo. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETDebitMemoCycleHistoryResponse' - /api/v1/payments/account_cycle_history/: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getAccountCycleHistory - summary: Get retry cycle history for an account - description: > - Gets information of all retry cycles for an account in Configurable - Payment Retry. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: ID of an account. - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETAccountCycleHistoryResponse' - /api/v1/payments/execute_invoice_payment/: - put: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: executeExecuteInvoicePayment - summary: Execute invoice payment - description: > - For all active retry cycles associated with an invoice, schedules the - next payment retry attempt to occur in the next hourly payment processor - run. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: invoice_id - required: true - schema: - type: string - description: ID of an invoice. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs enqueued for processing: - [290, 291] - /api/v1/payments/execute_debit_memo_payment/: - put: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: executeExecuteDebitMemoPayment - summary: Execute debit memo payment - description: > - For all active retry cycles associated with a debit memo, schedules the - next payment retry attempt to occur in the next hourly payment processor - run. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: debit_memo_id - required: true - schema: - type: string - description: ID of a debit memo. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs enqueued for processing: - [300] - /api/v1/payments/execute_account_payments/: - put: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: executeExecuteAccountPayments - summary: Execute account payments - description: > - For all active retry cycles associated with an account, schedules the - next payment retry attempt to occur in the next hourly payment processor - run. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: ID of an account. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs enqueued for processing: - [310, 311, 312] - /api/v1/payments/execute_payments: - post: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: UpdateExecutePayments - summary: Execute payments - description: > - For all active retry cycles associated with the invoice, debit memo, - and/or account IDs provided, schedules the next payment retry attempt to - occur in the next hourly payment processor run. - tags: - - Configurable Payment Retry - requestBody: - content: - application/json: - schema: - type: object - properties: - account_ids: - type: array - items: - type: string - description: IDs of accounts. - debit_memo_ids: - description: IDs of debit memos. - type: array - items: - type: string - invoice_ids: - type: array - items: - type: string - description: IDs of invoices. - example: - account_ids: - - 2c92c0f96bd69165016bdcbf55ad5e62 - invoice_ids: - - 2c92c0fa7853052701785a38c6622473 - - 2c92c0fa7849b40a01784bc5de0f760f - debit_memo_ids: - - 2c92c0fa7853052701785a38f3bb267f - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs enqueued for processing: - [100, 101, 110, 111, 121] - /api/v1/payments/remove_invoice_from_retry_cycle/: - put: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: removeRemoveInoviceFromCycle - summary: Remove an invoice from retry cycle - description: | - Stops any active retry cycles associated with the invoice provided. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: invoice_id - required: true - schema: - type: string - description: ID of an invoice. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs have been removed from the - retry cycle: [290, 291] - /api/v1/payments/remove_debit_memo_from_retry_cycle/: - put: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: removeDebitMemoFromCycle - summary: Remove a debit memo from retry cycle - description: | - Stops any active retry cycles associated with the debit memo provided. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: debit_memo_id - required: true - schema: - type: string - description: ID of a debit memo. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs have been removed from the - retry cycle: [301] - /api/v1/payments/remove_account_from_retry_cycle/: - put: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: removeAccountFromCycle - summary: Remove an account from retry cycle - description: | - Stops any active retry cycles associated with the account provided. - tags: - - Configurable Payment Retry - parameters: - - in: path - name: account_id - required: true - schema: - type: string - description: ID of an account. - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: >- - Payments with the following IDs have been removed from the - retry cycle: [310, 311, 312] - /api/v1/payments/submit_failed_payment: - post: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: UpdateSubmitPaymentToCycle - summary: Submit a payment to retry cycle - description: > - Submit a failed payment into the retry cycle of Configurable Payment - Retry. - tags: - - Configurable Payment Retry - requestBody: - content: - application/json: - schema: - type: object - properties: - payment_id: - type: string - description: ID of a failed payment. - example: - payment_id: 2c92c0867849d42301784bc9ce806c31 - responses: - '200': - description: '' - content: - application/json: - schema: - type: object - properties: - success: - type: boolean - description: Indicates whether the operation is successful. - message: - type: string - description: The response message. - example: - success: true - message: Payment entered into retry process - /api/v1/metrics/baseline: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getBaselineMetrics - summary: Get baseline metrics - description: > - Gets baseline metrics for Configurable Payment Retry, including Retry - Success Rate and trend, Document Success Rate and trend, and Average - Days Outstanding and trend. See Response Schema for detailed - descriptions of the metrics. - tags: - - Configurable Payment Retry - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETBaselineMetricsResponse' - /api/v1/metrics/amount_recovered: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getAmountRecovered - summary: Get the Amount Recovered metrics - description: > - Gets the Amount Recovered metrics, including the total amount recovered - and the amount recovered over the last 30 days broken down by currency. - tags: - - Configurable Payment Retry - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETAmountRecoveredResponse' - /api/v1/metrics/customer_group_over_time: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getDocumentSuccessRateByCustomerGroup - summary: Get the Document Success Rate metrics by customer group - description: > - Gets the Document Success Rate timeseries for each customer group over - the past 6 months. The data of the current month will not be included. - For example, if it is April 15th today, the data for April will not be - included. Data for March and earlier will be shown. - tags: - - Configurable Payment Retry - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: >- - #/components/schemas/GETDocumentSuccessRateByCustomerGroupResponse - /api/v1/metrics/customer_group: - get: - servers: - - url: https://payment-retry.apps.zuora.com - operationId: getCustomerGroupMetrics - summary: Get the Customer Group metrics - description: > - Gets the following metrics for each customer group that is in the active - status: - - Document Success Rate and trend - - Retry Success Rate - - Average Attempts - tags: - - Configurable Payment Retry - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/GETCustomerGroupMetricsResponse' -components: - schemas: - Customer_Groups: - type: object - properties: - id: - type: integer - name: - type: string - smart_retry: - type: string - document_success_rate: - type: string - document_success_rate_trend: - type: string - retry_success_rate: - type: string - average_attempts: - type: string - Customer_Groups_Detail: - type: array - items: - type: string - - GETCustomerGroupMetricsResponse: - type: object - properties: - customer_groups: - type: array - items: - $ref: '#/components/schemas/Customer_Groups' - description: > - An array containing the following information for each customer - group. - - Customer group ID - - Customer group name - - Whether Smart Retry is enabled for this customer group - - Document Success Rate indicating the percentage of billing documents that are successfully collected - - The trend of change in Document Success Rate over the last 30 days - - Retry Success Rate indicating the percentage of the successful payment attempts - - Average Attempts indicating the average number of attempts required to recover funds - success: - type: boolean - description: > - Indicates whether the metrics are retrieved successfully. - - - If no data is loaded yet, a 200 response code will be returned with - the success field set to `true`. All expected fields will be present - but the value will be `null`. - example: - customer_groups: - - id: 1 - name: batch22 - smart_retry: false - document_success_rate: '17.17' - document_success_rate_trend: up - retry_success_rate: '21.76' - average_attempts: '4.11' - - id: 2 - name: Smart Retry - smart_retry: true - document_success_rate: '74.17' - document_success_rate_trend: down - retry_success_rate: '81.21' - average_attempts: '1.32' - - id: 4 - name: All Remaining Customers - smart_retry: false - document_success_rate: '16.35' - document_success_rate_trend: up - retry_success_rate: '15.21' - average_attempts: '3.32' - success: true - GETDocumentSuccessRateByCustomerGroupResponse: - type: object - properties: - customer_groups: - type: array - items: - $ref: '#/components/schemas/Customer_Groups_Detail' - description: > - An array containing the Document Success Rate timeseries for each - customer group represented by the customer group ID. - - A timeseries over the past 6 months is present in the format of - `: `. The data of the current - month is not included. For example, if it is April 15th today, the - data for April will not be included. Data for March and earlier will - be shown. - success: - type: boolean - description: > - Indicates whether the metrics are retrieved successfully. - - - If no data is loaded yet, a 200 response code will be returned with - the success field set to `true`. All expected fields will be present - but the value will be `null`. - example: - customer_groups: - '1': - '05_21': '17.53' - '04_21': '13.21' - '03_21': '14.92' - '02_21': '8.99' - '01_21': '34.25' - '12_20': '12.30' - '2': - '05_21': '11.11' - '04_21': '7.87' - '03_21': '26.00' - '02_21': '11.06' - '01_21': '13.43' - '12_20': '17.92' - '4': - '05_21': '11.13' - '04_21': '9.17' - '03_21': '17.20' - '02_21': '19.06' - '01_21': '12.43' - '12_20': '15.92' - success: true - GETAmountRecoveredResponse: - type: object - properties: - currency: - type: array - items: - type: string - description: > - An array containing the following information for each available - currency. - - If no payment of a given currency has been processed over the last - 30 days, the currency will not appear in the array. - - The total amount recovered to date - - The amount recovered over the last 30 days - success: - type: boolean - description: > - Indicates whether the metrics are retrieved successfully. - - - If no data is loaded yet, a 200 response code will be returned with - the success field set to `true`. All expected fields will be present - but the value will be `null`. - example: - currency: - USD: - total_amount: '77515.21' - last_30_days: '1100.01' - EUR: - total_amount: '337.19' - last_30_days: '17.17' - CAD: - total_amount: '123954.10' - last_30_days: '5132.87' - success: true - GETBaselineMetricsResponse: - type: object - properties: - retry_success_rate: - type: number - description: > - The percentage of successful payment attempts for all customer - groups on this Configurable Payment Retry instance so far. - - - Retry Success Rate = Number of successful retry payment attempts / - Total number of retry payments attempted - - - Payment attempts here are any payment attempts executed by - Configurable Payment Retry, excluding the initial payment run. - retry_success_rate_trend: - type: string - description: | - The trend of change in Retry Success Rate over the last 30 days. - document_success_rate: - type: number - description: > - The percentage of billing documents that are successfully collected, - for all customer groups on this Configurable Payment Retry instance - so far. - - - Document Success Rate = Number of billing documents collected / - Total number of billing documents attempted - - - Billing documents collected are any invoices and debit memos that - were paid through the payment attempt initiated by Configurable - Payment Retry. - document_success_rate_trend: - type: string - description: | - The trend of change in Document Success Rate over the last 30 days. - average_days_outstanding: - type: number - description: > - The average number of days invoices and debit memos are unpaid - before collection, for all customer groups on this Configurable - Payment Retry instance so far. - average_days_outstanding_trend: - type: string - description: > - The trend of change in Average Days Outstanding over the last 30 - days. - success: - type: boolean - description: > - Indicates whether the metrics are retrieved successfully. - - - If no data is loaded yet, a 200 response code will be returned with - the success field set to `true`. All expected fields will be present - but the value will be `null`. - example: - retry_success_rate: '11.90' - retry_success_rate_trend: down - document_success_rate: '13.54' - document_success_rate_trend: neutral - average_days_outstanding: '4.76' - average_days_outstanding_trend: up - success: true - GETActiveInvoiceCycleResponse: - type: object - properties: - cycles: - type: array - items: - $ref: '#/components/schemas/GETInvoiceCycleElementResponse' - description: > - An array containing information of all active retry cycles for an - invoice. See the schema and example for details. - example: - cycles: - - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 - invoice_id: 2c92c0f8778bf8cd017798168cb50e0b - payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 - currency: USD - status: Cycle Incomplete - current_attempt_number: 2 - next_attempt: '2021-04-01T19:27:34.648Z' - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c0867849d42301784bc9ca076c21 - time_of_execution: '2021-03-19T18:42:20.103Z' - source: PR-00000371 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-04-01T19:27:34.648-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - attempt_number: 2 - zuora_payment_id: 2c92c09c7849d3c101784bce0d0a06d5 - time_of_execution: '2021-03-19T18:52:24.137Z' - source: PR-00000372 - cpr_generated: true - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-19T09:53:39.845-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - GETInvoiceCycleElementResponse: - type: object - title: retry cycle object - properties: - account_id: - type: string - description: | - The ID of the customer account. - invoice_id: - type: string - description: | - The ID of the invoice. - payment_method_id: - type: string - description: | - The ID of the payment method. - currency: - type: string - description: | - The type of the currency used. - status: - type: string - description: | - The status of the retry cycle. - current_attempt_number: - type: number - description: | - The number of the current retry attempt. - next_attempt: - type: string - format: date-time - description: > - The date and time of the next retry attempt, in `yyyy-mm-dd - hh:mm:ss` format. - customer_group: - type: string - description: | - The name of the customer group. - attempts: - type: array - description: > - An array containing information of the retry attempts that have been - made. See the schema and example for details. - items: - $ref: '#/components/schemas/GETCycleElementAttemptResponse' - GETCycleElementAttemptResponse: - type: object - title: retry attempt object - properties: - attempt_number: - type: number - description: | - The number of the retry attempt. - zuora_payment_id: - type: string - description: | - The ID of the payment in Zuora Payments. - time_of_execution: - type: string - format: date-time - description: > - The date and time when the retry attempt was made, in `yyyy-mm-dd - hh:mm:ss` format. - source: - type: string - description: | - The number of the failed payment run. - cpr_generated: - type: boolean - description: > - Indicates whether the first retry attempt was generated by - Configurable Payment Retry. - - - `true` for the cases of the first retry attempt generated by CPR and - the second or later attempt. - - - `false` for the cases that the retry attempt was made by the payment - run or an external source during retry cycles. - success: - type: boolean - description: | - Indicates whether the retry attempt is successful. - amount_collected: - type: number - description: | - The amount collected in this retry attempt. - action_info: - type: object - description: | - Information about the action of the retry attempt. - properties: - action: - type: string - description: | - The action taken in the retry attempt. - retry_info: - type: object - description: | - Information about the next retry attempt. - properties: - next: - type: string - format: date-time - description: > - The date and time of the next retry attempt as determined by - `criteria`, in `yyyy-mm-dd hh:mm:ss` format. - criteria: - type: string - description: > - The criteria defined in the retry configuration in the CPR UI, - to specify whether the next retry will occur in an incremental - time or at a specific time or day. - mapping_info: - type: object - description: | - Information about the response code mapping for the retry attempt. - properties: - label: - type: string - description: > - The response code label, can be `Hard Decline`, `Soft Decline`, - `System Error`, or custom labels. - level: - type: string - description: > - The response code level for the payment gateway, can be `Code` - or `Description`. - customer_group_id: - type: number - description: | - The ID of the customer group. - gateway_info: - type: object - description: | - Information about the payment gateway. - properties: - id: - type: string - description: | - The ID of the payment gateway. - code: - type: string - description: | - The response code from the gateway. - response: - type: string - description: | - The response message from the gateway. - GETActiveDebitMemoCycleResponse: - type: object - properties: - cycles: - type: array - items: - $ref: '#/components/schemas/GETDebitMemoCycleElementResponse' - description: > - An array containing information of all active retry cycles for a - debit memo. See the schema and example for details. - example: - cycles: - - account_id: 2c92c0f868e161e70168e25eb51d755f - debit_memo_id: 2c92c0fa7853052701785a38f3bb267f - payment_method_id: 2c92c0f8774f1afe01775f6e533c4c06 - currency: USD - status: Cycle Incomplete - current_attempt_number: 2 - next_attempt: '2021-04-01T10:22:57.464Z' - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c085785305e201785a51af791979 - time_of_execution: '2021-03-23T16:50:18.878Z' - source: PR-00000376 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-23T07:51:30.380-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - attempt_number: 2 - zuora_payment_id: 2c92c0857881cf3e01788ee263b0331c - time_of_execution: '2021-04-01T19:21:55.207Z' - source: PR-00000380 - cpr_generated: true - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-04-01T10:22:57.464-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - GETDebitMemoCycleElementResponse: - type: object - title: retry cycle object - properties: - account_id: - type: string - description: | - The ID of the customer account. - debit_memo_id: - type: string - description: | - The ID of the debit memo. - payment_method_id: - type: string - description: | - The ID of the payment method. - currency: - type: string - description: | - The type of the currency used. - status: - type: string - description: | - The status of the retry cycle. - current_attempt_number: - type: number - description: | - The number of the current retry attempt. - next_attempt: - type: string - format: date-time - description: > - The date and time of the next retry attempt, in `yyyy-mm-dd - hh:mm:ss` format. - customer_group: - type: string - description: | - The name of the customer group. - attempts: - type: array - description: > - An array containing information of the retry attempts that have been - made. See the schema and example for details. - items: - $ref: '#/components/schemas/GETCycleElementAttemptResponse' - GETActiveAccountCycleResponse: - type: object - properties: - cycles: - type: array - items: - $ref: '#/components/schemas/GETAccountCycleElementResponse' - description: > - An array containing information of all active retry cycles for an - account. See the schema and example for details. - example: - cycles: - - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 - debit_memo_id: 2c92c0fb78532b0001785a38f6427976 - payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 - currency: USD - status: Cycle Incomplete - current_attempt_number: 1 - next_attempt: '2021-04-01T19:27:34.473Z' - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c085785305e201785a5199a6192d - time_of_execution: '2021-03-23T16:50:18.878Z' - source: PR-00000376 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-23T07:51:27.521-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 - invoice_id: 2c92c0fa7853052701785a38c6622473 - payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 - currency: USD - status: Cycle Incomplete - current_attempt_number: 1 - next_attempt: '2021-04-01T19:27:34.436Z' - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c085785305e201785a519d85193b - time_of_execution: '2021-03-23T16:50:18.878Z' - source: PR-00000376 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-23T07:51:28.161-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - GETAccountCycleElementResponse: - type: object - title: retry cycle object - properties: - account_id: - type: string - description: | - The ID of the customer account. - invoice_id: - type: string - description: | - The ID of the invoice. - debit_memo_id: - type: string - description: | - The ID of the debit memo. - payment_method_id: - type: string - description: | - The ID of the payment method. - currency: - type: string - description: | - The type of the currency used. - status: - type: string - description: | - The status of the retry cycle. - current_attempt_number: - type: number - description: | - The number of the current retry attempt. - next_attempt: - type: string - format: date-time - description: > - The date and time of the next retry attempt, in `yyyy-mm-dd - hh:mm:ss` format. - customer_group: - type: string - description: | - The name of the customer group. - attempts: - type: array - description: > - An array containing information of the retry attempts that have been - made. See the schema and example for details. - items: - $ref: '#/components/schemas/GETCycleElementAttemptResponse' - GETInvoiceCycleHistoryResponse: - type: object - properties: - cycles: - type: array - items: - $ref: '#/components/schemas/GETInvoiceCycleElementResponse' - description: > - An array containing information of all completed retry cycles for an - invoice. See the example for details. - example: - cycles: - - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 - invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 - payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a - currency: USD - status: Cycle Complete - current_attempt_number: 1 - next_attempt: null - customer_group: Testing Group - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 - time_of_execution: '2021-04-01T19:11:21.639Z' - source: PR-00000370 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Stop - retry_info: {} - mapping_info: - label: Hard Decline - level: code - customer_group_id: 5 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 - invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 - payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a - currency: USD - status: Cycle Complete - current_attempt_number: 2 - next_attempt: null - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 - time_of_execution: '2021-03-19T18:42:20.103Z' - source: PR-00000371 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-19T09:43:28.670-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - attempt_number: 2 - zuora_payment_id: 2c92c09c7849d3c101784bcdfc010671 - time_of_execution: '2021-03-19T18:52:24.137Z' - source: PR-00000372 - cpr_generated: true - success: false - amount_collected: '0.0' - action_info: - action: Stop - retry_info: {} - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - GETDebitMemoCycleHistoryResponse: - type: object - properties: - cycles: - type: array - items: - $ref: '#/components/schemas/GETDebitMemoCycleElementResponse' - description: > - An array containing information of all completed retry cycles for a - debit memo. See the example for details. - example: - cycles: - - account_id: 2c92c0f868e161e70168e25eb51d755f - debit_memo_id: 2c92c0fa7853052701785a38f3bb267f - payment_method_id: 2c92c0f8774f1afe01775f6e533c4c06 - currency: USD - status: Cycle Complete - current_attempt_number: 2 - next_attempt: null - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c085785305e201785a51af791979 - time_of_execution: '2021-03-23T16:50:18.878Z' - source: PR-00000376 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-23T07:51:30.380-09:00' - criteria: incremental_time - api_updated_retry_time: '2021-03-26T14:27:21.107-04:00' - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - attempt_number: 2 - zuora_payment_id: 2c92c0857881cf3e01788ee263b0331c - time_of_execution: '2021-04-01T19:21:55.207Z' - source: PR-00000378 - cpr_generated: true - success: false - amount_collected: '0.0' - action_info: - action: Stop - retry_info: {} - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - GETAccountCycleHistoryResponse: - type: object - properties: - cycles: - type: array - items: - $ref: '#/components/schemas/GETAccountCycleElementResponse' - description: > - An array containing information of all completed retry cycles for an - account. See the example for details. - example: - cycles: - - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 - invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 - payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a - currency: USD - status: Cycle Complete - current_attempt_number: 3 - next_attempt: '2021-03-19T18:53:39.641Z' - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 - time_of_execution: '2021-03-19T18:42:20.103Z' - source: PR-00000371 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-19T09:43:28.670-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - attempt_number: 2 - zuora_payment_id: 2c92c09c7849d3c101784bcdfc010671 - time_of_execution: '2021-03-19T18:52:24.137Z' - source: PR-00000372 - cpr_generated: true - success: false - amount_collected: '0.0' - action_info: - action: Stop - retry_info: {} - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 - invoice_id: 2c92c0fb78532b0f01785a38cede190a - payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a - currency: USD - status: Cycle Incomplete - current_attempt_number: 1 - next_attempt: '2021-03-24T19:34:20.254Z' - customer_group: All Remaining Customers - attempts: - - attempt_number: 1 - zuora_payment_id: 2c92c085785305e201785a51aae41969 - time_of_execution: '2021-03-23T16:50:18.878Z' - source: PR-00000376 - cpr_generated: false - success: false - amount_collected: '0.0' - action_info: - action: Retry - retry_info: - next: '2021-03-23T07:51:30.316-09:00' - criteria: incremental_time - mapping_info: - label: Hard Decline - level: code - customer_group_id: 1 - gateway_info: - id: 2c92c0f85e2d19af015e3a61d8947e5d - code: insufficient_funds - response: Your card has insufficient funds. - GETPaymentRunResponse: - type: object - properties: - success: - type: boolean - description: | - Whether the operation is successful. - id: - type: integer - description: | - The ID of the payment run in Advanced Payment Manager. - status: - type: string - description: | - The status of the payment run. - target_date: - type: string - format: date - description: | - The target date of the payment run, in the format of YYYY-MM-DD. - filter: - type: string - description: | - The filter that is used for the payment run. - payment_run_schedule_id: - type: string - description: > - The ID of the payment run schedule. If this is not a scheduled - payment run, the value is **Adhoc**. - invoices_held: - type: object - description: | - Invoices that are held by the payment run for manual processing. - metrics: - type: object - description: | - Metrics of the payment runs after completion. - errors: - type: array - description: > - Errors that occur in the operation. Available only when **success** - is **false**. - items: {} - POSTPaymentRun: - type: object - properties: - target_date: - type: string - format: date - description: > - The target date of the payment run to be created, in the format of - YYYY-MM-DD. - billrun: - type: string - description: > - A bill run name that is used to determine what receivables should be - included in the payment run. Valid only if the custom filter is not - used. - batch: - type: string - description: > - A batch name that is used to determine what receivables should be - included in the payment run. Valid only if the custom filter is not - used. - currency: - type: string - description: > - A three-character currency code that is used to determine what - receivables should be included in the payment run. Valid only if the - custom filter is not used. - payment_gateway: - type: string - description: > - A payment gateway name that is used to determine what receivables - should be included in the payment run. Valid only if the custom - filter is not used. - bill_cycle_day: - type: string - description: > - A bill cycle day value that is used to determine what receivables - should be included in the payment run. Valid only if the custom - filter is not used. - custom: - type: string - description: > - A custom ZOQL query that is used to determine what receivables - should be included in the payment run. It cannot be used with other - filters. - example: - target_date: '2019-02-04' - currency: CAD - POSTPaymentRunResponse: - type: object - properties: - id: - type: integer - description: | - The ID of the payment run in Advanced Payment Manager. - success: - type: boolean - description: | - Whether the operation is successful. - errors: - type: array - items: - type: string - description: > - Errors that occur in the operation. Available only when **success** - is **false**. - GETPaymentRunSchedulesResponse: - type: object - properties: - schedules: - type: array - items: - type: object - description: | - An array containing all available schedules. - size: - type: integer - description: | - The number of schedules retrieved. - success: - type: boolean - description: | - Whether the operation is successful. - errors: - type: array - description: > - Errors that occur in the operation. Available only when **success** - is **false**. - items: {} - GETPaymentRunScheduleResponse: - type: object - properties: - success: - type: boolean - description: | - Whether the operation is successful. - id: - type: integer - description: | - The ID of the payment run schedule in Advanced Payment Manager. - status: - type: string - description: | - The status of the payment run schedule. - filter: - type: string - format: date - description: | - The filter that is defined in the payment run schedule. - schedule: - type: string - description: | - The schedule that is defined for this payment run schedule. - errors: - type: array - description: > - Errors that occur in the operation. Available only when **success** - is **false**. - items: {} - POSTPaymentRunSchedule: - type: object - properties: - frequency: - type: string - description: | - The frequency of payment runs in the schedule. - enum: - - Daily - - Weekly - - Monthly - day: - type: string - description: > - The day of a month when payment runs need to be performed. Required - only if **frequency** is **Monthly**. Allowed values are 1-31 or - **L** (the last day of a month). - day_of_week: - type: array - items: - type: integer - description: > - An array of days in a week when payment runs need to be performed. - Required only if **frequency** is **Weekly**. Allowed integers are - 1-7. 1 stands for Monday. 2 stands for Tuesday, etc. - hour: - type: integer - description: > - The hour of a day when payment runs need to be performed. Allowed - values are 1-23. - billrun: - type: string - description: > - A bill run name that is used to determine what receivables should be - included in payment runs in this schedule. Valid only if the custom - filter is not used. - batch: - type: string - description: > - A batch name that is used to determine what receivables should be - included in payment runs in this schedule. Valid only if the custom - filter is not used. - currency: - type: string - description: > - A three-character currency code that is used to determine what - receivables should be included in payment runs in this schedule. - Valid only if the custom filter is not used. - payment_gateway: - type: string - description: > - A payment gateway name that is used to determine what receivables - should be included in payment runs in this schedule. Valid only if - the custom filter is not used. - bill_cycle_day: - type: string - description: > - A bill cycle day value that is used to determine what receivables - should be included in payment runs in this schedule. Valid only if - the custom filter is not used. - custom: - type: string - description: > - A custom ZOQL query that is used to determine what receivables - should be included in payment runs in this schedule. It cannot be - used with other filters. - example: - frequency: Weekly - days_of_week: - - 2 - - 3 - hour: 2 - currency: CAD - PUTPaymentRunSchedule: - type: object - properties: - frequency: - type: string - description: | - The frequency of payment runs in the schedule. - enum: - - Daily - - Weekly - - Monthly - day: - type: string - description: > - The day of a month when payment runs need to be performed. Required - only if **frequency** is **Monthly**. Allowed values are 1-31 or - **L** (the last day of a month). - day_of_week: - type: array - items: - type: integer - description: > - An array of days in a week when payment runs need to be performed. - Required only if **frequency** is **Weekly**. Allowed integers are - 1-7. 1 stands for Monday. 2 stands for Tuesday, etc. - hour: - type: integer - description: > - The hour of a day when payment runs need to be performed. Allowed - values are 1-23. - billrun: - type: string - description: > - A bill run name that is used to determine what receivables should be - included in payment runs in this schedule. Valid only if the custom - filter is not used. - batch: - type: string - description: > - A batch name that is used to determine what receivables should be - included in payment runs in this schedule. Valid only if the custom - filter is not used. - currency: - type: string - description: > - A three-character currency code that is used to determine what - receivables should be included in payment runs in this schedule. - Valid only if the custom filter is not used. - payment_gateway: - type: string - description: > - A payment gateway name that is used to determine what receivables - should be included in payment runs in this schedule. Valid only if - the custom filter is not used. - bill_cycle_day: - type: string - description: > - A bill cycle day value that is used to determine what receivables - should be included in payment runs in this schedule. Valid only if - the custom filter is not used. - custom: - type: string - description: > - A custom ZOQL query that is used to determine what receivables - should be included in payment runs in this schedule. It cannot be - used with other filters. - example: - currency: USD - POSTPaymentRunScheduleResponse: - type: object - properties: - id: - type: integer - description: | - The ID of the payment run schedule in Advanced Payment Manager. - success: - type: boolean - description: | - Whether the operation is successful. - errors: - type: array - items: - type: string - description: > - Errors that occur in the operation. Available only when **success** - is **false**. - DELETEPaymentRunScheduleResponse: - type: object - properties: - success: - type: boolean - description: | - Whether the operation is successful. - errors: - type: array - items: - type: string - description: > - Errors that occur in the operation. Available only when **success** - is **false**. - GETStatementsResponse: - type: object - properties: - statements: - type: array - items: - type: object - description: > - An array containing the requested number of statements of the - specified account. Every object contains an Amazon S3 link. You can - click the links to view and download the statements. The links will - expire in 10 minutes. - success: - type: boolean - description: | - Whether the operation is successful. - count: - type: integer - description: | - The number of statements retrieved. - GETStatementSettingsResponse: - type: object - properties: - success: - type: boolean - description: | - Whether the operation is successful. - templates: - type: array - items: - type: object - properties: - name: - type: string - description: The name of the template. - description: | - An array containing all available templates. - advanced_ar: - type: boolean - description: | - Whether Invoice Settlement is enabled on the tenant. - default_template: - type: string - description: | - The name of the default template. - default_cycle: - type: string - description: | - The statement cycle being used. - POSTAdhocStatementRun: - type: object - properties: - starting_date: - type: string - format: date - description: > - The starting date of the time period for which the statement is - generated, in the format of MM-DD-YYYY. - ending_date: - type: string - format: date - description: > - The ending date of the time period for which the statement is - generated, in the format of MM-DD-YYYY. - template_name: - type: string - description: | - The name of the template to be used in the statement run. - advanced_ar: - type: boolean - description: | - Specifies whether Invoice Settlement is enabled on the tenant. - account_id: - type: string - description: | - The ID of the account for which the statement run is created. - attach_to_account: - type: boolean - description: > - Indicates whether the generated statement is attached to the - account. - required: - - starting_date - - ending_date - - template_name - - advanced_ar - - account_id - example: - starting_date: 05-01-2018 - ending_date: 08-01-2018 - template_name: Default Name - advanced_ar: false - account_id: 2c92c0f964eaa3ec0164fad1eab730d6 - attach_to_account: true - POSTAdhocStatementRunResponse: - type: object - properties: - success: - type: boolean - description: | - Whether the operation is successful. - code: - type: integer - description: | - The response code. - message: - type: string - description: | - The response message. - statement_number: - type: string - description: | - The number of the statement. - POSTCustomStatementRun: - type: object - properties: - starting_date: - type: string - format: date - description: > - The starting date of the time period for which the statement is - generated, in the format of MM-DD-YYYY. - ending_date: - type: string - format: date - description: > - The ending date of the time period for which the statement is - generated, in the format of MM-DD-YYYY. - batch: - type: string - description: > - The billing batch of accounts the statements need to be generated - for. - mode: - type: string - description: | - The mode in which the run has to be executed. - enum: - - open_invoices - - open_balance - - no_invoice - - no_invoice_w_balance - - custom - required: - - starting_date - - ending_date - - batch - - mode - example: - starting_date: 05-01-2018 - ending_date: 08-01-2018 - batch: Batch40 - mode: custom - POSTCustomStatementRunResponse: - type: object - properties: - success: - type: boolean - description: | - Whether the operation is successful. - code: - type: integer - description: | - The response code. - message: - type: string - description: | - The response message. - execution_number: - type: string - description: | - The serial number of the execution. - report_file: - type: string - description: | - The URL pointing to the report of the run. - NotesObject: - type: object - properties: - success: - type: boolean - description: Whether this operation is successful or not. - data: - type: object - properties: - id: - type: integer - description: The ID of the Notes object. - object: - type: string - description: >- - The type of the object. It can be "Accounts" or "Invoices" for - Collections Window. - notesId: - type: string - description: >- - The ID of the Notes object. It is an account number (32-digit - hex) for Accounts object type, and an invoice number for - Invoices object type. - notesParentId: - type: string - description: >- - The ID of the parent object. For "Accounts" object, this - parameter is the account name that the Notes object is created - for. - createdAt: - type: string - format: time-date - description: The time and date when this Notes object is created. - updatedAt: - type: string - format: time-date - description: The last time and date when the Notes object is updated. - NotesObjectWithComment: - type: object - properties: - success: - type: boolean - description: Whether this operation is successful or not. - data: - type: object - properties: - id: - type: integer - description: The ID of the Notes object. - object: - type: string - description: >- - The type of the object. It can be "Accounts" or "Invoices" for - Collections Window. - notesId: - type: string - description: >- - The ID of the notes object. It is an account number (32-digit - hex) for Accounts object type, and an invoice number for - Invoices object type. - notesParentId: - type: string - description: >- - The ID of the parent object. For "Accounts" object, this - parameter is the account name that the Notes object is created - for. - createdAt: - type: string - format: time-date - description: The time and date when this Notes object is created. - updatedAt: - type: string - format: time-date - description: The last time and date when the Notes object is updated. - comments: - type: array - description: The array of comments for this Notes object. - items: - $ref: '#/components/schemas/NotesComment' - NotesUser: - type: object - properties: - id: - type: integer - description: The ID of the Notes user. - username: - type: string - description: The user name. - connectIdentity: - type: string - description: The connect ID of the user. It must be a 32-digit hex number. - email: - type: string - description: The email address of the user. - firstName: - type: string - description: The first name. - lastName: - type: string - description: The last name. - fullName: - type: string - description: The full name of the user. - platformRole: - type: string - description: The Platform role of the user. - timeZone: - type: string - description: The time zone setting for the user. - createdAt: - type: string - format: time-date - description: The time and date when this user record is created. - updatedAt: - type: string - format: time-date - description: The last time and date when the user record is updated. - escalationUser: - type: string - description: >- - The full name of the user that is configured to handle escalations - for the current user. - escalationUserId: - type: string - description: The ID of the escalation user. It must be a 32-digit hex number. - approvalAmount: - type: number - description: The amount of money that this user is allowed to approve. - avatar: - type: string - description: The link to the avatar image file for the user. - NotesReply: - type: object - properties: - id: - type: integer - description: The ID of the reply. - body: - type: string - description: The body of the reply. - image: - type: string - description: >- - The link to the image file. The value is null if no image files are - available. - attachment: - type: string - description: >- - The link to the attachment. The value is null if no attachments are - available. - createdAt: - type: string - format: time-date - description: The time and date when the reply is created. - updatedAt: - type: string - format: time-date - description: The last time and date when the reply is updated. - user: - $ref: '#/components/schemas/NotesUser' - NotesComment: - type: object - properties: - id: - type: integer - description: The ID of the comment. - body: - type: string - description: The body of the comment. - image: - type: string - description: >- - The link to the image file. The value is null if no image files are - available. - attachment: - type: string - description: >- - The link to the attachment. The value is null if no attachments are - available. - createdAt: - type: string - format: time-date - description: The time and date when this comment is created. - updatedAt: - type: string - format: time-date - description: The last time and date when the comment is updated. - user: - description: The creator of the comment. - $ref: '#/components/schemas/NotesUser' - replies: - type: array - description: An array of replies. - items: - $ref: '#/components/schemas/NotesReply' - NotesTasksResponse: - type: object - properties: - success: - type: boolean - description: Whether this operation is successful. - data: - type: object - description: The actual tasks data. - properties: - tasks: - type: array - items: + schema: # Request body contents type: object properties: id: type: integer - description: The ID of the task. - task: - type: string - description: The title of the task. - description: - type: string - description: Additional details about the task. - dueDate: - type: string - format: time-date - description: The due date and time of the task. - createdAt: - type: string - format: time-date - description: The date and time when this task is created. - updatedAt: - type: string - format: time-date - description: The last date and time when the task is updated. - reminderDate: + name: type: string - format: time-date - description: >- - The data and time when a reminder about this task needs to - be sent. - notifications: - type: string - description: >- - The message to be sent as notifications. It can be null if - no message is defined. - status: - type: string - description: The status of the task. - comment: - type: string - description: The comment about the task. - autoEscalation: - type: string - description: The automatic escalation setting for the task. - createdBy: - $ref: '#/components/schemas/NotesUser' - assignTo: - $ref: '#/components/schemas/NotesUser' - pagination: - type: object - properties: - page: - type: integer - description: The number of the current page. - per_page: - type: integer - description: The number of results on each page. - total_filtered_records: - type: integer - description: The total number of filtered records. - total_records: - type: integer - description: The total number of records. - NotesTasks: - type: object - properties: - id: - type: integer - description: The ID of the task. - task: - type: string - description: The title of the task. - description: - type: string - description: Additional details about the task. - dueDate: - type: string - format: time-date - description: The due date and time of the task. - createdAt: - type: string - format: time-date - description: The date and time when this task is created. - updatedAt: - type: string - format: time-date - description: The last date and time when the task is updated. - reminderDate: - type: string - format: time-date - description: The data and time when a reminder about this task needs to be sent. - notifications: - type: string - description: >- - The message to be sent as notifications. It can be null if no - message is defined. - status: - type: string - description: The status of the task. - comment: - type: string - description: The comment about the task. - autoEscalation: - type: string - description: The automatic escalation setting for the task. - createdBy: - $ref: '#/components/schemas/NotesUser' - assignTo: - $ref: '#/components/schemas/NotesUser' - NotesGroup: - type: object - properties: - id: - type: integer - description: The ID of the Notes group. - name: - type: string - description: The name of the group. - description: - type: string - description: Additional information about the group. - created_at: - type: string - format: time-date - description: The date and time when the group was created. - updated_at: - type: string - format: time-date - description: The last date and time when the group was updated. - users: - type: array - description: A list of all users in the group. - items: - $ref: '#/components/schemas/NotesUser' - NotesGroupsResponse: - type: object - properties: - success: - type: boolean - description: Whether this operation is successful. - groups: - type: array - items: - $ref: '#/components/schemas/NotesGroup' - NotesCreateGroupBody: - type: object - properties: - name: - type: string - description: The name of the group that you want to create. - description: - type: string - description: Additional information about the group. - NotesUpdateGroupBody: - type: object - properties: - name: - type: string - description: The new name of the group. - description: - type: string - description: The new description about the group. - NotesDeleteGroupBody: - type: object - properties: - name: - type: string - description: The name of the group that has been deleted. - description: - type: string - description: The description of the group. - NotesCreateGroupResponse: + example: # Sample object + id: 10 + name: Sam Smith +components: + schemas: + ABC: type: object properties: - success: - type: boolean - description: Whether the operation is successful. id: type: integer - description: The ID of the Notes group. - name: - type: string - description: The name of the group. - description: - type: string - description: Additional information about the group. - created_at: - type: string - format: time-date - description: The date and time when the group was created. - updated_at: - type: string - format: time-date - description: The last date and time when the group was updated. - users: - type: array - description: An array of users in the group. - items: - $ref: '#/components/schemas/NotesUser' - ResultsPagination: - type: object - description: The pagination information. - properties: - page: - type: integer - description: The current page. - page_length: - type: integer - description: The number of result on each page. - next_page: - type: string - description: The link to the next page of results. - CollectionAccount: - type: object - properties: name: type: string - description: The name of the account. - zuora_id: - type: string - description: The Zuora ID of the account. - in_collections: - type: boolean - description: Whether the account is in collections. - account_currency: - type: string - description: The currency that is currently used by the account. - home_currency: - type: string - description: The home currency of the tenant. - amount_due_account_currency: - type: number - description: The amount that is due for the account in the account currency. - amount_due_home_currency: - type: number - description: The amount that is due for the account in the tenant home currency. - last_open_invoice_date: - type: string - format: date - description: The last open invoice date. - average_debt_age: - type: number - description: The average age of all the debt of the account. - statuses: - $ref: '#/components/schemas/CollectionStatuses' - CollectionStatuses: - type: object - description: The status of the account. - properties: - In Collections: - type: boolean - description: Whether this account is in collections. - Pending: - type: boolean - description: Whether this account is pending. - In Dispute: - type: boolean - description: Whether this account is in dispute. - Paid In Full: - type: boolean - description: Whether this account has paid in full. - CollectionAgent: - type: object - properties: - name: - type: string - description: The name of the agent. - email: - type: string - description: The email of the agent. - zuora_identity_id: - type: string - description: The Zuora ID of the agent. - amount_in_collections: - type: number - description: The total amount of debt for accounts that are assigned to the user. - accounts: - type: integer - description: The number of accounts that are assigned to the user. - account_statuses: - type: object - properties: - In Collections: - type: integer - description: The number of accounts that are in collections. - Pending: - type: integer - description: The number of accounts that are pending. - In Disputes: - type: integer - description: The number of accounts that are in dispute. - Paid in Full: - type: integer - description: The number of accounts that have paid in full. - GETCollectionAgentsResponse: - type: object - properties: - accounts: - $ref: '#/components/schemas/CollectionAgent' - pagination: - $ref: '#/components/schemas/ResultsPagination' - GETCollectionAccountsResponse: - type: object - properties: - accounts: - type: array - description: The array of accounts. - items: - $ref: '#/components/schemas/CollectionAccount' - pagination: - $ref: '#/components/schemas/ResultsPagination' - CollectionsInfo: - type: object - properties: - accounts_in_collections: - type: integer - description: The number of accounts that are in collections. - home_currency: - type: string - description: The home currency of the tenant. - total_debt: - type: number - description: The total debt of all accounts that are in collections. - largest_debts: - type: array - description: The five largest debts that are in collections. - items: - type: string - description: An account number and the amount due for the account. - oldest_debts: - type: array - description: The five oldest debts that are in collections. - items: - type: string - description: An account number and the amount due for the account. - statuses: - type: object - properties: - In Collection: - type: integer - description: The number of accounts that are in collections. - Pending: - type: integer - description: The number of accounts that are in pending status. - In Dispute: - type: integer - description: The number of accounts that are in dispute. - Paid In Full: - type: integer - securitySchemes: - BasicAuth: - type: http - scheme: basic diff --git a/openapi-cli/src/test/resources/generators/client/mock/basic_response_examples.yaml b/openapi-cli/src/test/resources/generators/client/mock/basic_response_examples.yaml new file mode 100644 index 000000000..e98720a08 --- /dev/null +++ b/openapi-cli/src/test/resources/generators/client/mock/basic_response_examples.yaml @@ -0,0 +1,3158 @@ +openapi: 3.0.0 +info: + version: 2021-08 + title: 'API Reference: Collections' +tags: + - name: Advanced Payment Manager + - name: Collections Window + - name: Configurable Payment Retry + - name: Notes + - name: Statement Generator +security: + - BasicAuth: [] +paths: + /api/v1/subscription_payment_runs/{payment_run_id}: + get: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: getPaymentRun + summary: Get a payment run + description: > + Gets details about a particular payment run based on a payment run id in + Advanced Payment Manager. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: payment_run_id + required: true + schema: + type: integer + description: >- + The payment run ID. A payment run id in Advanced Payment Manager is + different from a payment run id in Zuora. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETPaymentRunResponse' + examples: + response: + value: + success: true + id: 6 + status: Complete + target_date: 2018-01-02T00:00:00.000Z + filter: Account.Currency = 'CAD' + payment_run_schedule_id: Adhoc + invoices_held: {} + metrics: + documents: 0 + payments: 0 + failed: 0 + skipped: 0 + amount: 0 + credit: 0 + /api/v1/subscription_payment_runs: + post: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + description: > + Creates a payment run to be executed immediately. You must specify the + **target_date** field. You can specify one or more filters to determine + which receivables are to be paid in the payment run. + + + If you use a custom filter, you cannot use other filters. + summary: Create a payment run + operationId: createPaymentRun + tags: + - Advanced Payment Manager + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRun' + required: true + responses: + '200': + description: '' + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRunResponse' + application/json: + examples: + response: + value: + id: 6 + success: 'true' + /api/v1/payment_run_schedules: + get: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: getPaymentRunSchedules + summary: Get all payment run schedules + description: | + Retrieves all payment run schedules in Advanced Payment Manager. + tags: + - Advanced Payment Manager + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETPaymentRunSchedulesResponse' + examples: + response: + value: + success: true + size: 3 + schedules: + - id: 6 + status: Active + filter: Account.BillCycleDay = 8 + schedule: At 6:00 AM, only on Monday and Tuesday + post: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + description: | + Creates a payment run schedule. + summary: Create a payment run schedule + operationId: createPaymentRunSchedule + tags: + - Advanced Payment Manager + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRunSchedule' + required: true + responses: + '200': + description: '' + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTPaymentRunScheduleResponse' + application/json: + examples: + response: + value: + id: 6 + success: 'true' + /api/v1/payment_run_schedules/{schedule_id}: + get: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: getPaymentRunSchedule + summary: Get a payment run schedule + description: | + Gets details about a particular payment run schedule. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: schedule_id + required: true + schema: + type: integer + description: The schedule ID + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETPaymentRunScheduleResponse' + examples: + response: + value: + success: true + id: 6 + status: Active + filter: Account.BillCycleDay = 8 + schedule: At 6:00 AM, only on Monday and Tuesday + put: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: updatePaymentRunSchedule + summary: Update a payment run schedule + description: | + Updates details about a particular payment run schedule. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: schedule_id + required: true + schema: + type: integer + description: The schedule ID + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/PUTPaymentRunSchedule' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/POSTPaymentRunScheduleResponse' + examples: + response: + value: + id: 6 + success: true + delete: + servers: + - url: https://advanced-payment-manager.apps.zuora.com + operationId: deletePaymentRunSchedule + summary: Cancel a payment run schedule + description: | + Cancels a payment run schedule. + tags: + - Advanced Payment Manager + parameters: + - in: path + name: schedule_id + required: true + schema: + type: integer + description: The schedule ID + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/DELETEPaymentRunScheduleResponse' + examples: + response: + value: + success: true + /api/v1/fetch_statement?statement_number={statement_number}: + get: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: getStatement + summary: Get a statement + description: > + Gets details about a particular statement. The statement will be + available for download in the response. + tags: + - Statement Generator + parameters: + - in: path + name: statement_number + required: true + schema: + type: integer + description: The statement number + responses: + '200': + description: '' + /api/v1/fetch_settings: + get: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: getSettings + summary: Get Statement Generator settings + description: > + Gets several key settings of Statement Generator, including the + available templates, whether Invoice Settlement is enabled on the + tenant, the name of the default template, and the statement cycle being + used. + tags: + - Statement Generator + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETStatementSettingsResponse' + examples: + response: + value: + success: true + templates: + - name: Default Template + - name: Template for end consumers + default_template: Default Template + default_cycle: Month + /api/v1/run: + post: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: createAdhocStatementRun + summary: Create an ad hoc statement run + description: | + Create an ad hoc statement run. + tags: + - Statement Generator + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTAdhocStatementRun' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/POSTAdhocStatementRunResponse' + examples: + response: + value: + success: true + code: 200 + message: Success + statement_number: STA00000008 + /api/v1/execute: + post: + servers: + - url: https://statement-generator.apps.zuora.com + operationId: createCustomStatementRun + summary: Create a custom statement run + description: | + Create a custom statement run. + tags: + - Statement Generator + requestBody: + content: + application/json; charset=utf-8: + schema: + $ref: '#/components/schemas/POSTCustomStatementRun' + required: true + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/POSTCustomStatementRunResponse' + examples: + response: + value: + success: true + code: 200 + message: Success + execution_number: '2' + report_file: + /api/v1/accounts/{account_id}: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getAccount + summary: Get an account + description: | + Gets details about a particular account. + tags: + - Collections Window + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: The account ID. + example: 2c92c0f86680fd090166a578754812bd + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/CollectionAccount' + examples: + response: + value: + name: Testing Account + zuora_id: 2c92c0f863f2b1680163f579b7e705da + in_collections: true + collections_agent: 2018-01-02T00:00:00.000Z + account_currency: CAD + home_currency: USD + amount_due_account_currency: 15540 + amount_due_home_currency: 800.55 + last_open_invoice_date: '2018-06-12' + average_debt_age: 194.4 days + statuses: + In Collections: true + Pending: false + In Dispute: false + Paid In Full: false + /api/v1/accounts: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getAccounts + summary: Get all accounts + description: | + Gets all accounts that are currently or have been in collection. + tags: + - Collections Window + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETCollectionAccountsResponse' + examples: + response: + value: + accounts: + - name: Testing Account + zuora_id: 2c92c0f863f2b1680163f579b7e705da + in_collections: true + collections_agent: 2018-01-02T00:00:00.000Z + account_currency: CAD + home_currency: USD + amount_due_account_currency: 15540 + amount_due_home_currency: 800.55 + last_open_invoice_date: '2018-06-12' + average_debt_age: 194.4 days + statuses: + In Collections: 0 + Pending: 0 + In Dispute: 0 + Paid In Full: 0 + pagination: + page: 1 + page_length: 20 + next_page: >- + https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20 + /api/v1/users/{email}: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getCollectionsAgent + summary: Get a collections agent by email + description: > + Gets details about a collections agent, including the amount in + collections, and the statuses of the accounts that this agent is + assigned to. + tags: + - Collections Window + parameters: + - in: path + name: email + required: true + schema: + type: string + description: The email of the collections agent. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/CollectionAgent' + examples: + response: + value: + name: Testing User + email: test@zuora.com + zuora_identity_id: 2c92c0f96178a7a901619b10f5d12345 + amount_in_collections: 800.55 + accounts: 2 + account_statuses: + In Collections: 1 + Pending: 0 + In Dispute: 1 + Paid In Full: 0 + /api/v1/users: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getCollectionsAgents + summary: Get all collections agents + description: | + Gets the details of all collections agents. + tags: + - Collections Window + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETCollectionAgentsResponse' + examples: + response: + value: + accounts: + - name: Testing User + email: test@zuora.com + zuora_identity_id: 2c92c0f96178a7a901619b10f5d12345 + amount_in_collections: 800.55 + accounts: 2 + account_statuses: + In Collections: 1 + Pending: 0 + In Dispute: 1 + Paid In Full: 0 + pagination: + page: 1 + page_length: 20 + next_page: >- + https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20 + /api/v1/collections_info: + get: + servers: + - url: https://collections-window.apps.zuora.com + operationId: getCollectionsInfo + summary: Get an overview of collections + description: | + Gets an overview of the collections. + tags: + - Collections Window + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/CollectionsInfo' + examples: + response: + value: + accounts_in_collections: 24 + home_currency: USD + total_debt: '8379.78' + largest_debts: + - Test Account - 12438.00 USD + - Jimmy John - 8000.00 USD + - James Smith - 2450.55 USD + - Bob Roberts - 1000.00 USD + - Jim Reynolds - 829.00 USD + oldest_debts: + - Test Account - 2662 days + - Jimbo - 1494 days + - Steve Smith - 942 days + - Jason Williams - 678 days + - Will Jasons - 365 days + statuses: + In Collections: 24 + Pending: 2 + In Dispute: 5 + Paid in Full: 0 + /api/v1/accounts/{account_id}/update_status: + post: + servers: + - url: https://collections-window.apps.zuora.com + operationId: UpdateAccount + summary: Update account status + description: > + Updates the status of an account. You must use the two query parameters + to specify the status that you want to update, and the new value of the + status. + tags: + - Collections Window + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: The account ID. + example: 2c92c0f86680fd090166a578754812bd + - in: query + name: status + required: true + schema: + type: string + description: The status that you want to update for the specified account. + example: in_dispute + - in: query + name: value + schema: + type: boolean + description: >- + The new value of the status. 0 indicates false, while 1 indicates + true. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Whether the operation is successful. + examples: + response: + value: + success: true + /api/v1/accounts/{account_id}/update_agent: + post: + servers: + - url: https://collections-window.apps.zuora.com + operationId: UpdateAccountAgent + summary: Update account agent + description: > + Updates the collections agent that is displayed within the UI of + Collections Window, and the custom field for the agent displayed in + account details in the Zuora UI. + tags: + - Collections Window + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: The account ID. + example: 2c92c0f86680fd090166a578754812bd + - in: query + name: agent_email + required: true + schema: + type: string + description: The email of the agent. + example: jdoe@company.com + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Whether the operation is successful. + examples: + response: + value: + success: true + /api/v1/payments/active_invoice_cycle_information/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getActiveInvoiceCycle + summary: Get active retry cycles for an invoice + description: > + Gets information of active retry cycles that have not been completed for + an invoice in Configurable Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETActiveInvoiceCycleResponse' + /api/v1/payments/active_debit_memo_cycle_information/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getActiveDebitMemoCycle + summary: Get active retry cycles for a debit memo + description: > + Gets information of active retry cycles that have not been completed for + a debit memo in Configurable Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETActiveDebitMemoCycleResponse' + /api/v1/payments/active_account_cycle_information/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getActiveAccountCycle + summary: Get active retry cycles for an account + description: > + Gets information of active retry cycles that have not been completed for + an account in Configurable Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETActiveAccountCycleResponse' + /api/v1/payments/invoice_cycle_history/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getInvoiceCycleHistory + summary: Get retry cycle history for an invoice + description: > + Gets information of all retry cycles for an invoice in Configurable + Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETInvoiceCycleHistoryResponse' + /api/v1/payments/debit_memo_cycle_history/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getDebitMemoCycleHistory + summary: Get retry cycle history for a debit memo + description: > + Gets information of all retry cycles for a debit memo in Configurable + Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETDebitMemoCycleHistoryResponse' + /api/v1/payments/account_cycle_history/: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getAccountCycleHistory + summary: Get retry cycle history for an account + description: > + Gets information of all retry cycles for an account in Configurable + Payment Retry. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETAccountCycleHistoryResponse' + /api/v1/payments/execute_invoice_payment/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: executeExecuteInvoicePayment + summary: Execute invoice payment + description: > + For all active retry cycles associated with an invoice, schedules the + next payment retry attempt to occur in the next hourly payment processor + run. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [290, 291] + /api/v1/payments/execute_debit_memo_payment/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: executeExecuteDebitMemoPayment + summary: Execute debit memo payment + description: > + For all active retry cycles associated with a debit memo, schedules the + next payment retry attempt to occur in the next hourly payment processor + run. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [300] + /api/v1/payments/execute_account_payments/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: executeExecuteAccountPayments + summary: Execute account payments + description: > + For all active retry cycles associated with an account, schedules the + next payment retry attempt to occur in the next hourly payment processor + run. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [310, 311, 312] + /api/v1/payments/execute_payments: + post: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: UpdateExecutePayments + summary: Execute payments + description: > + For all active retry cycles associated with the invoice, debit memo, + and/or account IDs provided, schedules the next payment retry attempt to + occur in the next hourly payment processor run. + tags: + - Configurable Payment Retry + requestBody: + content: + application/json: + schema: + type: object + properties: + account_ids: + type: array + items: + type: string + description: IDs of accounts. + debit_memo_ids: + description: IDs of debit memos. + type: array + items: + type: string + invoice_ids: + type: array + items: + type: string + description: IDs of invoices. + example: + account_ids: + - 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_ids: + - 2c92c0fa7853052701785a38c6622473 + - 2c92c0fa7849b40a01784bc5de0f760f + debit_memo_ids: + - 2c92c0fa7853052701785a38f3bb267f + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs enqueued for processing: + [100, 101, 110, 111, 121] + /api/v1/payments/remove_invoice_from_retry_cycle/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: removeRemoveInoviceFromCycle + summary: Remove an invoice from retry cycle + description: | + Stops any active retry cycles associated with the invoice provided. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: invoice_id + required: true + schema: + type: string + description: ID of an invoice. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs have been removed from the + retry cycle: [290, 291] + /api/v1/payments/remove_debit_memo_from_retry_cycle/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: removeDebitMemoFromCycle + summary: Remove a debit memo from retry cycle + description: | + Stops any active retry cycles associated with the debit memo provided. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: debit_memo_id + required: true + schema: + type: string + description: ID of a debit memo. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs have been removed from the + retry cycle: [301] + /api/v1/payments/remove_account_from_retry_cycle/: + put: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: removeAccountFromCycle + summary: Remove an account from retry cycle + description: | + Stops any active retry cycles associated with the account provided. + tags: + - Configurable Payment Retry + parameters: + - in: path + name: account_id + required: true + schema: + type: string + description: ID of an account. + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: >- + Payments with the following IDs have been removed from the + retry cycle: [310, 311, 312] + /api/v1/payments/submit_failed_payment: + post: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: UpdateSubmitPaymentToCycle + summary: Submit a payment to retry cycle + description: > + Submit a failed payment into the retry cycle of Configurable Payment + Retry. + tags: + - Configurable Payment Retry + requestBody: + content: + application/json: + schema: + type: object + properties: + payment_id: + type: string + description: ID of a failed payment. + example: + payment_id: 2c92c0867849d42301784bc9ce806c31 + responses: + '200': + description: '' + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + description: Indicates whether the operation is successful. + message: + type: string + description: The response message. + example: + success: true + message: Payment entered into retry process + /api/v1/metrics/baseline: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getBaselineMetrics + summary: Get baseline metrics + description: > + Gets baseline metrics for Configurable Payment Retry, including Retry + Success Rate and trend, Document Success Rate and trend, and Average + Days Outstanding and trend. See Response Schema for detailed + descriptions of the metrics. + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETBaselineMetricsResponse' + /api/v1/metrics/amount_recovered: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getAmountRecovered + summary: Get the Amount Recovered metrics + description: > + Gets the Amount Recovered metrics, including the total amount recovered + and the amount recovered over the last 30 days broken down by currency. + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETAmountRecoveredResponse' + /api/v1/metrics/customer_group_over_time: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getDocumentSuccessRateByCustomerGroup + summary: Get the Document Success Rate metrics by customer group + description: > + Gets the Document Success Rate timeseries for each customer group over + the past 6 months. The data of the current month will not be included. + For example, if it is April 15th today, the data for April will not be + included. Data for March and earlier will be shown. + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: >- + #/components/schemas/GETDocumentSuccessRateByCustomerGroupResponse + /api/v1/metrics/customer_group: + get: + servers: + - url: https://payment-retry.apps.zuora.com + operationId: getCustomerGroupMetrics + summary: Get the Customer Group metrics + description: > + Gets the following metrics for each customer group that is in the active + status: + - Document Success Rate and trend + - Retry Success Rate + - Average Attempts + tags: + - Configurable Payment Retry + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/GETCustomerGroupMetricsResponse' +components: + schemas: + Customer_Groups: + type: object + properties: + id: + type: integer + name: + type: string + smart_retry: + type: string + document_success_rate: + type: string + document_success_rate_trend: + type: string + retry_success_rate: + type: string + average_attempts: + type: string + Customer_Groups_Detail: + type: array + items: + type: string + + GETCustomerGroupMetricsResponse: + type: object + properties: + customer_groups: + type: array + items: + $ref: '#/components/schemas/Customer_Groups' + description: > + An array containing the following information for each customer + group. + - Customer group ID + - Customer group name + - Whether Smart Retry is enabled for this customer group + - Document Success Rate indicating the percentage of billing documents that are successfully collected + - The trend of change in Document Success Rate over the last 30 days + - Retry Success Rate indicating the percentage of the successful payment attempts + - Average Attempts indicating the average number of attempts required to recover funds + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + customer_groups: + - id: 1 + name: batch22 + smart_retry: false + document_success_rate: '17.17' + document_success_rate_trend: up + retry_success_rate: '21.76' + average_attempts: '4.11' + - id: 2 + name: Smart Retry + smart_retry: true + document_success_rate: '74.17' + document_success_rate_trend: down + retry_success_rate: '81.21' + average_attempts: '1.32' + - id: 4 + name: All Remaining Customers + smart_retry: false + document_success_rate: '16.35' + document_success_rate_trend: up + retry_success_rate: '15.21' + average_attempts: '3.32' + success: true + GETDocumentSuccessRateByCustomerGroupResponse: + type: object + properties: + customer_groups: + type: array + items: + $ref: '#/components/schemas/Customer_Groups_Detail' + description: > + An array containing the Document Success Rate timeseries for each + customer group represented by the customer group ID. + + A timeseries over the past 6 months is present in the format of + `: `. The data of the current + month is not included. For example, if it is April 15th today, the + data for April will not be included. Data for March and earlier will + be shown. + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + customer_groups: + '1': + '05_21': '17.53' + '04_21': '13.21' + '03_21': '14.92' + '02_21': '8.99' + '01_21': '34.25' + '12_20': '12.30' + '2': + '05_21': '11.11' + '04_21': '7.87' + '03_21': '26.00' + '02_21': '11.06' + '01_21': '13.43' + '12_20': '17.92' + '4': + '05_21': '11.13' + '04_21': '9.17' + '03_21': '17.20' + '02_21': '19.06' + '01_21': '12.43' + '12_20': '15.92' + success: true + GETAmountRecoveredResponse: + type: object + properties: + currency: + type: array + items: + type: string + description: > + An array containing the following information for each available + currency. + + If no payment of a given currency has been processed over the last + 30 days, the currency will not appear in the array. + - The total amount recovered to date + - The amount recovered over the last 30 days + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + currency: + USD: + total_amount: '77515.21' + last_30_days: '1100.01' + EUR: + total_amount: '337.19' + last_30_days: '17.17' + CAD: + total_amount: '123954.10' + last_30_days: '5132.87' + success: true + GETBaselineMetricsResponse: + type: object + properties: + retry_success_rate: + type: number + description: > + The percentage of successful payment attempts for all customer + groups on this Configurable Payment Retry instance so far. + + + Retry Success Rate = Number of successful retry payment attempts / + Total number of retry payments attempted + + + Payment attempts here are any payment attempts executed by + Configurable Payment Retry, excluding the initial payment run. + retry_success_rate_trend: + type: string + description: | + The trend of change in Retry Success Rate over the last 30 days. + document_success_rate: + type: number + description: > + The percentage of billing documents that are successfully collected, + for all customer groups on this Configurable Payment Retry instance + so far. + + + Document Success Rate = Number of billing documents collected / + Total number of billing documents attempted + + + Billing documents collected are any invoices and debit memos that + were paid through the payment attempt initiated by Configurable + Payment Retry. + document_success_rate_trend: + type: string + description: | + The trend of change in Document Success Rate over the last 30 days. + average_days_outstanding: + type: number + description: > + The average number of days invoices and debit memos are unpaid + before collection, for all customer groups on this Configurable + Payment Retry instance so far. + average_days_outstanding_trend: + type: string + description: > + The trend of change in Average Days Outstanding over the last 30 + days. + success: + type: boolean + description: > + Indicates whether the metrics are retrieved successfully. + + + If no data is loaded yet, a 200 response code will be returned with + the success field set to `true`. All expected fields will be present + but the value will be `null`. + example: + retry_success_rate: '11.90' + retry_success_rate_trend: down + document_success_rate: '13.54' + document_success_rate_trend: neutral + average_days_outstanding: '4.76' + average_days_outstanding_trend: up + success: true + GETActiveInvoiceCycleResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETInvoiceCycleElementResponse' + description: > + An array containing information of all active retry cycles for an + invoice. See the schema and example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 + invoice_id: 2c92c0f8778bf8cd017798168cb50e0b + payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 + currency: USD + status: Cycle Incomplete + current_attempt_number: 2 + next_attempt: '2021-04-01T19:27:34.648Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ca076c21 + time_of_execution: '2021-03-19T18:42:20.103Z' + source: PR-00000371 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-04-01T19:27:34.648-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c09c7849d3c101784bce0d0a06d5 + time_of_execution: '2021-03-19T18:52:24.137Z' + source: PR-00000372 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-19T09:53:39.845-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETInvoiceCycleElementResponse: + type: object + title: retry cycle object + properties: + account_id: + type: string + description: | + The ID of the customer account. + invoice_id: + type: string + description: | + The ID of the invoice. + payment_method_id: + type: string + description: | + The ID of the payment method. + currency: + type: string + description: | + The type of the currency used. + status: + type: string + description: | + The status of the retry cycle. + current_attempt_number: + type: number + description: | + The number of the current retry attempt. + next_attempt: + type: string + format: date-time + description: > + The date and time of the next retry attempt, in `yyyy-mm-dd + hh:mm:ss` format. + customer_group: + type: string + description: | + The name of the customer group. + attempts: + type: array + description: > + An array containing information of the retry attempts that have been + made. See the schema and example for details. + items: + $ref: '#/components/schemas/GETCycleElementAttemptResponse' + GETCycleElementAttemptResponse: + type: object + title: retry attempt object + properties: + attempt_number: + type: number + description: | + The number of the retry attempt. + zuora_payment_id: + type: string + description: | + The ID of the payment in Zuora Payments. + time_of_execution: + type: string + format: date-time + description: > + The date and time when the retry attempt was made, in `yyyy-mm-dd + hh:mm:ss` format. + source: + type: string + description: | + The number of the failed payment run. + cpr_generated: + type: boolean + description: > + Indicates whether the first retry attempt was generated by + Configurable Payment Retry. + + + `true` for the cases of the first retry attempt generated by CPR and + the second or later attempt. + + + `false` for the cases that the retry attempt was made by the payment + run or an external source during retry cycles. + success: + type: boolean + description: | + Indicates whether the retry attempt is successful. + amount_collected: + type: number + description: | + The amount collected in this retry attempt. + action_info: + type: object + description: | + Information about the action of the retry attempt. + properties: + action: + type: string + description: | + The action taken in the retry attempt. + retry_info: + type: object + description: | + Information about the next retry attempt. + properties: + next: + type: string + format: date-time + description: > + The date and time of the next retry attempt as determined by + `criteria`, in `yyyy-mm-dd hh:mm:ss` format. + criteria: + type: string + description: > + The criteria defined in the retry configuration in the CPR UI, + to specify whether the next retry will occur in an incremental + time or at a specific time or day. + mapping_info: + type: object + description: | + Information about the response code mapping for the retry attempt. + properties: + label: + type: string + description: > + The response code label, can be `Hard Decline`, `Soft Decline`, + `System Error`, or custom labels. + level: + type: string + description: > + The response code level for the payment gateway, can be `Code` + or `Description`. + customer_group_id: + type: number + description: | + The ID of the customer group. + gateway_info: + type: object + description: | + Information about the payment gateway. + properties: + id: + type: string + description: | + The ID of the payment gateway. + code: + type: string + description: | + The response code from the gateway. + response: + type: string + description: | + The response message from the gateway. + GETActiveDebitMemoCycleResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETDebitMemoCycleElementResponse' + description: > + An array containing information of all active retry cycles for a + debit memo. See the schema and example for details. + example: + cycles: + - account_id: 2c92c0f868e161e70168e25eb51d755f + debit_memo_id: 2c92c0fa7853052701785a38f3bb267f + payment_method_id: 2c92c0f8774f1afe01775f6e533c4c06 + currency: USD + status: Cycle Incomplete + current_attempt_number: 2 + next_attempt: '2021-04-01T10:22:57.464Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a51af791979 + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:30.380-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c0857881cf3e01788ee263b0331c + time_of_execution: '2021-04-01T19:21:55.207Z' + source: PR-00000380 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-04-01T10:22:57.464-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETDebitMemoCycleElementResponse: + type: object + title: retry cycle object + properties: + account_id: + type: string + description: | + The ID of the customer account. + debit_memo_id: + type: string + description: | + The ID of the debit memo. + payment_method_id: + type: string + description: | + The ID of the payment method. + currency: + type: string + description: | + The type of the currency used. + status: + type: string + description: | + The status of the retry cycle. + current_attempt_number: + type: number + description: | + The number of the current retry attempt. + next_attempt: + type: string + format: date-time + description: > + The date and time of the next retry attempt, in `yyyy-mm-dd + hh:mm:ss` format. + customer_group: + type: string + description: | + The name of the customer group. + attempts: + type: array + description: > + An array containing information of the retry attempts that have been + made. See the schema and example for details. + items: + $ref: '#/components/schemas/GETCycleElementAttemptResponse' + GETActiveAccountCycleResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETAccountCycleElementResponse' + description: > + An array containing information of all active retry cycles for an + account. See the schema and example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 + debit_memo_id: 2c92c0fb78532b0001785a38f6427976 + payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 + currency: USD + status: Cycle Incomplete + current_attempt_number: 1 + next_attempt: '2021-04-01T19:27:34.473Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a5199a6192d + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:27.521-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - account_id: 2c92c0f96bd69165016bdccdd6ce2f29 + invoice_id: 2c92c0fa7853052701785a38c6622473 + payment_method_id: 2c92c0f9774f2b3e01775f6f06d87b61 + currency: USD + status: Cycle Incomplete + current_attempt_number: 1 + next_attempt: '2021-04-01T19:27:34.436Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a519d85193b + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:28.161-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETAccountCycleElementResponse: + type: object + title: retry cycle object + properties: + account_id: + type: string + description: | + The ID of the customer account. + invoice_id: + type: string + description: | + The ID of the invoice. + debit_memo_id: + type: string + description: | + The ID of the debit memo. + payment_method_id: + type: string + description: | + The ID of the payment method. + currency: + type: string + description: | + The type of the currency used. + status: + type: string + description: | + The status of the retry cycle. + current_attempt_number: + type: number + description: | + The number of the current retry attempt. + next_attempt: + type: string + format: date-time + description: > + The date and time of the next retry attempt, in `yyyy-mm-dd + hh:mm:ss` format. + customer_group: + type: string + description: | + The name of the customer group. + attempts: + type: array + description: > + An array containing information of the retry attempts that have been + made. See the schema and example for details. + items: + $ref: '#/components/schemas/GETCycleElementAttemptResponse' + GETInvoiceCycleHistoryResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETInvoiceCycleElementResponse' + description: > + An array containing information of all completed retry cycles for an + invoice. See the example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Complete + current_attempt_number: 1 + next_attempt: null + customer_group: Testing Group + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 + time_of_execution: '2021-04-01T19:11:21.639Z' + source: PR-00000370 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 5 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Complete + current_attempt_number: 2 + next_attempt: null + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 + time_of_execution: '2021-03-19T18:42:20.103Z' + source: PR-00000371 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-19T09:43:28.670-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c09c7849d3c101784bcdfc010671 + time_of_execution: '2021-03-19T18:52:24.137Z' + source: PR-00000372 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETDebitMemoCycleHistoryResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETDebitMemoCycleElementResponse' + description: > + An array containing information of all completed retry cycles for a + debit memo. See the example for details. + example: + cycles: + - account_id: 2c92c0f868e161e70168e25eb51d755f + debit_memo_id: 2c92c0fa7853052701785a38f3bb267f + payment_method_id: 2c92c0f8774f1afe01775f6e533c4c06 + currency: USD + status: Cycle Complete + current_attempt_number: 2 + next_attempt: null + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a51af791979 + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:30.380-09:00' + criteria: incremental_time + api_updated_retry_time: '2021-03-26T14:27:21.107-04:00' + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c0857881cf3e01788ee263b0331c + time_of_execution: '2021-04-01T19:21:55.207Z' + source: PR-00000378 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETAccountCycleHistoryResponse: + type: object + properties: + cycles: + type: array + items: + $ref: '#/components/schemas/GETAccountCycleElementResponse' + description: > + An array containing information of all completed retry cycles for an + account. See the example for details. + example: + cycles: + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fa7849b3ff01784bc5e8ee18b5 + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Complete + current_attempt_number: 3 + next_attempt: '2021-03-19T18:53:39.641Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c0867849d42301784bc9ce806c31 + time_of_execution: '2021-03-19T18:42:20.103Z' + source: PR-00000371 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-19T09:43:28.670-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - attempt_number: 2 + zuora_payment_id: 2c92c09c7849d3c101784bcdfc010671 + time_of_execution: '2021-03-19T18:52:24.137Z' + source: PR-00000372 + cpr_generated: true + success: false + amount_collected: '0.0' + action_info: + action: Stop + retry_info: {} + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + - account_id: 2c92c0f96bd69165016bdcbf55ad5e62 + invoice_id: 2c92c0fb78532b0f01785a38cede190a + payment_method_id: 2c92c0f9774f2b3e01775f6cf2fb726a + currency: USD + status: Cycle Incomplete + current_attempt_number: 1 + next_attempt: '2021-03-24T19:34:20.254Z' + customer_group: All Remaining Customers + attempts: + - attempt_number: 1 + zuora_payment_id: 2c92c085785305e201785a51aae41969 + time_of_execution: '2021-03-23T16:50:18.878Z' + source: PR-00000376 + cpr_generated: false + success: false + amount_collected: '0.0' + action_info: + action: Retry + retry_info: + next: '2021-03-23T07:51:30.316-09:00' + criteria: incremental_time + mapping_info: + label: Hard Decline + level: code + customer_group_id: 1 + gateway_info: + id: 2c92c0f85e2d19af015e3a61d8947e5d + code: insufficient_funds + response: Your card has insufficient funds. + GETPaymentRunResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + id: + type: integer + description: | + The ID of the payment run in Advanced Payment Manager. + status: + type: string + description: | + The status of the payment run. + target_date: + type: string + format: date + description: | + The target date of the payment run, in the format of YYYY-MM-DD. + filter: + type: string + description: | + The filter that is used for the payment run. + payment_run_schedule_id: + type: string + description: > + The ID of the payment run schedule. If this is not a scheduled + payment run, the value is **Adhoc**. + invoices_held: + type: object + description: | + Invoices that are held by the payment run for manual processing. + metrics: + type: object + description: | + Metrics of the payment runs after completion. + errors: + type: array + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + items: {} + POSTPaymentRun: + type: object + properties: + target_date: + type: string + format: date + description: > + The target date of the payment run to be created, in the format of + YYYY-MM-DD. + billrun: + type: string + description: > + A bill run name that is used to determine what receivables should be + included in the payment run. Valid only if the custom filter is not + used. + batch: + type: string + description: > + A batch name that is used to determine what receivables should be + included in the payment run. Valid only if the custom filter is not + used. + currency: + type: string + description: > + A three-character currency code that is used to determine what + receivables should be included in the payment run. Valid only if the + custom filter is not used. + payment_gateway: + type: string + description: > + A payment gateway name that is used to determine what receivables + should be included in the payment run. Valid only if the custom + filter is not used. + bill_cycle_day: + type: string + description: > + A bill cycle day value that is used to determine what receivables + should be included in the payment run. Valid only if the custom + filter is not used. + custom: + type: string + description: > + A custom ZOQL query that is used to determine what receivables + should be included in the payment run. It cannot be used with other + filters. + example: + target_date: '2019-02-04' + currency: CAD + POSTPaymentRunResponse: + type: object + properties: + id: + type: integer + description: | + The ID of the payment run in Advanced Payment Manager. + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + items: + type: string + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + GETPaymentRunSchedulesResponse: + type: object + properties: + schedules: + type: array + items: + type: object + description: | + An array containing all available schedules. + size: + type: integer + description: | + The number of schedules retrieved. + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + items: {} + GETPaymentRunScheduleResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + id: + type: integer + description: | + The ID of the payment run schedule in Advanced Payment Manager. + status: + type: string + description: | + The status of the payment run schedule. + filter: + type: string + format: date + description: | + The filter that is defined in the payment run schedule. + schedule: + type: string + description: | + The schedule that is defined for this payment run schedule. + errors: + type: array + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + items: {} + POSTPaymentRunSchedule: + type: object + properties: + frequency: + type: string + description: | + The frequency of payment runs in the schedule. + enum: + - Daily + - Weekly + - Monthly + day: + type: string + description: > + The day of a month when payment runs need to be performed. Required + only if **frequency** is **Monthly**. Allowed values are 1-31 or + **L** (the last day of a month). + day_of_week: + type: array + items: + type: integer + description: > + An array of days in a week when payment runs need to be performed. + Required only if **frequency** is **Weekly**. Allowed integers are + 1-7. 1 stands for Monday. 2 stands for Tuesday, etc. + hour: + type: integer + description: > + The hour of a day when payment runs need to be performed. Allowed + values are 1-23. + billrun: + type: string + description: > + A bill run name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + batch: + type: string + description: > + A batch name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + currency: + type: string + description: > + A three-character currency code that is used to determine what + receivables should be included in payment runs in this schedule. + Valid only if the custom filter is not used. + payment_gateway: + type: string + description: > + A payment gateway name that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + bill_cycle_day: + type: string + description: > + A bill cycle day value that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + custom: + type: string + description: > + A custom ZOQL query that is used to determine what receivables + should be included in payment runs in this schedule. It cannot be + used with other filters. + example: + frequency: Weekly + days_of_week: + - 2 + - 3 + hour: 2 + currency: CAD + PUTPaymentRunSchedule: + type: object + properties: + frequency: + type: string + description: | + The frequency of payment runs in the schedule. + enum: + - Daily + - Weekly + - Monthly + day: + type: string + description: > + The day of a month when payment runs need to be performed. Required + only if **frequency** is **Monthly**. Allowed values are 1-31 or + **L** (the last day of a month). + day_of_week: + type: array + items: + type: integer + description: > + An array of days in a week when payment runs need to be performed. + Required only if **frequency** is **Weekly**. Allowed integers are + 1-7. 1 stands for Monday. 2 stands for Tuesday, etc. + hour: + type: integer + description: > + The hour of a day when payment runs need to be performed. Allowed + values are 1-23. + billrun: + type: string + description: > + A bill run name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + batch: + type: string + description: > + A batch name that is used to determine what receivables should be + included in payment runs in this schedule. Valid only if the custom + filter is not used. + currency: + type: string + description: > + A three-character currency code that is used to determine what + receivables should be included in payment runs in this schedule. + Valid only if the custom filter is not used. + payment_gateway: + type: string + description: > + A payment gateway name that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + bill_cycle_day: + type: string + description: > + A bill cycle day value that is used to determine what receivables + should be included in payment runs in this schedule. Valid only if + the custom filter is not used. + custom: + type: string + description: > + A custom ZOQL query that is used to determine what receivables + should be included in payment runs in this schedule. It cannot be + used with other filters. + example: + currency: USD + POSTPaymentRunScheduleResponse: + type: object + properties: + id: + type: integer + description: | + The ID of the payment run schedule in Advanced Payment Manager. + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + items: + type: string + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + DELETEPaymentRunScheduleResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + errors: + type: array + items: + type: string + description: > + Errors that occur in the operation. Available only when **success** + is **false**. + GETStatementsResponse: + type: object + properties: + statements: + type: array + items: + type: object + description: > + An array containing the requested number of statements of the + specified account. Every object contains an Amazon S3 link. You can + click the links to view and download the statements. The links will + expire in 10 minutes. + success: + type: boolean + description: | + Whether the operation is successful. + count: + type: integer + description: | + The number of statements retrieved. + GETStatementSettingsResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + templates: + type: array + items: + type: object + properties: + name: + type: string + description: The name of the template. + description: | + An array containing all available templates. + advanced_ar: + type: boolean + description: | + Whether Invoice Settlement is enabled on the tenant. + default_template: + type: string + description: | + The name of the default template. + default_cycle: + type: string + description: | + The statement cycle being used. + POSTAdhocStatementRun: + type: object + properties: + starting_date: + type: string + format: date + description: > + The starting date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + ending_date: + type: string + format: date + description: > + The ending date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + template_name: + type: string + description: | + The name of the template to be used in the statement run. + advanced_ar: + type: boolean + description: | + Specifies whether Invoice Settlement is enabled on the tenant. + account_id: + type: string + description: | + The ID of the account for which the statement run is created. + attach_to_account: + type: boolean + description: > + Indicates whether the generated statement is attached to the + account. + required: + - starting_date + - ending_date + - template_name + - advanced_ar + - account_id + example: + starting_date: 05-01-2018 + ending_date: 08-01-2018 + template_name: Default Name + advanced_ar: false + account_id: 2c92c0f964eaa3ec0164fad1eab730d6 + attach_to_account: true + POSTAdhocStatementRunResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + code: + type: integer + description: | + The response code. + message: + type: string + description: | + The response message. + statement_number: + type: string + description: | + The number of the statement. + POSTCustomStatementRun: + type: object + properties: + starting_date: + type: string + format: date + description: > + The starting date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + ending_date: + type: string + format: date + description: > + The ending date of the time period for which the statement is + generated, in the format of MM-DD-YYYY. + batch: + type: string + description: > + The billing batch of accounts the statements need to be generated + for. + mode: + type: string + description: | + The mode in which the run has to be executed. + enum: + - open_invoices + - open_balance + - no_invoice + - no_invoice_w_balance + - custom + required: + - starting_date + - ending_date + - batch + - mode + example: + starting_date: 05-01-2018 + ending_date: 08-01-2018 + batch: Batch40 + mode: custom + POSTCustomStatementRunResponse: + type: object + properties: + success: + type: boolean + description: | + Whether the operation is successful. + code: + type: integer + description: | + The response code. + message: + type: string + description: | + The response message. + execution_number: + type: string + description: | + The serial number of the execution. + report_file: + type: string + description: | + The URL pointing to the report of the run. + NotesObject: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful or not. + data: + type: object + properties: + id: + type: integer + description: The ID of the Notes object. + object: + type: string + description: >- + The type of the object. It can be "Accounts" or "Invoices" for + Collections Window. + notesId: + type: string + description: >- + The ID of the Notes object. It is an account number (32-digit + hex) for Accounts object type, and an invoice number for + Invoices object type. + notesParentId: + type: string + description: >- + The ID of the parent object. For "Accounts" object, this + parameter is the account name that the Notes object is created + for. + createdAt: + type: string + format: time-date + description: The time and date when this Notes object is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the Notes object is updated. + NotesObjectWithComment: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful or not. + data: + type: object + properties: + id: + type: integer + description: The ID of the Notes object. + object: + type: string + description: >- + The type of the object. It can be "Accounts" or "Invoices" for + Collections Window. + notesId: + type: string + description: >- + The ID of the notes object. It is an account number (32-digit + hex) for Accounts object type, and an invoice number for + Invoices object type. + notesParentId: + type: string + description: >- + The ID of the parent object. For "Accounts" object, this + parameter is the account name that the Notes object is created + for. + createdAt: + type: string + format: time-date + description: The time and date when this Notes object is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the Notes object is updated. + comments: + type: array + description: The array of comments for this Notes object. + items: + $ref: '#/components/schemas/NotesComment' + NotesUser: + type: object + properties: + id: + type: integer + description: The ID of the Notes user. + username: + type: string + description: The user name. + connectIdentity: + type: string + description: The connect ID of the user. It must be a 32-digit hex number. + email: + type: string + description: The email address of the user. + firstName: + type: string + description: The first name. + lastName: + type: string + description: The last name. + fullName: + type: string + description: The full name of the user. + platformRole: + type: string + description: The Platform role of the user. + timeZone: + type: string + description: The time zone setting for the user. + createdAt: + type: string + format: time-date + description: The time and date when this user record is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the user record is updated. + escalationUser: + type: string + description: >- + The full name of the user that is configured to handle escalations + for the current user. + escalationUserId: + type: string + description: The ID of the escalation user. It must be a 32-digit hex number. + approvalAmount: + type: number + description: The amount of money that this user is allowed to approve. + avatar: + type: string + description: The link to the avatar image file for the user. + NotesReply: + type: object + properties: + id: + type: integer + description: The ID of the reply. + body: + type: string + description: The body of the reply. + image: + type: string + description: >- + The link to the image file. The value is null if no image files are + available. + attachment: + type: string + description: >- + The link to the attachment. The value is null if no attachments are + available. + createdAt: + type: string + format: time-date + description: The time and date when the reply is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the reply is updated. + user: + $ref: '#/components/schemas/NotesUser' + NotesComment: + type: object + properties: + id: + type: integer + description: The ID of the comment. + body: + type: string + description: The body of the comment. + image: + type: string + description: >- + The link to the image file. The value is null if no image files are + available. + attachment: + type: string + description: >- + The link to the attachment. The value is null if no attachments are + available. + createdAt: + type: string + format: time-date + description: The time and date when this comment is created. + updatedAt: + type: string + format: time-date + description: The last time and date when the comment is updated. + user: + description: The creator of the comment. + $ref: '#/components/schemas/NotesUser' + replies: + type: array + description: An array of replies. + items: + $ref: '#/components/schemas/NotesReply' + NotesTasksResponse: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful. + data: + type: object + description: The actual tasks data. + properties: + tasks: + type: array + items: + type: object + properties: + id: + type: integer + description: The ID of the task. + task: + type: string + description: The title of the task. + description: + type: string + description: Additional details about the task. + dueDate: + type: string + format: time-date + description: The due date and time of the task. + createdAt: + type: string + format: time-date + description: The date and time when this task is created. + updatedAt: + type: string + format: time-date + description: The last date and time when the task is updated. + reminderDate: + type: string + format: time-date + description: >- + The data and time when a reminder about this task needs to + be sent. + notifications: + type: string + description: >- + The message to be sent as notifications. It can be null if + no message is defined. + status: + type: string + description: The status of the task. + comment: + type: string + description: The comment about the task. + autoEscalation: + type: string + description: The automatic escalation setting for the task. + createdBy: + $ref: '#/components/schemas/NotesUser' + assignTo: + $ref: '#/components/schemas/NotesUser' + pagination: + type: object + properties: + page: + type: integer + description: The number of the current page. + per_page: + type: integer + description: The number of results on each page. + total_filtered_records: + type: integer + description: The total number of filtered records. + total_records: + type: integer + description: The total number of records. + NotesTasks: + type: object + properties: + id: + type: integer + description: The ID of the task. + task: + type: string + description: The title of the task. + description: + type: string + description: Additional details about the task. + dueDate: + type: string + format: time-date + description: The due date and time of the task. + createdAt: + type: string + format: time-date + description: The date and time when this task is created. + updatedAt: + type: string + format: time-date + description: The last date and time when the task is updated. + reminderDate: + type: string + format: time-date + description: The data and time when a reminder about this task needs to be sent. + notifications: + type: string + description: >- + The message to be sent as notifications. It can be null if no + message is defined. + status: + type: string + description: The status of the task. + comment: + type: string + description: The comment about the task. + autoEscalation: + type: string + description: The automatic escalation setting for the task. + createdBy: + $ref: '#/components/schemas/NotesUser' + assignTo: + $ref: '#/components/schemas/NotesUser' + NotesGroup: + type: object + properties: + id: + type: integer + description: The ID of the Notes group. + name: + type: string + description: The name of the group. + description: + type: string + description: Additional information about the group. + created_at: + type: string + format: time-date + description: The date and time when the group was created. + updated_at: + type: string + format: time-date + description: The last date and time when the group was updated. + users: + type: array + description: A list of all users in the group. + items: + $ref: '#/components/schemas/NotesUser' + NotesGroupsResponse: + type: object + properties: + success: + type: boolean + description: Whether this operation is successful. + groups: + type: array + items: + $ref: '#/components/schemas/NotesGroup' + NotesCreateGroupBody: + type: object + properties: + name: + type: string + description: The name of the group that you want to create. + description: + type: string + description: Additional information about the group. + NotesUpdateGroupBody: + type: object + properties: + name: + type: string + description: The new name of the group. + description: + type: string + description: The new description about the group. + NotesDeleteGroupBody: + type: object + properties: + name: + type: string + description: The name of the group that has been deleted. + description: + type: string + description: The description of the group. + NotesCreateGroupResponse: + type: object + properties: + success: + type: boolean + description: Whether the operation is successful. + id: + type: integer + description: The ID of the Notes group. + name: + type: string + description: The name of the group. + description: + type: string + description: Additional information about the group. + created_at: + type: string + format: time-date + description: The date and time when the group was created. + updated_at: + type: string + format: time-date + description: The last date and time when the group was updated. + users: + type: array + description: An array of users in the group. + items: + $ref: '#/components/schemas/NotesUser' + ResultsPagination: + type: object + description: The pagination information. + properties: + page: + type: integer + description: The current page. + page_length: + type: integer + description: The number of result on each page. + next_page: + type: string + description: The link to the next page of results. + CollectionAccount: + type: object + properties: + name: + type: string + description: The name of the account. + zuora_id: + type: string + description: The Zuora ID of the account. + in_collections: + type: boolean + description: Whether the account is in collections. + account_currency: + type: string + description: The currency that is currently used by the account. + home_currency: + type: string + description: The home currency of the tenant. + amount_due_account_currency: + type: number + description: The amount that is due for the account in the account currency. + amount_due_home_currency: + type: number + description: The amount that is due for the account in the tenant home currency. + last_open_invoice_date: + type: string + format: date + description: The last open invoice date. + average_debt_age: + type: number + description: The average age of all the debt of the account. + statuses: + $ref: '#/components/schemas/CollectionStatuses' + CollectionStatuses: + type: object + description: The status of the account. + properties: + In Collections: + type: boolean + description: Whether this account is in collections. + Pending: + type: boolean + description: Whether this account is pending. + In Dispute: + type: boolean + description: Whether this account is in dispute. + Paid In Full: + type: boolean + description: Whether this account has paid in full. + CollectionAgent: + type: object + properties: + name: + type: string + description: The name of the agent. + email: + type: string + description: The email of the agent. + zuora_identity_id: + type: string + description: The Zuora ID of the agent. + amount_in_collections: + type: number + description: The total amount of debt for accounts that are assigned to the user. + accounts: + type: integer + description: The number of accounts that are assigned to the user. + account_statuses: + type: object + properties: + In Collections: + type: integer + description: The number of accounts that are in collections. + Pending: + type: integer + description: The number of accounts that are pending. + In Disputes: + type: integer + description: The number of accounts that are in dispute. + Paid in Full: + type: integer + description: The number of accounts that have paid in full. + GETCollectionAgentsResponse: + type: object + properties: + accounts: + $ref: '#/components/schemas/CollectionAgent' + pagination: + $ref: '#/components/schemas/ResultsPagination' + GETCollectionAccountsResponse: + type: object + properties: + accounts: + type: array + description: The array of accounts. + items: + $ref: '#/components/schemas/CollectionAccount' + pagination: + $ref: '#/components/schemas/ResultsPagination' + CollectionsInfo: + type: object + properties: + accounts_in_collections: + type: integer + description: The number of accounts that are in collections. + home_currency: + type: string + description: The home currency of the tenant. + total_debt: + type: number + description: The total debt of all accounts that are in collections. + largest_debts: + type: array + description: The five largest debts that are in collections. + items: + type: string + description: An account number and the amount due for the account. + oldest_debts: + type: array + description: The five oldest debts that are in collections. + items: + type: string + description: An account number and the amount due for the account. + statuses: + type: object + properties: + In Collection: + type: integer + description: The number of accounts that are in collections. + Pending: + type: integer + description: The number of accounts that are in pending status. + In Dispute: + type: integer + description: The number of accounts that are in dispute. + Paid In Full: + type: integer + securitySchemes: + BasicAuth: + type: http + scheme: basic diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal index 71070c5d5..e1b67b7b6 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal @@ -29,12 +29,9 @@ annotation ClientMethodImpl MethodImpl on function; type ClientMethodInvocationError http:ClientError; -@display {label: "Zuora Collection", iconPath: "icon.png"} public isolated client class Client { final http:StatusCodeClient clientEp; # Gets invoked to initialize the `connector`. - # The connector initialization requires setting the API credentials. - # Create a [Zuora account](https://www.zuora.com/) and obtain tokens by following [this guide](https://www.zuora.com/developer/collect-api/#section/Authentication). # # + config - The configurations to be used when initializing the `connector` # + serviceUrl - URL of the target service @@ -59,6 +56,18 @@ public isolated client class Client { @MethodImpl {name: "UpdateAccountImpl"} resource isolated function post api/v1/accounts/[string account_id]/update_status(map headers = {}, typedesc targetType = <>, *UpdateAccountQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + # Execute payments + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "UpdateExecutePaymentsImpl"} + resource isolated function post api/v1/payments/execute_payments(payments_execute_payments_body payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Submit a payment to retry cycle + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "UpdateSubmitPaymentToCycleImpl"} + resource isolated function post api/v1/payments/submit_failed_payment(payments_submit_failed_payment_body payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + # Create an ad hoc statement run # # + headers - Headers to be sent with the request @@ -90,6 +99,18 @@ public isolated client class Client { @MethodImpl {name: "deletePaymentRunScheduleImpl"} resource isolated function delete api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + @MethodImpl {name: "executeExecuteAccountPaymentsImpl"} + resource isolated function put api/v1/payments/execute_account_payments/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "executeExecuteDebitMemoPaymentImpl"} + resource isolated function put api/v1/payments/execute_debit_memo_payment/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "executeExecuteInvoicePaymentImpl"} + resource isolated function put api/v1/payments/execute_invoice_payment/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "getAccountCycleHistoryImpl"} + resource isolated function get api/v1/payments/account_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + # Get an account # # + account_id - The account ID. @@ -103,6 +124,27 @@ public isolated client class Client { @MethodImpl {name: "getAccountsImpl"} resource isolated function get api/v1/accounts(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + @MethodImpl {name: "getActiveAccountCycleImpl"} + resource isolated function get api/v1/payments/active_account_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "getActiveDebitMemoCycleImpl"} + resource isolated function get api/v1/payments/active_debit_memo_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "getActiveInvoiceCycleImpl"} + resource isolated function get api/v1/payments/active_invoice_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get the Amount Recovered metrics + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getAmountRecoveredImpl"} + resource isolated function get api/v1/metrics/amount_recovered(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + # Get baseline metrics + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getBaselineMetricsImpl"} + resource isolated function get api/v1/metrics/baseline(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + # Get a collections agent by email # # + email - The email of the collections agent. @@ -122,6 +164,24 @@ public isolated client class Client { @MethodImpl {name: "getCollectionsInfoImpl"} resource isolated function get api/v1/collections_info(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + # Get the Customer Group metrics + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getCustomerGroupMetricsImpl"} + resource isolated function get api/v1/metrics/customer_group(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + @MethodImpl {name: "getDebitMemoCycleHistoryImpl"} + resource isolated function get api/v1/payments/debit_memo_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + # Get the Document Success Rate metrics by customer group + # + # + headers - Headers to be sent with the request + @MethodImpl {name: "getDocumentSuccessRateByCustomerGroupImpl"} + resource isolated function get api/v1/metrics/customer_group_over_time(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + + @MethodImpl {name: "getInvoiceCycleHistoryImpl"} + resource isolated function get api/v1/payments/invoice_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + # Get a payment run # # + payment_run_id - The payment run ID. A payment run id in Advanced Payment Manager is different from a payment run id in Zuora. @@ -148,6 +208,15 @@ public isolated client class Client { @MethodImpl {name: "getSettingsImpl"} resource isolated function get api/v1/fetch_settings(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + @MethodImpl {name: "removeAccountFromCycleImpl"} + resource isolated function put api/v1/payments/remove_account_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "removeDebitMemoFromCycleImpl"} + resource isolated function put api/v1/payments/remove_debit_memo_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + + @MethodImpl {name: "removeRemoveInoviceFromCycleImpl"} + resource isolated function put api/v1/payments/remove_invoice_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + # Update a payment run schedule # # + schedule_id - The schedule ID @@ -169,6 +238,20 @@ public isolated client class Client { }; } + private isolated function UpdateExecutePaymentsImpl(payments_execute_payments_body payload, map headers, typedesc targetType) returns OkInline_response_200_4|error { + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [100, 101, 110, 111, 121]"}, + headers: {} + }; + } + + private isolated function UpdateSubmitPaymentToCycleImpl(payments_submit_failed_payment_body payload, map headers, typedesc targetType) returns OkInline_response_200_8|error { + return { + body: {"success": true, "message": "Payment entered into retry process"}, + headers: {} + }; + } + private isolated function createAdhocStatementRunImpl(POSTAdhocStatementRun payload, map headers, typedesc targetType) returns OkPOSTAdhocStatementRunResponse|error { return { body: {"success": true, "code": 200, "message": "Success", "statement_number": "STA00000008"}, @@ -204,6 +287,34 @@ public isolated client class Client { }; } + private isolated function executeExecuteAccountPaymentsImpl(map headers, typedesc targetType) returns OkInline_response_200_3|error { + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [310, 311, 312]"}, + headers: {} + }; + } + + private isolated function executeExecuteDebitMemoPaymentImpl(map headers, typedesc targetType) returns OkInline_response_200_2|error { + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [300]"}, + headers: {} + }; + } + + private isolated function executeExecuteInvoicePaymentImpl(map headers, typedesc targetType) returns OkInline_response_200_1|error { + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [290, 291]"}, + headers: {} + }; + } + + private isolated function getAccountCycleHistoryImpl(map headers, typedesc targetType) returns OkGETAccountCycleHistoryResponse|error { + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 3, "next_attempt": "2021-03-19T18:53:39.641Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fb78532b0f01785a38cede190a", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-03-24T19:34:20.254Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51aae41969", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.316-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, + headers: {} + }; + } + private isolated function getAccountImpl(string account_id, map headers, typedesc targetType) returns OkCollectionAccount|error { return { body: {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}}, @@ -218,6 +329,41 @@ public isolated client class Client { }; } + private isolated function getActiveAccountCycleImpl(map headers, typedesc targetType) returns OkGETActiveAccountCycleResponse|error { + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "debit_memo_id": "2c92c0fb78532b0001785a38f6427976", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.473Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a5199a6192d", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:27.521-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0fa7853052701785a38c6622473", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.436Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a519d85193b", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:28.161-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, + headers: {} + }; + } + + private isolated function getActiveDebitMemoCycleImpl(map headers, typedesc targetType) returns OkGETActiveDebitMemoCycleResponse|error { + return { + body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T10:22:57.464Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000380", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T10:22:57.464-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, + headers: {} + }; + } + + private isolated function getActiveInvoiceCycleImpl(map headers, typedesc targetType) returns OkGETActiveInvoiceCycleResponse|error { + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0f8778bf8cd017798168cb50e0b", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T19:27:34.648Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ca076c21", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T19:27:34.648-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bce0d0a06d5", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:53:39.845-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, + headers: {} + }; + } + + private isolated function getAmountRecoveredImpl(map headers, typedesc targetType) returns OkGETAmountRecoveredResponse|error { + return { + body: {"currency": {"USD": {"total_amount": "77515.21", "last_30_days": "1100.01"}, "EUR": {"total_amount": "337.19", "last_30_days": "17.17"}, "CAD": {"total_amount": "123954.10", "last_30_days": "5132.87"}}, "success": true}, + headers: {} + }; + } + + private isolated function getBaselineMetricsImpl(map headers, typedesc targetType) returns OkGETBaselineMetricsResponse|error { + return { + body: {"retry_success_rate": "11.90", "retry_success_rate_trend": "down", "document_success_rate": "13.54", "document_success_rate_trend": "neutral", "average_days_outstanding": "4.76", "average_days_outstanding_trend": "up", "success": true}, + headers: {} + }; + } + private isolated function getCollectionsAgentImpl(string email, map headers, typedesc targetType) returns OkCollectionAgent|error { return { body: {"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}, @@ -239,6 +385,34 @@ public isolated client class Client { }; } + private isolated function getCustomerGroupMetricsImpl(map headers, typedesc targetType) returns OkGETCustomerGroupMetricsResponse|error { + return { + body: {"customer_groups": [{"id": 1, "name": "batch22", "smart_retry": false, "document_success_rate": "17.17", "document_success_rate_trend": "up", "retry_success_rate": "21.76", "average_attempts": "4.11"}, {"id": 2, "name": "Smart Retry", "smart_retry": true, "document_success_rate": "74.17", "document_success_rate_trend": "down", "retry_success_rate": "81.21", "average_attempts": "1.32"}, {"id": 4, "name": "All Remaining Customers", "smart_retry": false, "document_success_rate": "16.35", "document_success_rate_trend": "up", "retry_success_rate": "15.21", "average_attempts": "3.32"}], "success": true}, + headers: {} + }; + } + + private isolated function getDebitMemoCycleHistoryImpl(map headers, typedesc targetType) returns OkGETDebitMemoCycleHistoryResponse|error { + return { + body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time", "api_updated_retry_time": "2021-03-26T14:27:21.107-04:00"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000378", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, + headers: {} + }; + } + + private isolated function getDocumentSuccessRateByCustomerGroupImpl(map headers, typedesc targetType) returns OkGETDocumentSuccessRateByCustomerGroupResponse|error { + return { + body: {"customer_groups": {"1": {"05_21": "17.53", "04_21": "13.21", "03_21": "14.92", "02_21": "8.99", "01_21": "34.25", "12_20": "12.30"}, "2": {"05_21": "11.11", "04_21": "7.87", "03_21": "26.00", "02_21": "11.06", "01_21": "13.43", "12_20": "17.92"}, "4": {"05_21": "11.13", "04_21": "9.17", "03_21": "17.20", "02_21": "19.06", "01_21": "12.43", "12_20": "15.92"}}, "success": true}, + headers: {} + }; + } + + private isolated function getInvoiceCycleHistoryImpl(map headers, typedesc targetType) returns OkGETInvoiceCycleHistoryResponse|error { + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 1, "next_attempt": null, "customer_group": "Testing Group", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-04-01T19:11:21.639Z", "source": "PR-00000370", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 5}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, + headers: {} + }; + } + private isolated function getPaymentRunImpl(int payment_run_id, map headers, typedesc targetType) returns OkGETPaymentRunResponse|error { return { body: {"success": true, "id": 6, "status": "Complete", "target_date": "2018-01-02T00:00:00.000Z", "filter": "Account.Currency = 'CAD'", "payment_run_schedule_id": "Adhoc", "invoices_held": {}, "metrics": {"documents": 0, "payments": 0, "failed": 0, "skipped": 0, "amount": 0, "credit": 0}}, @@ -267,6 +441,27 @@ public isolated client class Client { }; } + private isolated function removeAccountFromCycleImpl(map headers, typedesc targetType) returns OkInline_response_200_7|error { + return { + body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [310, 311, 312]"}, + headers: {} + }; + } + + private isolated function removeDebitMemoFromCycleImpl(map headers, typedesc targetType) returns OkInline_response_200_6|error { + return { + body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [301]"}, + headers: {} + }; + } + + private isolated function removeRemoveInoviceFromCycleImpl(map headers, typedesc targetType) returns OkInline_response_200_5|error { + return { + body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [290, 291]"}, + headers: {} + }; + } + private isolated function updatePaymentRunScheduleImpl(int schedule_id, PUTPaymentRunSchedule payload, map headers, typedesc targetType) returns OkPOSTPaymentRunScheduleResponse|error { return { body: {"id": 6, "success": true}, diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal index db6461540..29a607577 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal @@ -1,11 +1,8 @@ import ballerina/http; -@display {label: "Zuora Collection", iconPath: "icon.png"} public isolated client class Client { final http:Client clientEp; # Gets invoked to initialize the `connector`. - # The connector initialization requires setting the API credentials. - # Create a [Zuora account](https://www.zuora.com/) and obtain tokens by following [this guide](https://www.zuora.com/developer/collect-api/#section/Authentication). # # + config - The configurations to be used when initializing the `connector` # + serviceUrl - URL of the target service @@ -32,6 +29,20 @@ public isolated client class Client { return {"success": true}; } + # Execute payments + # + # + headers - Headers to be sent with the request + remote isolated function UpdateExecutePayments(payments_execute_payments_body payload, map headers = {}) returns inline_response_200_4|error { + return {"success": true, "message": "Payments with the following IDs enqueued for processing: [100, 101, 110, 111, 121]"}; + } + + # Submit a payment to retry cycle + # + # + headers - Headers to be sent with the request + remote isolated function UpdateSubmitPaymentToCycle(payments_submit_failed_payment_body payload, map headers = {}) returns inline_response_200_8|error { + return {"success": true, "message": "Payment entered into retry process"}; + } + # Create an ad hoc statement run # # + headers - Headers to be sent with the request @@ -68,6 +79,30 @@ public isolated client class Client { return {"success": true}; } + # Execute account payments + # + # + account_id - ID of an account. + # + headers - Headers to be sent with the request + remote isolated function executeExecuteAccountPayments(string account_id, map headers = {}) returns inline_response_200_3|error { + return {"success": true, "message": "Payments with the following IDs enqueued for processing: [310, 311, 312]"}; + } + + # Execute debit memo payment + # + # + debit_memo_id - ID of a debit memo. + # + headers - Headers to be sent with the request + remote isolated function executeExecuteDebitMemoPayment(string debit_memo_id, map headers = {}) returns inline_response_200_2|error { + return {"success": true, "message": "Payments with the following IDs enqueued for processing: [300]"}; + } + + # Execute invoice payment + # + # + invoice_id - ID of an invoice. + # + headers - Headers to be sent with the request + remote isolated function executeExecuteInvoicePayment(string invoice_id, map headers = {}) returns inline_response_200_1|error { + return {"success": true, "message": "Payments with the following IDs enqueued for processing: [290, 291]"}; + } + # Get an account # # + account_id - The account ID. @@ -76,6 +111,14 @@ public isolated client class Client { return {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}}; } + # Get retry cycle history for an account + # + # + account_id - ID of an account. + # + headers - Headers to be sent with the request + remote isolated function getAccountCycleHistory(string account_id, map headers = {}) returns GETAccountCycleHistoryResponse|error { + return {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 3, "next_attempt": "2021-03-19T18:53:39.641Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fb78532b0f01785a38cede190a", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-03-24T19:34:20.254Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51aae41969", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.316-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}; + } + # Get all accounts # # + headers - Headers to be sent with the request @@ -83,6 +126,44 @@ public isolated client class Client { return {"accounts": [{"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": 0, "Pending": 0, "In Dispute": 0, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20"}}; } + # Get active retry cycles for an account + # + # + account_id - ID of an account. + # + headers - Headers to be sent with the request + remote isolated function getActiveAccountCycle(string account_id, map headers = {}) returns GETActiveAccountCycleResponse|error { + return {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "debit_memo_id": "2c92c0fb78532b0001785a38f6427976", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.473Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a5199a6192d", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:27.521-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0fa7853052701785a38c6622473", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.436Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a519d85193b", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:28.161-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}; + } + + # Get active retry cycles for a debit memo + # + # + debit_memo_id - ID of a debit memo. + # + headers - Headers to be sent with the request + remote isolated function getActiveDebitMemoCycle(string debit_memo_id, map headers = {}) returns GETActiveDebitMemoCycleResponse|error { + return {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T10:22:57.464Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000380", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T10:22:57.464-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}; + } + + # Get active retry cycles for an invoice + # + # + invoice_id - ID of an invoice. + # + headers - Headers to be sent with the request + remote isolated function getActiveInvoiceCycle(string invoice_id, map headers = {}) returns GETActiveInvoiceCycleResponse|error { + return {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0f8778bf8cd017798168cb50e0b", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T19:27:34.648Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ca076c21", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T19:27:34.648-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bce0d0a06d5", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:53:39.845-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}; + } + + # Get the Amount Recovered metrics + # + # + headers - Headers to be sent with the request + remote isolated function getAmountRecovered(map headers = {}) returns GETAmountRecoveredResponse|error { + return {"currency": {"USD": {"total_amount": "77515.21", "last_30_days": "1100.01"}, "EUR": {"total_amount": "337.19", "last_30_days": "17.17"}, "CAD": {"total_amount": "123954.10", "last_30_days": "5132.87"}}, "success": true}; + } + + # Get baseline metrics + # + # + headers - Headers to be sent with the request + remote isolated function getBaselineMetrics(map headers = {}) returns GETBaselineMetricsResponse|error { + return {"retry_success_rate": "11.90", "retry_success_rate_trend": "down", "document_success_rate": "13.54", "document_success_rate_trend": "neutral", "average_days_outstanding": "4.76", "average_days_outstanding_trend": "up", "success": true}; + } + # Get a collections agent by email # # + email - The email of the collections agent. @@ -105,6 +186,36 @@ public isolated client class Client { return {"accounts_in_collections": 24, "home_currency": "USD", "total_debt": "8379.78", "largest_debts": ["Test Account - 12438.00 USD", "Jimmy John - 8000.00 USD", "James Smith - 2450.55 USD", "Bob Roberts - 1000.00 USD", "Jim Reynolds - 829.00 USD"], "oldest_debts": ["Test Account - 2662 days", "Jimbo - 1494 days", "Steve Smith - 942 days", "Jason Williams - 678 days", "Will Jasons - 365 days"], "statuses": {"In Collections": 24, "Pending": 2, "In Dispute": 5, "Paid in Full": 0}}; } + # Get the Customer Group metrics + # + # + headers - Headers to be sent with the request + remote isolated function getCustomerGroupMetrics(map headers = {}) returns GETCustomerGroupMetricsResponse|error { + return {"customer_groups": [{"id": 1, "name": "batch22", "smart_retry": false, "document_success_rate": "17.17", "document_success_rate_trend": "up", "retry_success_rate": "21.76", "average_attempts": "4.11"}, {"id": 2, "name": "Smart Retry", "smart_retry": true, "document_success_rate": "74.17", "document_success_rate_trend": "down", "retry_success_rate": "81.21", "average_attempts": "1.32"}, {"id": 4, "name": "All Remaining Customers", "smart_retry": false, "document_success_rate": "16.35", "document_success_rate_trend": "up", "retry_success_rate": "15.21", "average_attempts": "3.32"}], "success": true}; + } + + # Get retry cycle history for a debit memo + # + # + debit_memo_id - ID of a debit memo. + # + headers - Headers to be sent with the request + remote isolated function getDebitMemoCycleHistory(string debit_memo_id, map headers = {}) returns GETDebitMemoCycleHistoryResponse|error { + return {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time", "api_updated_retry_time": "2021-03-26T14:27:21.107-04:00"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000378", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}; + } + + # Get the Document Success Rate metrics by customer group + # + # + headers - Headers to be sent with the request + remote isolated function getDocumentSuccessRateByCustomerGroup(map headers = {}) returns GETDocumentSuccessRateByCustomerGroupResponse|error { + return {"customer_groups": {"1": {"05_21": "17.53", "04_21": "13.21", "03_21": "14.92", "02_21": "8.99", "01_21": "34.25", "12_20": "12.30"}, "2": {"05_21": "11.11", "04_21": "7.87", "03_21": "26.00", "02_21": "11.06", "01_21": "13.43", "12_20": "17.92"}, "4": {"05_21": "11.13", "04_21": "9.17", "03_21": "17.20", "02_21": "19.06", "01_21": "12.43", "12_20": "15.92"}}, "success": true}; + } + + # Get retry cycle history for an invoice + # + # + invoice_id - ID of an invoice. + # + headers - Headers to be sent with the request + remote isolated function getInvoiceCycleHistory(string invoice_id, map headers = {}) returns GETInvoiceCycleHistoryResponse|error { + return {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 1, "next_attempt": null, "customer_group": "Testing Group", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-04-01T19:11:21.639Z", "source": "PR-00000370", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 5}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}; + } + # Get a payment run # # + payment_run_id - The payment run ID. A payment run id in Advanced Payment Manager is different from a payment run id in Zuora. @@ -135,6 +246,30 @@ public isolated client class Client { return {"success": true, "templates": [{"name": "Default Template"}, {"name": "Template for end consumers"}], "default_template": "Default Template", "default_cycle": "Month"}; } + # Remove an account from retry cycle + # + # + account_id - ID of an account. + # + headers - Headers to be sent with the request + remote isolated function removeAccountFromCycle(string account_id, map headers = {}) returns inline_response_200_7|error { + return {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [310, 311, 312]"}; + } + + # Remove a debit memo from retry cycle + # + # + debit_memo_id - ID of a debit memo. + # + headers - Headers to be sent with the request + remote isolated function removeDebitMemoFromCycle(string debit_memo_id, map headers = {}) returns inline_response_200_6|error { + return {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [301]"}; + } + + # Remove an invoice from retry cycle + # + # + invoice_id - ID of an invoice. + # + headers - Headers to be sent with the request + remote isolated function removeRemoveInoviceFromCycle(string invoice_id, map headers = {}) returns inline_response_200_5|error { + return {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [290, 291]"}; + } + # Update a payment run schedule # # + schedule_id - The schedule ID diff --git a/openapi-core/build.gradle b/openapi-core/build.gradle index 53074bbcb..cd5731a71 100644 --- a/openapi-core/build.gradle +++ b/openapi-core/build.gradle @@ -32,6 +32,7 @@ configurations { dependencies { implementation project(':ballerina-to-openapi') + implementation "com.fasterxml.jackson.core:jackson-databind" implementation ("io.swagger.parser.v3:swagger-parser:${swaggerParserVersion}") { exclude group: "io.swagger", module: "swagger-compat-spec-parser" exclude group: "org.slf4j", module: "slf4j-ext" diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java index 0512915d8..46cf3d8c7 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java @@ -65,7 +65,8 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; /** - * This class iss contain the advance client generation when the client generation enable with status code bindings. + * This class contains the advance client generation when the client generation enables with status code bindings. + * * @since 2.1.0 */ public class AdvanceMockClientGenerator extends BallerinaClientGeneratorWithStatusCodeBinding { @@ -102,22 +103,6 @@ protected List getModuleMemberDeclarationNodes() th return nodes; } - @Override - protected void addClientFunctionImpl(Map.Entry> operation, - Map.Entry operationEntry, - List clientFunctionNodes) { - FunctionDefinitionNode clientExternFunction = clientFunctionNodes.get(clientFunctionNodes.size() - 1); - Optional implFunction = createImplFunction(operation.getKey(), operationEntry, openAPI, - authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction, oasClientConfig.isMock()); - if (implFunction.isPresent()) { - clientFunctionNodes.add(implFunction.get()); - } else { - diagnostics.add(new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_112, - operationEntry.getValue().getOperationId())); - clientFunctionNodes.remove(clientFunctionNodes.size() - 1); - } - } - /** * This method for generate the client syntax tree. * @@ -127,13 +112,9 @@ protected void addClientFunctionImpl(Map.Entry importForHttp = getImportDeclarationNodes(); imports.addAll(importForHttp); - - // Add authentication related records authConfigGeneratorImp.addAuthRelatedRecords(openAPI); - List nodes = getModuleMemberDeclarationNodes(); NodeList importsList = createNodeList(imports); ModulePartNode modulePartNode = @@ -141,7 +122,6 @@ public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientE TextDocument textDocument = TextDocuments.from(""); SyntaxTree syntaxTree = SyntaxTree.from(textDocument); syntaxTree = syntaxTree.modifyWith(modulePartNode); - //Add comments ClientDocCommentGenerator clientDocCommentGenerator = new ClientDocCommentGenerator(syntaxTree, openAPI, oasClientConfig.isResourceMode()); return clientDocCommentGenerator.updateSyntaxTreeWithDocComments(); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java index 69db8774a..68394f31a 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java @@ -298,7 +298,7 @@ protected Map> filterOperations() { } /** - * This includes the filtering logic. + * This includes the filtering logic for OAS operations. */ private boolean shouldFilterOperation(List filterTags, List filterOperations, List operationTags, String operationId) { diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java index a512d3a97..5bfbc9f18 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java @@ -174,7 +174,7 @@ protected QualifiedNameReferenceNode getHttpClientTypeName() { createIdentifierToken(GeneratorConstants.STATUS_CODE_CLIENT)); } - protected void addClientFunctionImpl(Map.Entry> operation, + private void addClientFunctionImpl(Map.Entry> operation, Map.Entry operationEntry, List clientFunctionNodes) { FunctionDefinitionNode clientExternFunction = clientFunctionNodes.get(clientFunctionNodes.size() - 1); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java index b433671c6..be7130fb8 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java @@ -70,7 +70,7 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN; /** - * This generator class for generate the mock clients. + * This generator class is for generate the mock clients. * * @since 2.1.0 */ @@ -79,7 +79,6 @@ public BallerinaMockClientGenerator(OASClientConfig oasClientConfig) { super(oasClientConfig); } - //override init function generation public FunctionDefinitionNode getInitFunction() { FunctionSignatureNode functionSignatureNode = super.getInitFunctionSignatureNode(); NodeList qualifierList = createNodeList(createToken(PUBLIC_KEYWORD), createToken(ISOLATED_KEYWORD)); @@ -96,7 +95,6 @@ public FunctionDefinitionNode getInitFunction() { functionBodyNode); } - //override client function generation public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException { List memberNodeList = new ArrayList<>(); memberNodeList.addAll(createClassInstanceVariables()); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java index 701958a2b..61f2c1cd6 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java @@ -59,7 +59,10 @@ public enum DiagnosticMessages { OAS_CLIENT_115("OAS_CLIENT_115", "the 'default' response for the operation: '%s' is skipped in the client " + "generation, since it is not supported with status code binding option", DiagnosticSeverity.WARNING), OAS_CLIENT_116("OAS_CLIENT_116", "the operation for given path `%s` , method `%s` is skipped in " + - "the mock client function generation since it is not provided with examples", DiagnosticSeverity.WARNING); + "the mock client function generation since it is not provided with examples", DiagnosticSeverity.WARNING), + + OAS_CLIENT_117("OAS_CLIENT_117", "the operation for given path `%s` , method `%s` is skipped in " + + "the mock client function generation since it has invalid reference", DiagnosticSeverity.WARNING); private final String code; private final String description; private final DiagnosticSeverity severity; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java index 5af0089ab..4ec835062 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java @@ -59,6 +59,7 @@ /** * Mock client function generator. + * * @since 2.1.0 */ public class MockClientFunctionGenerator implements FunctionGenerator { diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java index 39fb0d893..701c230cc 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java @@ -34,6 +34,7 @@ import io.swagger.v3.oas.models.PathItem; import io.swagger.v3.oas.models.examples.Example; import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; @@ -48,6 +49,7 @@ import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode; import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN; import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.RESPONSE; /** * Mock function body generator. @@ -73,7 +75,6 @@ public MockFunctionBodyGenerator(String path, Map.Entry getFunctionBodyNode() { - //Check inline example ApiResponses responses = operation.getValue().getResponses(); //Get the successful response ApiResponse successResponse = null; @@ -83,20 +84,31 @@ public Optional getFunctionBodyNode() { break; } } - // Here only consider 2xx response + // Here only consider 2xx response, since this range consider for success status code if (successResponse == null || successResponse.getContent() == null) { return Optional.empty(); } - // Get the example Map examples = new HashMap<>(); for (Map.Entry mediaType : successResponse.getContent().entrySet()) { - // handle reference - if (mediaType.getValue().getExamples() != null) { - examples = mediaType.getValue().getExamples(); - } - if (mediaType.getValue().getExample() != null) { - Example example = (Example) mediaType.getValue().getExample(); - examples.put("response", example); + MediaType value = mediaType.getValue(); + Schema schema = value.getSchema(); + + if (value.getExamples() != null) { + examples = value.getExamples(); + } else if (value.getExample() != null) { + Object exampleObject = value.getExample(); + Example example = new Example(); + example.setValue(exampleObject); + examples.put(RESPONSE, example); + } else { + try { + examples = getExamplesFromSchema(schema); + } catch (InvalidReferenceException e) { + ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_117, + path, operation.getKey().toString()); + diagnostics.add(diagnosticImp); + return Optional.empty(); + } } } @@ -107,9 +119,8 @@ public Optional getFunctionBodyNode() { return Optional.empty(); } - Example example = examples.get("response"); + Example example = examples.get(RESPONSE); if (example == null) { - //when the example has key value which is not capture via response example = examples.values().iterator().next(); } @@ -140,6 +151,30 @@ public Optional getFunctionBodyNode() { return Optional.of(fBodyBlock); } + private Map getExamplesFromSchema(Schema schema) throws InvalidReferenceException { + Map examples = new HashMap<>(); + if (schema.getExample() != null) { + Object exampleObject = schema.getExample(); + Example example = new Example(); + example.setValue(exampleObject); + examples.put(RESPONSE, example); + } else if (schema.getExamples() != null) { + List schemaExamples = schema.getExamples(); + Object exampleObject = schemaExamples.get(0); + Example example = new Example(); + example.setValue(exampleObject); + examples.put(RESPONSE, example); + } else if (schema.get$ref() != null) { + String ref = schema.get$ref(); + String refName = GeneratorUtils.extractReferenceType(ref); + schema = openAPI.getComponents().getSchemas().get(refName); + if (schema != null) { + return getExamplesFromSchema(schema); + } + } + return examples; + } + @Override public List getDiagnostics() { return diagnostics; diff --git a/openapi-core/src/main/java/module-info.java b/openapi-core/src/main/java/module-info.java index ccc136505..322fdfe99 100644 --- a/openapi-core/src/main/java/module-info.java +++ b/openapi-core/src/main/java/module-info.java @@ -37,8 +37,8 @@ requires swagger.parser.core; requires swagger.parser.v3; requires org.apache.commons.lang3; + requires com.fasterxml.jackson.databind; -// exports io.ballerina.openapi.core.generators.service; exports io.ballerina.openapi.core.generators.common.model; exports io.ballerina.openapi.core.generators.common.exception; exports io.ballerina.openapi.core.generators.client.model; From ab113a619e41fa7be5a4f7e0f66899192949524d Mon Sep 17 00:00:00 2001 From: lnash94 Date: Wed, 29 May 2024 14:44:14 +0530 Subject: [PATCH 08/15] Add `add` command implementation for mock client --- .../src/main/java/io/ballerina/openapi/cmd/Add.java | 8 +++++++- .../java/io/ballerina/openapi/cmd/CmdOptions.java | 11 +++++++++++ .../java/io/ballerina/openapi/cmd/OpenApiCmd.java | 11 +++++++++-- .../generators/client/AdvanceMockClientGenerator.java | 6 ------ 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/Add.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/Add.java index 9b935c15b..b9753689f 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/Add.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/Add.java @@ -181,7 +181,9 @@ private CmdOptions collectCLIOptions() { .withOperations(getOperations()) .withTags(getTags()) .withLicensePath(baseCmd.licenseFilePath) - .withStatusCodeBinding(baseCmd.statusCodeBinding).build(); + .withStatusCodeBinding(baseCmd.statusCodeBinding) + .withMock(baseCmd.mock) + .build(); } /** @@ -252,6 +254,10 @@ private NodeList populateOpenAPITomlConfig(CmdOpt moduleMembers = moduleMembers.add(SampleNodeGenerator.createBooleanKV("options.statusCodeBinding", optionsBuilder.getStatusCodeBinding(), null)); } + if (optionsBuilder.getMock()) { + moduleMembers = moduleMembers.add(SampleNodeGenerator.createBooleanKV("options.mock", + optionsBuilder.getMock(), null)); + } moduleMembers = CmdUtils.addNewLine(moduleMembers, 2); return moduleMembers; } diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/CmdOptions.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/CmdOptions.java index 5c56e0313..14c8380ae 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/CmdOptions.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/CmdOptions.java @@ -35,6 +35,7 @@ public class CmdOptions { private final boolean nullable; private final String licensePath; private boolean statusCodeBinding; + private boolean mock; private CmdOptions(CmdOptionsBuilder builder) { this.input = builder.input; @@ -48,6 +49,7 @@ private CmdOptions(CmdOptionsBuilder builder) { this.nullable = builder.nullable; this.licensePath = builder.licensePath; this.statusCodeBinding = builder.statusCodeBinding; + this.mock = builder.mock; } public String getInput() { @@ -95,6 +97,10 @@ public boolean getStatusCodeBinding() { return statusCodeBinding; } + public boolean getMock() { + return mock; + } + /** * CMD options builder class. */ @@ -110,6 +116,7 @@ public static class CmdOptionsBuilder { private String input; private String licensePath; private boolean statusCodeBinding; + private boolean mock; public CmdOptionsBuilder withOutputModule(String outputModule) { this.outputModule = outputModule; @@ -166,6 +173,10 @@ public CmdOptionsBuilder withStatusCodeBinding(boolean statusCodeBinding) { return this; } + public CmdOptionsBuilder withMock(boolean mock) { + this.mock = mock; + return this; + } public CmdOptions build() { return new CmdOptions(this); } diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java index e97c79c64..56422a31f 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/OpenApiCmd.java @@ -430,8 +430,15 @@ private void generateServiceFile(BallerinaCodeGenerator generator, String servic try { assert resourcePath != null; - generator.generateService(resourcePath.toString(), serviceName, targetOutputPath.toString(), filter, - baseCmd.nullable, generateServiceType, generateWithoutDataBinding); + if (baseCmd.mock) { + //Brining some format for info message from ballerina info ex: `ballerina: ` + outStream.println("openapi: Mock server generation is currently not supported via the ballerina " + + "openapi tool."); + exitError(this.exitWhenFinish); + } else { + generator.generateService(resourcePath.toString(), serviceName, targetOutputPath.toString(), filter, + baseCmd.nullable, generateServiceType, generateWithoutDataBinding); + } } catch (IOException | FormatterException | BallerinaOpenApiException e) { outStream.println("Error occurred when generating service for openAPI contract at " + baseCmd.inputPath + "." + e.getMessage() + "."); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java index 46cf3d8c7..f76942ab2 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java @@ -30,21 +30,15 @@ import io.ballerina.compiler.syntax.tree.StatementNode; import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.Token; -import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp; -import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages; import io.ballerina.openapi.core.generators.client.exception.ClientException; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; import io.ballerina.openapi.core.generators.document.ClientDocCommentGenerator; import io.ballerina.tools.text.TextDocument; import io.ballerina.tools.text.TextDocuments; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Optional; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; From f9dea0d0c06b9dbf06ece00601a42b64c6ba7694 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Thu, 30 May 2024 11:29:09 +0530 Subject: [PATCH 09/15] Fix conflicts --- module-ballerina-openapi/Ballerina.toml | 6 +- module-ballerina-openapi/CompilerPlugin.toml | 4 +- .../mock_client_for_advance_return_type.bal | 140 +++++++++--------- .../client/FunctionSignatureGenerator.java | 3 +- .../mock/MockClientFunctionGenerator.java | 22 ++- 5 files changed, 93 insertions(+), 82 deletions(-) diff --git a/module-ballerina-openapi/Ballerina.toml b/module-ballerina-openapi/Ballerina.toml index 3f7db9168..49e3f3887 100644 --- a/module-ballerina-openapi/Ballerina.toml +++ b/module-ballerina-openapi/Ballerina.toml @@ -1,10 +1,10 @@ [package] org= "ballerina" name= "openapi" -version= "1.9.0" +version= "@toml.version@" [[platform.java17.dependency]] -path = "../openapi-validator/build/libs/openapi-validator-1.9.0-SNAPSHOT.jar" +path = "../openapi-validator/build/libs/openapi-validator-@project.version@.jar" groupId = "ballerina" artifactId = "openapi" -version = "1.9.0-SNAPSHOT" +version = "@project.version@" diff --git a/module-ballerina-openapi/CompilerPlugin.toml b/module-ballerina-openapi/CompilerPlugin.toml index 0e743c2c6..c4c4205c0 100644 --- a/module-ballerina-openapi/CompilerPlugin.toml +++ b/module-ballerina-openapi/CompilerPlugin.toml @@ -3,7 +3,7 @@ id = "openapi-tools" class = "io.ballerina.openapi.validator.OpenAPIValidatorPlugin" [[dependency]] -path = "../openapi-validator/build/libs/openapi-validator-1.9.0-SNAPSHOT.jar" +path = "../openapi-validator/build/libs/openapi-validator-@project.version@.jar" groupId = "ballerina" artifactId = "openapi" -version = "1.9.0-SNAPSHOT" +version = "@project.version@." diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal index e1b67b7b6..8b8b1394e 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal @@ -46,7 +46,7 @@ public isolated client class Client { # + headers - Headers to be sent with the request # + queries - Queries to be sent with the request @MethodImpl {name: "UpdateAccountAgentImpl"} - resource isolated function post api/v1/accounts/[string account_id]/update_agent(map headers = {}, typedesc targetType = <>, *UpdateAccountAgentQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function post api/v1/accounts/[string account_id]/update_agent(map headers = {}, typedesc targetType = <>, *UpdateAccountAgentQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Update account status # @@ -54,415 +54,415 @@ public isolated client class Client { # + headers - Headers to be sent with the request # + queries - Queries to be sent with the request @MethodImpl {name: "UpdateAccountImpl"} - resource isolated function post api/v1/accounts/[string account_id]/update_status(map headers = {}, typedesc targetType = <>, *UpdateAccountQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function post api/v1/accounts/[string account_id]/update_status(map headers = {}, typedesc targetType = <>, *UpdateAccountQueries queries) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Execute payments # # + headers - Headers to be sent with the request @MethodImpl {name: "UpdateExecutePaymentsImpl"} - resource isolated function post api/v1/payments/execute_payments(payments_execute_payments_body payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post api/v1/payments/execute_payments(payments_execute_payments_body payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Submit a payment to retry cycle # # + headers - Headers to be sent with the request @MethodImpl {name: "UpdateSubmitPaymentToCycleImpl"} - resource isolated function post api/v1/payments/submit_failed_payment(payments_submit_failed_payment_body payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post api/v1/payments/submit_failed_payment(payments_submit_failed_payment_body payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Create an ad hoc statement run # # + headers - Headers to be sent with the request @MethodImpl {name: "createAdhocStatementRunImpl"} - resource isolated function post api/v1/run(POSTAdhocStatementRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post api/v1/run(POSTAdhocStatementRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Create a custom statement run # # + headers - Headers to be sent with the request @MethodImpl {name: "createCustomStatementRunImpl"} - resource isolated function post api/v1/execute(POSTCustomStatementRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post api/v1/execute(POSTCustomStatementRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Create a payment run # # + headers - Headers to be sent with the request @MethodImpl {name: "createPaymentRunImpl"} - resource isolated function post api/v1/subscription_payment_runs(POSTPaymentRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post api/v1/subscription_payment_runs(POSTPaymentRun payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Create a payment run schedule # # + headers - Headers to be sent with the request @MethodImpl {name: "createPaymentRunScheduleImpl"} - resource isolated function post api/v1/payment_run_schedules(POSTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function post api/v1/payment_run_schedules(POSTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Cancel a payment run schedule # # + schedule_id - The schedule ID # + headers - Headers to be sent with the request @MethodImpl {name: "deletePaymentRunScheduleImpl"} - resource isolated function delete api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function delete api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "executeExecuteAccountPaymentsImpl"} - resource isolated function put api/v1/payments/execute_account_payments/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payments/execute_account_payments/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "executeExecuteDebitMemoPaymentImpl"} - resource isolated function put api/v1/payments/execute_debit_memo_payment/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payments/execute_debit_memo_payment/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "executeExecuteInvoicePaymentImpl"} - resource isolated function put api/v1/payments/execute_invoice_payment/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payments/execute_invoice_payment/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "getAccountCycleHistoryImpl"} - resource isolated function get api/v1/payments/account_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payments/account_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get an account # # + account_id - The account ID. # + headers - Headers to be sent with the request @MethodImpl {name: "getAccountImpl"} - resource isolated function get api/v1/accounts/[string account_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/accounts/[string account_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get all accounts # # + headers - Headers to be sent with the request @MethodImpl {name: "getAccountsImpl"} - resource isolated function get api/v1/accounts(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/accounts(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; @MethodImpl {name: "getActiveAccountCycleImpl"} - resource isolated function get api/v1/payments/active_account_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payments/active_account_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "getActiveDebitMemoCycleImpl"} - resource isolated function get api/v1/payments/active_debit_memo_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payments/active_debit_memo_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "getActiveInvoiceCycleImpl"} - resource isolated function get api/v1/payments/active_invoice_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payments/active_invoice_cycle_information/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get the Amount Recovered metrics # # + headers - Headers to be sent with the request @MethodImpl {name: "getAmountRecoveredImpl"} - resource isolated function get api/v1/metrics/amount_recovered(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/metrics/amount_recovered(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Get baseline metrics # # + headers - Headers to be sent with the request @MethodImpl {name: "getBaselineMetricsImpl"} - resource isolated function get api/v1/metrics/baseline(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/metrics/baseline(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Get a collections agent by email # # + email - The email of the collections agent. # + headers - Headers to be sent with the request @MethodImpl {name: "getCollectionsAgentImpl"} - resource isolated function get api/v1/users/[string email](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/users/[string email](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get all collections agents # # + headers - Headers to be sent with the request @MethodImpl {name: "getCollectionsAgentsImpl"} - resource isolated function get api/v1/users(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/users(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Get an overview of collections # # + headers - Headers to be sent with the request @MethodImpl {name: "getCollectionsInfoImpl"} - resource isolated function get api/v1/collections_info(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/collections_info(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Get the Customer Group metrics # # + headers - Headers to be sent with the request @MethodImpl {name: "getCustomerGroupMetricsImpl"} - resource isolated function get api/v1/metrics/customer_group(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/metrics/customer_group(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; @MethodImpl {name: "getDebitMemoCycleHistoryImpl"} - resource isolated function get api/v1/payments/debit_memo_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payments/debit_memo_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get the Document Success Rate metrics by customer group # # + headers - Headers to be sent with the request @MethodImpl {name: "getDocumentSuccessRateByCustomerGroupImpl"} - resource isolated function get api/v1/metrics/customer_group_over_time(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/metrics/customer_group_over_time(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; @MethodImpl {name: "getInvoiceCycleHistoryImpl"} - resource isolated function get api/v1/payments/invoice_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payments/invoice_cycle_history/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get a payment run # # + payment_run_id - The payment run ID. A payment run id in Advanced Payment Manager is different from a payment run id in Zuora. # + headers - Headers to be sent with the request @MethodImpl {name: "getPaymentRunImpl"} - resource isolated function get api/v1/subscription_payment_runs/[int payment_run_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/subscription_payment_runs/[int payment_run_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get a payment run schedule # # + schedule_id - The schedule ID # + headers - Headers to be sent with the request @MethodImpl {name: "getPaymentRunScheduleImpl"} - resource isolated function get api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function get api/v1/payment_run_schedules/[int schedule_id](map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Get all payment run schedules # # + headers - Headers to be sent with the request @MethodImpl {name: "getPaymentRunSchedulesImpl"} - resource isolated function get api/v1/payment_run_schedules(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/payment_run_schedules(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; # Get Statement Generator settings # # + headers - Headers to be sent with the request @MethodImpl {name: "getSettingsImpl"} - resource isolated function get api/v1/fetch_settings(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; + resource isolated function get api/v1/fetch_settings(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResourceWithoutPath"} external; @MethodImpl {name: "removeAccountFromCycleImpl"} - resource isolated function put api/v1/payments/remove_account_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payments/remove_account_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "removeDebitMemoFromCycleImpl"} - resource isolated function put api/v1/payments/remove_debit_memo_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payments/remove_debit_memo_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; @MethodImpl {name: "removeRemoveInoviceFromCycleImpl"} - resource isolated function put api/v1/payments/remove_invoice_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payments/remove_invoice_from_retry_cycle/\(map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; # Update a payment run schedule # # + schedule_id - The schedule ID # + headers - Headers to be sent with the request @MethodImpl {name: "updatePaymentRunScheduleImpl"} - resource isolated function put api/v1/payment_run_schedules/[int schedule_id](PUTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; + resource isolated function put api/v1/payment_run_schedules/[int schedule_id](PUTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; - private isolated function UpdateAccountAgentImpl(string account_id, map headers, typedesc targetType, *UpdateAccountAgentQueries queries) returns OkInline_response_200|error { + private isolated function UpdateAccountAgentImpl(string account_id, map headers, typedesc targetType, *UpdateAccountAgentQueries queries) returns http:StatusCodeResponse|error { return { body: {"success": true}, headers: {} }; } - private isolated function UpdateAccountImpl(string account_id, map headers, typedesc targetType, *UpdateAccountQueries queries) returns OkInline_response_200|error { + private isolated function UpdateAccountImpl(string account_id, map headers, typedesc targetType, *UpdateAccountQueries queries) returns http:StatusCodeResponse|error { return { body: {"success": true}, headers: {} }; } - private isolated function UpdateExecutePaymentsImpl(payments_execute_payments_body payload, map headers, typedesc targetType) returns OkInline_response_200_4|error { + private isolated function UpdateExecutePaymentsImpl(payments_execute_payments_body payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [100, 101, 110, 111, 121]"}, headers: {} }; } - private isolated function UpdateSubmitPaymentToCycleImpl(payments_submit_failed_payment_body payload, map headers, typedesc targetType) returns OkInline_response_200_8|error { + private isolated function UpdateSubmitPaymentToCycleImpl(payments_submit_failed_payment_body payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payment entered into retry process"}, headers: {} }; } - private isolated function createAdhocStatementRunImpl(POSTAdhocStatementRun payload, map headers, typedesc targetType) returns OkPOSTAdhocStatementRunResponse|error { + private isolated function createAdhocStatementRunImpl(POSTAdhocStatementRun payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "code": 200, "message": "Success", "statement_number": "STA00000008"}, headers: {} }; } - private isolated function createCustomStatementRunImpl(POSTCustomStatementRun payload, map headers, typedesc targetType) returns OkPOSTCustomStatementRunResponse|error { + private isolated function createCustomStatementRunImpl(POSTCustomStatementRun payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "code": 200, "message": "Success", "execution_number": "2", "report_file": ""}, headers: {} }; } - private isolated function createPaymentRunImpl(POSTPaymentRun payload, map headers, typedesc targetType) returns OkPostpaymentrunresponseJson|error { + private isolated function createPaymentRunImpl(POSTPaymentRun payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"id": 6, "success": "true"}, headers: {} }; } - private isolated function createPaymentRunScheduleImpl(POSTPaymentRunSchedule payload, map headers, typedesc targetType) returns OkPostpaymentrunscheduleresponseJson|error { + private isolated function createPaymentRunScheduleImpl(POSTPaymentRunSchedule payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"id": 6, "success": "true"}, headers: {} }; } - private isolated function deletePaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns OkDELETEPaymentRunScheduleResponse|error { + private isolated function deletePaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true}, headers: {} }; } - private isolated function executeExecuteAccountPaymentsImpl(map headers, typedesc targetType) returns OkInline_response_200_3|error { + private isolated function executeExecuteAccountPaymentsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [310, 311, 312]"}, headers: {} }; } - private isolated function executeExecuteDebitMemoPaymentImpl(map headers, typedesc targetType) returns OkInline_response_200_2|error { + private isolated function executeExecuteDebitMemoPaymentImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [300]"}, headers: {} }; } - private isolated function executeExecuteInvoicePaymentImpl(map headers, typedesc targetType) returns OkInline_response_200_1|error { + private isolated function executeExecuteInvoicePaymentImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [290, 291]"}, headers: {} }; } - private isolated function getAccountCycleHistoryImpl(map headers, typedesc targetType) returns OkGETAccountCycleHistoryResponse|error { + private isolated function getAccountCycleHistoryImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 3, "next_attempt": "2021-03-19T18:53:39.641Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fb78532b0f01785a38cede190a", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-03-24T19:34:20.254Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51aae41969", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.316-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, headers: {} }; } - private isolated function getAccountImpl(string account_id, map headers, typedesc targetType) returns OkCollectionAccount|error { + private isolated function getAccountImpl(string account_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}}, headers: {} }; } - private isolated function getAccountsImpl(map headers, typedesc targetType) returns OkGETCollectionAccountsResponse|error { + private isolated function getAccountsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"accounts": [{"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": 0, "Pending": 0, "In Dispute": 0, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20"}}, headers: {} }; } - private isolated function getActiveAccountCycleImpl(map headers, typedesc targetType) returns OkGETActiveAccountCycleResponse|error { + private isolated function getActiveAccountCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "debit_memo_id": "2c92c0fb78532b0001785a38f6427976", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.473Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a5199a6192d", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:27.521-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0fa7853052701785a38c6622473", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.436Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a519d85193b", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:28.161-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, headers: {} }; } - private isolated function getActiveDebitMemoCycleImpl(map headers, typedesc targetType) returns OkGETActiveDebitMemoCycleResponse|error { + private isolated function getActiveDebitMemoCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T10:22:57.464Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000380", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T10:22:57.464-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, headers: {} }; } - private isolated function getActiveInvoiceCycleImpl(map headers, typedesc targetType) returns OkGETActiveInvoiceCycleResponse|error { + private isolated function getActiveInvoiceCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0f8778bf8cd017798168cb50e0b", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T19:27:34.648Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ca076c21", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T19:27:34.648-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bce0d0a06d5", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:53:39.845-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, headers: {} }; } - private isolated function getAmountRecoveredImpl(map headers, typedesc targetType) returns OkGETAmountRecoveredResponse|error { + private isolated function getAmountRecoveredImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"currency": {"USD": {"total_amount": "77515.21", "last_30_days": "1100.01"}, "EUR": {"total_amount": "337.19", "last_30_days": "17.17"}, "CAD": {"total_amount": "123954.10", "last_30_days": "5132.87"}}, "success": true}, headers: {} }; } - private isolated function getBaselineMetricsImpl(map headers, typedesc targetType) returns OkGETBaselineMetricsResponse|error { + private isolated function getBaselineMetricsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"retry_success_rate": "11.90", "retry_success_rate_trend": "down", "document_success_rate": "13.54", "document_success_rate_trend": "neutral", "average_days_outstanding": "4.76", "average_days_outstanding_trend": "up", "success": true}, headers: {} }; } - private isolated function getCollectionsAgentImpl(string email, map headers, typedesc targetType) returns OkCollectionAgent|error { + private isolated function getCollectionsAgentImpl(string email, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}, headers: {} }; } - private isolated function getCollectionsAgentsImpl(map headers, typedesc targetType) returns OkGETCollectionAgentsResponse|error { + private isolated function getCollectionsAgentsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"accounts": [{"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20"}}, headers: {} }; } - private isolated function getCollectionsInfoImpl(map headers, typedesc targetType) returns OkCollectionsInfo|error { + private isolated function getCollectionsInfoImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"accounts_in_collections": 24, "home_currency": "USD", "total_debt": "8379.78", "largest_debts": ["Test Account - 12438.00 USD", "Jimmy John - 8000.00 USD", "James Smith - 2450.55 USD", "Bob Roberts - 1000.00 USD", "Jim Reynolds - 829.00 USD"], "oldest_debts": ["Test Account - 2662 days", "Jimbo - 1494 days", "Steve Smith - 942 days", "Jason Williams - 678 days", "Will Jasons - 365 days"], "statuses": {"In Collections": 24, "Pending": 2, "In Dispute": 5, "Paid in Full": 0}}, headers: {} }; } - private isolated function getCustomerGroupMetricsImpl(map headers, typedesc targetType) returns OkGETCustomerGroupMetricsResponse|error { + private isolated function getCustomerGroupMetricsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"customer_groups": [{"id": 1, "name": "batch22", "smart_retry": false, "document_success_rate": "17.17", "document_success_rate_trend": "up", "retry_success_rate": "21.76", "average_attempts": "4.11"}, {"id": 2, "name": "Smart Retry", "smart_retry": true, "document_success_rate": "74.17", "document_success_rate_trend": "down", "retry_success_rate": "81.21", "average_attempts": "1.32"}, {"id": 4, "name": "All Remaining Customers", "smart_retry": false, "document_success_rate": "16.35", "document_success_rate_trend": "up", "retry_success_rate": "15.21", "average_attempts": "3.32"}], "success": true}, headers: {} }; } - private isolated function getDebitMemoCycleHistoryImpl(map headers, typedesc targetType) returns OkGETDebitMemoCycleHistoryResponse|error { + private isolated function getDebitMemoCycleHistoryImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time", "api_updated_retry_time": "2021-03-26T14:27:21.107-04:00"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000378", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, headers: {} }; } - private isolated function getDocumentSuccessRateByCustomerGroupImpl(map headers, typedesc targetType) returns OkGETDocumentSuccessRateByCustomerGroupResponse|error { + private isolated function getDocumentSuccessRateByCustomerGroupImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"customer_groups": {"1": {"05_21": "17.53", "04_21": "13.21", "03_21": "14.92", "02_21": "8.99", "01_21": "34.25", "12_20": "12.30"}, "2": {"05_21": "11.11", "04_21": "7.87", "03_21": "26.00", "02_21": "11.06", "01_21": "13.43", "12_20": "17.92"}, "4": {"05_21": "11.13", "04_21": "9.17", "03_21": "17.20", "02_21": "19.06", "01_21": "12.43", "12_20": "15.92"}}, "success": true}, headers: {} }; } - private isolated function getInvoiceCycleHistoryImpl(map headers, typedesc targetType) returns OkGETInvoiceCycleHistoryResponse|error { + private isolated function getInvoiceCycleHistoryImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 1, "next_attempt": null, "customer_group": "Testing Group", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-04-01T19:11:21.639Z", "source": "PR-00000370", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 5}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, headers: {} }; } - private isolated function getPaymentRunImpl(int payment_run_id, map headers, typedesc targetType) returns OkGETPaymentRunResponse|error { + private isolated function getPaymentRunImpl(int payment_run_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "id": 6, "status": "Complete", "target_date": "2018-01-02T00:00:00.000Z", "filter": "Account.Currency = 'CAD'", "payment_run_schedule_id": "Adhoc", "invoices_held": {}, "metrics": {"documents": 0, "payments": 0, "failed": 0, "skipped": 0, "amount": 0, "credit": 0}}, headers: {} }; } - private isolated function getPaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns OkGETPaymentRunScheduleResponse|error { + private isolated function getPaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}, headers: {} }; } - private isolated function getPaymentRunSchedulesImpl(map headers, typedesc targetType) returns OkGETPaymentRunSchedulesResponse|error { + private isolated function getPaymentRunSchedulesImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "size": 3, "schedules": [{"id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}]}, headers: {} }; } - private isolated function getSettingsImpl(map headers, typedesc targetType) returns OkGETStatementSettingsResponse|error { + private isolated function getSettingsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "templates": [{"name": "Default Template"}, {"name": "Template for end consumers"}], "default_template": "Default Template", "default_cycle": "Month"}, headers: {} }; } - private isolated function removeAccountFromCycleImpl(map headers, typedesc targetType) returns OkInline_response_200_7|error { + private isolated function removeAccountFromCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [310, 311, 312]"}, headers: {} }; } - private isolated function removeDebitMemoFromCycleImpl(map headers, typedesc targetType) returns OkInline_response_200_6|error { + private isolated function removeDebitMemoFromCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [301]"}, headers: {} }; } - private isolated function removeRemoveInoviceFromCycleImpl(map headers, typedesc targetType) returns OkInline_response_200_5|error { + private isolated function removeRemoveInoviceFromCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [290, 291]"}, headers: {} }; } - private isolated function updatePaymentRunScheduleImpl(int schedule_id, PUTPaymentRunSchedule payload, map headers, typedesc targetType) returns OkPOSTPaymentRunScheduleResponse|error { + private isolated function updatePaymentRunScheduleImpl(int schedule_id, PUTPaymentRunSchedule payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { return { body: {"id": 6, "success": true}, headers: {} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java index 0dd050f7d..3d82b0e0e 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/FunctionSignatureGenerator.java @@ -21,13 +21,12 @@ import io.ballerina.compiler.syntax.tree.FunctionSignatureNode; import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; -import io.ballerina.openapi.core.generators.client.exception.FunctionSignatureGeneratorException; import java.util.List; import java.util.Optional; public interface FunctionSignatureGenerator { - Optional generateFunctionSignature() throws FunctionSignatureGeneratorException; + Optional generateFunctionSignature(); List getDiagnostics(); boolean hasDefaultStatusCodeBinding(); List getNonDefaultStatusCodes(); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java index 4ec835062..63b1a44b7 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java @@ -27,6 +27,7 @@ import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.Token; import io.ballerina.openapi.core.generators.client.FunctionGenerator; +import io.ballerina.openapi.core.generators.client.FunctionSignatureGenerator; import io.ballerina.openapi.core.generators.client.RemoteFunctionSignatureGenerator; import io.ballerina.openapi.core.generators.client.ResourceFunctionSignatureGenerator; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; @@ -69,6 +70,7 @@ public class MockClientFunctionGenerator implements FunctionGenerator { List diagnostics = new ArrayList<>(); boolean isResourceFunction; OASClientConfig oasClientConfig; + FunctionSignatureGenerator signatureGenerator; public MockClientFunctionGenerator(String path, Map.Entry operation, OASClientConfig oasClientConfig) { this.path = path; @@ -76,6 +78,10 @@ public MockClientFunctionGenerator(String path, Map.Entry generateFunction() throws BallerinaOpenA return Optional.empty(); } //create function signature - ResourceFunctionSignatureGenerator signatureGenerator = new ResourceFunctionSignatureGenerator( - operation.getValue(), openAPI, operation.getKey().toString(), path); Optional signatureNodeOptional = signatureGenerator.generateFunctionSignature(); diagnostics.addAll(signatureGenerator.getDiagnostics()); if (signatureNodeOptional.isEmpty()) { @@ -126,10 +130,8 @@ public Optional generateFunction() throws BallerinaOpenA NodeList qualifierList = createNodeList(createToken(REMOTE_KEYWORD), createToken(ISOLATED_KEYWORD)); Token functionKeyWord = createToken(FUNCTION_KEYWORD); IdentifierToken functionName = createIdentifierToken(operation.getValue().getOperationId()); - RemoteFunctionSignatureGenerator signatureGenerator = new RemoteFunctionSignatureGenerator( - operation.getValue(), openAPI, operation.getKey().toString().toLowerCase(Locale.ENGLISH), path); - diagnostics.addAll(signatureGenerator.getDiagnostics()); Optional signatureNodeOptional = signatureGenerator.generateFunctionSignature(); + diagnostics.addAll(signatureGenerator.getDiagnostics()); if (signatureNodeOptional.isEmpty()) { return Optional.empty(); } @@ -152,4 +154,14 @@ qualifierList, functionKeyWord, functionName, createEmptyNodeList(), functionSig public List getDiagnostics() { return diagnostics; } + + @Override + public boolean hasDefaultStatusCodeBinding() { + return signatureGenerator.hasDefaultStatusCodeBinding(); + } + + @Override + public List getNonDefaultStatusCodes() { + return signatureGenerator.getNonDefaultStatusCodes(); + } } From 66eb266ab801266ebe424e826da62399c3bbb8ee Mon Sep 17 00:00:00 2001 From: lnash94 Date: Mon, 3 Jun 2024 19:38:52 +0530 Subject: [PATCH 10/15] Separate ou the advance client mock client generation --- .../client/MockClientGenerationTests.java | 1 - .../mock_client_for_advance_return_type.bal | 190 +++++++----------- .../client/AdvanceMockClientGenerator.java | 30 +-- .../client/BallerinaClientGenerator.java | 4 +- ...aClientGeneratorWithStatusCodeBinding.java | 54 ++--- .../ImplFunctionSignatureGenerator.java | 11 +- .../MockImplFunctionSignatureGenerator.java | 86 ++++++++ .../mock/MockFunctionBodyGenerator.java | 53 +++-- 8 files changed, 250 insertions(+), 179 deletions(-) create mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java index 91447ea55..05470766c 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java @@ -135,5 +135,4 @@ public void advanceMockClientTest() throws IOException, BallerinaOpenApiExceptio SyntaxTree syntaxTree = mockClientGenerator.generateSyntaxTree(); compareGeneratedSyntaxTreeWithExpectedSyntaxTree(expectedPath, syntaxTree); } - } diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal index 8b8b1394e..8773125ab 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal @@ -15,22 +15,7 @@ annotation ClientMethodImpl MethodImpl on function; type ClientMethodInvocationError http:ClientError; -function setModule() = @java:Method {'class: "io.ballerina.openapi.client.ModuleUtils"} external; - -function init() { - setModule(); -} - -type ClientMethodImpl record {| - string name; -|}; - -annotation ClientMethodImpl MethodImpl on function; - -type ClientMethodInvocationError http:ClientError; - public isolated client class Client { - final http:StatusCodeClient clientEp; # Gets invoked to initialize the `connector`. # # + config - The configurations to be used when initializing the `connector` @@ -225,247 +210,212 @@ public isolated client class Client { resource isolated function put api/v1/payment_run_schedules/[int schedule_id](PUTPaymentRunSchedule payload, map headers = {}, typedesc targetType = <>) returns targetType|error = @java:Method {'class: "io.ballerina.openapi.client.GeneratedClient", name: "invokeResource"} external; private isolated function UpdateAccountAgentImpl(string account_id, map headers, typedesc targetType, *UpdateAccountAgentQueries queries) returns http:StatusCodeResponse|error { - return { - body: {"success": true}, - headers: {} + return { + body: {"success": true} }; } private isolated function UpdateAccountImpl(string account_id, map headers, typedesc targetType, *UpdateAccountQueries queries) returns http:StatusCodeResponse|error { - return { - body: {"success": true}, - headers: {} + return { + body: {"success": true} }; } private isolated function UpdateExecutePaymentsImpl(payments_execute_payments_body payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [100, 101, 110, 111, 121]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [100, 101, 110, 111, 121]"} }; } private isolated function UpdateSubmitPaymentToCycleImpl(payments_submit_failed_payment_body payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payment entered into retry process"}, - headers: {} + return { + body: {"success": true, "message": "Payment entered into retry process"} }; } private isolated function createAdhocStatementRunImpl(POSTAdhocStatementRun payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "code": 200, "message": "Success", "statement_number": "STA00000008"}, - headers: {} + return { + body: {"success": true, "code": 200, "message": "Success", "statement_number": "STA00000008"} }; } private isolated function createCustomStatementRunImpl(POSTCustomStatementRun payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "code": 200, "message": "Success", "execution_number": "2", "report_file": ""}, - headers: {} + return { + body: {"success": true, "code": 200, "message": "Success", "execution_number": "2", "report_file": ""} }; } private isolated function createPaymentRunImpl(POSTPaymentRun payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"id": 6, "success": "true"}, - headers: {} + return { + body: {"id": 6, "success": "true"} }; } private isolated function createPaymentRunScheduleImpl(POSTPaymentRunSchedule payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"id": 6, "success": "true"}, - headers: {} + return { + body: {"id": 6, "success": "true"} }; } private isolated function deletePaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true}, - headers: {} + return { + body: {"success": true} }; } private isolated function executeExecuteAccountPaymentsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [310, 311, 312]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [310, 311, 312]"} }; } private isolated function executeExecuteDebitMemoPaymentImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [300]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [300]"} }; } private isolated function executeExecuteInvoicePaymentImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [290, 291]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs enqueued for processing: [290, 291]"} }; } private isolated function getAccountCycleHistoryImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 3, "next_attempt": "2021-03-19T18:53:39.641Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fb78532b0f01785a38cede190a", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-03-24T19:34:20.254Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51aae41969", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.316-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, - headers: {} + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 3, "next_attempt": "2021-03-19T18:53:39.641Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fb78532b0f01785a38cede190a", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-03-24T19:34:20.254Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51aae41969", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.316-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]} }; } private isolated function getAccountImpl(string account_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}}, - headers: {} + return { + body: {"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": true, "Pending": false, "In Dispute": false, "Paid In Full": false}} }; } private isolated function getAccountsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"accounts": [{"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": 0, "Pending": 0, "In Dispute": 0, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20"}}, - headers: {} + return { + body: {"accounts": [{"name": "Testing Account", "zuora_id": "2c92c0f863f2b1680163f579b7e705da", "in_collections": true, "collections_agent": "2018-01-02T00:00:00.000Z", "account_currency": "CAD", "home_currency": "USD", "amount_due_account_currency": 15540, "amount_due_home_currency": 800.55, "last_open_invoice_date": "2018-06-12", "average_debt_age": "194.4 days", "statuses": {"In Collections": 0, "Pending": 0, "In Dispute": 0, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/accounts?page=2&page_length=20"}} }; } private isolated function getActiveAccountCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "debit_memo_id": "2c92c0fb78532b0001785a38f6427976", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.473Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a5199a6192d", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:27.521-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0fa7853052701785a38c6622473", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.436Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a519d85193b", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:28.161-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, - headers: {} + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "debit_memo_id": "2c92c0fb78532b0001785a38f6427976", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.473Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a5199a6192d", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:27.521-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0fa7853052701785a38c6622473", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 1, "next_attempt": "2021-04-01T19:27:34.436Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a519d85193b", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:28.161-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]} }; } private isolated function getActiveDebitMemoCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T10:22:57.464Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000380", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T10:22:57.464-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, - headers: {} + return { + body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T10:22:57.464Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000380", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T10:22:57.464-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]} }; } private isolated function getActiveInvoiceCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0f8778bf8cd017798168cb50e0b", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T19:27:34.648Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ca076c21", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T19:27:34.648-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bce0d0a06d5", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:53:39.845-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, - headers: {} + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdccdd6ce2f29", "invoice_id": "2c92c0f8778bf8cd017798168cb50e0b", "payment_method_id": "2c92c0f9774f2b3e01775f6f06d87b61", "currency": "USD", "status": "Cycle Incomplete", "current_attempt_number": 2, "next_attempt": "2021-04-01T19:27:34.648Z", "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ca076c21", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-04-01T19:27:34.648-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bce0d0a06d5", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:53:39.845-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]} }; } private isolated function getAmountRecoveredImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"currency": {"USD": {"total_amount": "77515.21", "last_30_days": "1100.01"}, "EUR": {"total_amount": "337.19", "last_30_days": "17.17"}, "CAD": {"total_amount": "123954.10", "last_30_days": "5132.87"}}, "success": true}, - headers: {} + return { + body: {"currency": {"USD": {"total_amount": "77515.21", "last_30_days": "1100.01"}, "EUR": {"total_amount": "337.19", "last_30_days": "17.17"}, "CAD": {"total_amount": "123954.10", "last_30_days": "5132.87"}}, "success": true} }; } private isolated function getBaselineMetricsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"retry_success_rate": "11.90", "retry_success_rate_trend": "down", "document_success_rate": "13.54", "document_success_rate_trend": "neutral", "average_days_outstanding": "4.76", "average_days_outstanding_trend": "up", "success": true}, - headers: {} + return { + body: {"retry_success_rate": "11.90", "retry_success_rate_trend": "down", "document_success_rate": "13.54", "document_success_rate_trend": "neutral", "average_days_outstanding": "4.76", "average_days_outstanding_trend": "up", "success": true} }; } private isolated function getCollectionsAgentImpl(string email, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}, - headers: {} + return { + body: {"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}} }; } private isolated function getCollectionsAgentsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"accounts": [{"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20"}}, - headers: {} + return { + body: {"accounts": [{"name": "Testing User", "email": "test@zuora.com", "zuora_identity_id": "2c92c0f96178a7a901619b10f5d12345", "amount_in_collections": 800.55, "accounts": 2, "account_statuses": {"In Collections": 1, "Pending": 0, "In Dispute": 1, "Paid In Full": 0}}], "pagination": {"page": 1, "page_length": 20, "next_page": "https://collections-window.apps.zuora.com/api/v1/users?page=2&page_length=20"}} }; } private isolated function getCollectionsInfoImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"accounts_in_collections": 24, "home_currency": "USD", "total_debt": "8379.78", "largest_debts": ["Test Account - 12438.00 USD", "Jimmy John - 8000.00 USD", "James Smith - 2450.55 USD", "Bob Roberts - 1000.00 USD", "Jim Reynolds - 829.00 USD"], "oldest_debts": ["Test Account - 2662 days", "Jimbo - 1494 days", "Steve Smith - 942 days", "Jason Williams - 678 days", "Will Jasons - 365 days"], "statuses": {"In Collections": 24, "Pending": 2, "In Dispute": 5, "Paid in Full": 0}}, - headers: {} + return { + body: {"accounts_in_collections": 24, "home_currency": "USD", "total_debt": "8379.78", "largest_debts": ["Test Account - 12438.00 USD", "Jimmy John - 8000.00 USD", "James Smith - 2450.55 USD", "Bob Roberts - 1000.00 USD", "Jim Reynolds - 829.00 USD"], "oldest_debts": ["Test Account - 2662 days", "Jimbo - 1494 days", "Steve Smith - 942 days", "Jason Williams - 678 days", "Will Jasons - 365 days"], "statuses": {"In Collections": 24, "Pending": 2, "In Dispute": 5, "Paid in Full": 0}} }; } private isolated function getCustomerGroupMetricsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"customer_groups": [{"id": 1, "name": "batch22", "smart_retry": false, "document_success_rate": "17.17", "document_success_rate_trend": "up", "retry_success_rate": "21.76", "average_attempts": "4.11"}, {"id": 2, "name": "Smart Retry", "smart_retry": true, "document_success_rate": "74.17", "document_success_rate_trend": "down", "retry_success_rate": "81.21", "average_attempts": "1.32"}, {"id": 4, "name": "All Remaining Customers", "smart_retry": false, "document_success_rate": "16.35", "document_success_rate_trend": "up", "retry_success_rate": "15.21", "average_attempts": "3.32"}], "success": true}, - headers: {} + return { + body: {"customer_groups": [{"id": 1, "name": "batch22", "smart_retry": false, "document_success_rate": "17.17", "document_success_rate_trend": "up", "retry_success_rate": "21.76", "average_attempts": "4.11"}, {"id": 2, "name": "Smart Retry", "smart_retry": true, "document_success_rate": "74.17", "document_success_rate_trend": "down", "retry_success_rate": "81.21", "average_attempts": "1.32"}, {"id": 4, "name": "All Remaining Customers", "smart_retry": false, "document_success_rate": "16.35", "document_success_rate_trend": "up", "retry_success_rate": "15.21", "average_attempts": "3.32"}], "success": true} }; } private isolated function getDebitMemoCycleHistoryImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time", "api_updated_retry_time": "2021-03-26T14:27:21.107-04:00"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000378", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, - headers: {} + return { + body: {"cycles": [{"account_id": "2c92c0f868e161e70168e25eb51d755f", "debit_memo_id": "2c92c0fa7853052701785a38f3bb267f", "payment_method_id": "2c92c0f8774f1afe01775f6e533c4c06", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c085785305e201785a51af791979", "time_of_execution": "2021-03-23T16:50:18.878Z", "source": "PR-00000376", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-23T07:51:30.380-09:00", "criteria": "incremental_time", "api_updated_retry_time": "2021-03-26T14:27:21.107-04:00"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c0857881cf3e01788ee263b0331c", "time_of_execution": "2021-04-01T19:21:55.207Z", "source": "PR-00000378", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]} }; } private isolated function getDocumentSuccessRateByCustomerGroupImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"customer_groups": {"1": {"05_21": "17.53", "04_21": "13.21", "03_21": "14.92", "02_21": "8.99", "01_21": "34.25", "12_20": "12.30"}, "2": {"05_21": "11.11", "04_21": "7.87", "03_21": "26.00", "02_21": "11.06", "01_21": "13.43", "12_20": "17.92"}, "4": {"05_21": "11.13", "04_21": "9.17", "03_21": "17.20", "02_21": "19.06", "01_21": "12.43", "12_20": "15.92"}}, "success": true}, - headers: {} + return { + body: {"customer_groups": {"1": {"05_21": "17.53", "04_21": "13.21", "03_21": "14.92", "02_21": "8.99", "01_21": "34.25", "12_20": "12.30"}, "2": {"05_21": "11.11", "04_21": "7.87", "03_21": "26.00", "02_21": "11.06", "01_21": "13.43", "12_20": "17.92"}, "4": {"05_21": "11.13", "04_21": "9.17", "03_21": "17.20", "02_21": "19.06", "01_21": "12.43", "12_20": "15.92"}}, "success": true} }; } private isolated function getInvoiceCycleHistoryImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 1, "next_attempt": null, "customer_group": "Testing Group", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-04-01T19:11:21.639Z", "source": "PR-00000370", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 5}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]}, - headers: {} + return { + body: {"cycles": [{"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 1, "next_attempt": null, "customer_group": "Testing Group", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-04-01T19:11:21.639Z", "source": "PR-00000370", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 5}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}, {"account_id": "2c92c0f96bd69165016bdcbf55ad5e62", "invoice_id": "2c92c0fa7849b3ff01784bc5e8ee18b5", "payment_method_id": "2c92c0f9774f2b3e01775f6cf2fb726a", "currency": "USD", "status": "Cycle Complete", "current_attempt_number": 2, "next_attempt": null, "customer_group": "All Remaining Customers", "attempts": [{"attempt_number": 1, "zuora_payment_id": "2c92c0867849d42301784bc9ce806c31", "time_of_execution": "2021-03-19T18:42:20.103Z", "source": "PR-00000371", "cpr_generated": false, "success": false, "amount_collected": "0.0", "action_info": {"action": "Retry"}, "retry_info": {"next": "2021-03-19T09:43:28.670-09:00", "criteria": "incremental_time"}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}, {"attempt_number": 2, "zuora_payment_id": "2c92c09c7849d3c101784bcdfc010671", "time_of_execution": "2021-03-19T18:52:24.137Z", "source": "PR-00000372", "cpr_generated": true, "success": false, "amount_collected": "0.0", "action_info": {"action": "Stop"}, "retry_info": {}, "mapping_info": {"label": "Hard Decline", "level": "code", "customer_group_id": 1}, "gateway_info": {"id": "2c92c0f85e2d19af015e3a61d8947e5d", "code": "insufficient_funds", "response": "Your card has insufficient funds."}}]}]} }; } private isolated function getPaymentRunImpl(int payment_run_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "id": 6, "status": "Complete", "target_date": "2018-01-02T00:00:00.000Z", "filter": "Account.Currency = 'CAD'", "payment_run_schedule_id": "Adhoc", "invoices_held": {}, "metrics": {"documents": 0, "payments": 0, "failed": 0, "skipped": 0, "amount": 0, "credit": 0}}, - headers: {} + return { + body: {"success": true, "id": 6, "status": "Complete", "target_date": "2018-01-02T00:00:00.000Z", "filter": "Account.Currency = 'CAD'", "payment_run_schedule_id": "Adhoc", "invoices_held": {}, "metrics": {"documents": 0, "payments": 0, "failed": 0, "skipped": 0, "amount": 0, "credit": 0}} }; } private isolated function getPaymentRunScheduleImpl(int schedule_id, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}, - headers: {} + return { + body: {"success": true, "id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"} }; } private isolated function getPaymentRunSchedulesImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "size": 3, "schedules": [{"id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}]}, - headers: {} + return { + body: {"success": true, "size": 3, "schedules": [{"id": 6, "status": "Active", "filter": "Account.BillCycleDay = 8", "schedule": "At 6:00 AM, only on Monday and Tuesday"}]} }; } private isolated function getSettingsImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "templates": [{"name": "Default Template"}, {"name": "Template for end consumers"}], "default_template": "Default Template", "default_cycle": "Month"}, - headers: {} + return { + body: {"success": true, "templates": [{"name": "Default Template"}, {"name": "Template for end consumers"}], "default_template": "Default Template", "default_cycle": "Month"} }; } private isolated function removeAccountFromCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [310, 311, 312]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [310, 311, 312]"} }; } private isolated function removeDebitMemoFromCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [301]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [301]"} }; } private isolated function removeRemoveInoviceFromCycleImpl(map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [290, 291]"}, - headers: {} + return { + body: {"success": true, "message": "Payments with the following IDs have been removed from the retry cycle: [290, 291]"} }; } private isolated function updatePaymentRunScheduleImpl(int schedule_id, PUTPaymentRunSchedule payload, map headers, typedesc targetType) returns http:StatusCodeResponse|error { - return { - body: {"id": 6, "success": true}, - headers: {} + return { + body: {"id": 6, "success": true} }; } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java index f76942ab2..8c5582aef 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java @@ -31,14 +31,20 @@ import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.Token; import io.ballerina.openapi.core.generators.client.exception.ClientException; +import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; import io.ballerina.openapi.core.generators.document.ClientDocCommentGenerator; import io.ballerina.tools.text.TextDocument; import io.ballerina.tools.text.TextDocuments; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken; @@ -85,18 +91,6 @@ public FunctionDefinitionNode createInitFunction() { functionBodyNode); } - @Override - protected List getModuleMemberDeclarationNodes() throws BallerinaOpenApiException { - List nodes = new ArrayList<>(); - nodes.add(getSetModuleFunction()); - nodes.add(getModuleInitFunction()); - nodes.add(getClientMethodImplType()); - nodes.add(getMethodImplAnnotation()); - nodes.add(getClientErrorType()); - nodes.addAll(super.getModuleMemberDeclarationNodes()); - return nodes; - } - /** * This method for generate the client syntax tree. * @@ -120,4 +114,16 @@ public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientE oasClientConfig.isResourceMode()); return clientDocCommentGenerator.updateSyntaxTreeWithDocComments(); } + + @Override + public FunctionBodyGenerator getFunctionBodyGeneratorImp(String path, + Map.Entry operation, + OpenAPI openAPI, + AuthConfigGeneratorImp authConfigGeneratorImp, + BallerinaUtilGenerator ballerinaUtilGenerator, + boolean hasDefaultResponse, + List nonDefaultStatusCodes, + ImplFunctionSignatureGenerator signatureGenerator) { + return new MockFunctionBodyGenerator(path, operation, openAPI, true); + } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java index 8b0b25b2d..a30ba3da0 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java @@ -245,7 +245,9 @@ private ClassDefinitionNode getClassDefinitionNode() { // Collect members for class definition node List memberNodeList = new ArrayList<>(); // Add instance variable to class definition node - memberNodeList.addAll(createClassInstanceVariables()); + if (!oasClientConfig.isMock()) { + memberNodeList.addAll(createClassInstanceVariables()); + } // Add init function to class definition node memberNodeList.add(createInitFunction()); Map> filteredOperations = filterOperations(); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java index c78ff3ec2..303f7849e 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java @@ -180,7 +180,7 @@ private void addClientFunctionImpl(Map.Entry ope FunctionDefinitionNode clientExternFunction = clientFunctionNodes.get(clientFunctionNodes.size() - 1); Optional implFunction = createImplFunction(path, operationEntry, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, clientExternFunction, hasDefaultResponse, - nonDefaultStatusCodes, oasClientConfig.isMock()); + nonDefaultStatusCodes); if (implFunction.isPresent()) { clientFunctionNodes.add(implFunction.get()); } else { @@ -215,44 +215,46 @@ protected Optional createImplFunction(String path, BallerinaUtilGenerator ballerinaUtilGenerator, FunctionDefinitionNode clientExternFunction, boolean hasDefaultResponse, - List nonDefaultStatusCodes, - boolean isMock) { + List nonDefaultStatusCodes) { //Create qualifier list NodeList qualifierList = createNodeList(createToken(PRIVATE_KEYWORD), createToken(ISOLATED_KEYWORD)); Token functionKeyWord = createToken(FUNCTION_KEYWORD); IdentifierToken functionName = createIdentifierToken(operation.getValue().getOperationId() + "Impl"); // Create function signature - ImplFunctionSignatureGenerator signatureGenerator = new ImplFunctionSignatureGenerator(operation.getValue(), - openAPI, operation.getKey().toString().toLowerCase(Locale.ROOT), path, clientExternFunction); + ImplFunctionSignatureGenerator signatureGenerator = getImplFunctionSignatureGenerator(path, operation, openAPI, clientExternFunction); //Create function body - FunctionBodyNode functionBodyNode; - if (isMock) { - MockFunctionBodyGenerator bodyGenerator = new MockFunctionBodyGenerator(path, operation, openAPI, - true); - Optional functionBodyOptionalNode = bodyGenerator.getFunctionBodyNode(); - diagnostics.addAll(bodyGenerator.getDiagnostics()); - if (functionBodyOptionalNode.isEmpty()) { - return Optional.empty(); - } - functionBodyNode = bodyGenerator.getFunctionBodyNode().get(); - } else { - FunctionBodyGeneratorImp functionBodyGenerator = new ImplFunctionBodyGenerator(path, operation, openAPI, - authConfigGeneratorImp, ballerinaUtilGenerator, imports, signatureGenerator.hasHeaders(), - signatureGenerator.hasDefaultHeaders(), signatureGenerator.hasQueries(), hasDefaultResponse, - nonDefaultStatusCodes); - Optional functionBodyNodeResult = functionBodyGenerator.getFunctionBodyNode(); - if (functionBodyNodeResult.isEmpty()) { - return Optional.empty(); - } - functionBodyNode = functionBodyNodeResult.get(); + FunctionBodyGenerator functionBodyGenerator = getFunctionBodyGeneratorImp(path, operation, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, hasDefaultResponse, nonDefaultStatusCodes, signatureGenerator); + Optional functionBodyNodeResult = functionBodyGenerator.getFunctionBodyNode(); + diagnostics.addAll(functionBodyGenerator.getDiagnostics()); + if (functionBodyNodeResult.isEmpty()) { + return Optional.empty(); } - + FunctionBodyNode functionBodyNode = functionBodyNodeResult.get(); Optional functionSignatureNode = signatureGenerator.generateFunctionSignature(); return functionSignatureNode.map(signatureNode -> NodeFactory.createFunctionDefinitionNode(OBJECT_METHOD_DEFINITION, null, qualifierList, functionKeyWord, functionName, createEmptyNodeList(), signatureNode, functionBodyNode)); } + protected ImplFunctionSignatureGenerator getImplFunctionSignatureGenerator(String path, Map.Entry operation, OpenAPI openAPI, FunctionDefinitionNode clientExternFunction) { + return new ImplFunctionSignatureGenerator(operation.getValue(), + openAPI, operation.getKey().toString().toLowerCase(Locale.ROOT), path, clientExternFunction); + } + + protected FunctionBodyGenerator getFunctionBodyGeneratorImp(String path, + Map.Entry operation, + OpenAPI openAPI, + AuthConfigGeneratorImp authConfigGeneratorImp, + BallerinaUtilGenerator ballerinaUtilGenerator, + boolean hasDefaultResponse, + List nonDefaultStatusCodes, + ImplFunctionSignatureGenerator signatureGenerator) { + return new ImplFunctionBodyGenerator(path, operation, openAPI, + authConfigGeneratorImp, ballerinaUtilGenerator, imports, signatureGenerator.hasHeaders(), + signatureGenerator.hasDefaultHeaders(), signatureGenerator.hasQueries(), hasDefaultResponse, + nonDefaultStatusCodes); + } + /** * Get the setModule function definition node. *
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java
index ad5e29d0c..284242ecc 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java
@@ -59,12 +59,19 @@ public class ImplFunctionSignatureGenerator {
 
     List parameterNodes = new ArrayList<>();
     ReturnTypeDescriptorNode returnTypeDescriptorNode;
-
     ResourceFunctionSignatureGenerator resourceFunctionSignatureGenerator;
-
+    Operation operation;
+    OpenAPI openAPI;
+    String path;
+    String httpMethod;
 
     public ImplFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, String httpMethod, String path,
                                           FunctionDefinitionNode clientExternFunction) {
+        this.operation = operation;
+        this.path = path;
+        this.httpMethod = httpMethod;
+        this.openAPI = openAPI;
+
         FunctionSignatureNode functionSignatureNode = clientExternFunction.functionSignature();
         if (Objects.isNull(functionSignatureNode)) {
             return;
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java
new file mode 100644
index 000000000..46066678a
--- /dev/null
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org).
+ *
+ *  WSO2 LLC. licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except
+ *  in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package io.ballerina.openapi.core.generators.client;
+
+import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode;
+import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode;
+import io.ballerina.compiler.syntax.tree.TypeDescriptorNode;
+import io.ballerina.openapi.core.generators.common.GeneratorConstants;
+import io.ballerina.openapi.core.generators.common.exception.InvalidReferenceException;
+import io.ballerina.tools.diagnostics.Diagnostic;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+import io.swagger.v3.oas.models.responses.ApiResponses;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList;
+import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken;
+import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnTypeDescriptorNode;
+import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURNS_KEYWORD;
+import static io.ballerina.openapi.core.generators.common.GeneratorUtils.generateStatusCodeTypeInclusionRecord;
+
+/**
+ * This class is for generating the mock advance client method signature.
+ *
+ * @since 2.1.0
+ */
+public class MockImplFunctionSignatureGenerator extends ImplFunctionSignatureGenerator {
+    List diagnostics = new ArrayList<>();
+    public MockImplFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, String httpMethod, String path,
+                                              FunctionDefinitionNode clientExternFunction) {
+        super(operation, openAPI, httpMethod, path, clientExternFunction);
+        returnTypeDescriptorNode = getReturnTypeDescriptorNode();
+    }
+
+    private ReturnTypeDescriptorNode getReturnTypeDescriptorNode() {
+        ApiResponses responses = operation.getResponses();
+        ApiResponse successResponse = null;
+        String code = null;
+        for (Map.Entry response : responses.entrySet()) {
+            if (response.getKey().startsWith("2")) {
+                code = response.getKey().trim();
+                successResponse = response.getValue();
+                break;
+            }
+        }
+        if (code == null) {
+            return null;
+        }
+        Optional typeDescriptorNode = populateReturnTypeDesc(code, successResponse);
+        return typeDescriptorNode.map(descriptorNode -> createReturnTypeDescriptorNode(createToken(RETURNS_KEYWORD),
+                createEmptyNodeList(), descriptorNode)).orElse(null);
+    }
+
+    public Optional populateReturnTypeDesc(String responseCode, ApiResponse response) {
+        String code = GeneratorConstants.HTTP_CODES_DES.get(responseCode);
+        try {
+            return Optional.of(generateStatusCodeTypeInclusionRecord(code, response, httpMethod, openAPI, path, diagnostics));
+        } catch (InvalidReferenceException e) {
+            return Optional.empty();
+        }
+    }
+
+    public List getDiagnostics () {
+        return diagnostics;
+    }
+}
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java
index 701c230cc..bd50ca7c8 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java
@@ -23,12 +23,15 @@
 import io.ballerina.compiler.syntax.tree.NodeList;
 import io.ballerina.compiler.syntax.tree.NodeParser;
 import io.ballerina.compiler.syntax.tree.StatementNode;
+import io.ballerina.compiler.syntax.tree.TypeDescriptorNode;
 import io.ballerina.openapi.core.generators.client.FunctionBodyGenerator;
 import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic;
 import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp;
 import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages;
+import io.ballerina.openapi.core.generators.common.GeneratorConstants;
 import io.ballerina.openapi.core.generators.common.GeneratorUtils;
 import io.ballerina.openapi.core.generators.common.exception.InvalidReferenceException;
+import io.ballerina.tools.diagnostics.Diagnostic;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
@@ -41,6 +44,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 
@@ -50,6 +54,7 @@
 import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN;
 import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN;
 import static io.ballerina.openapi.core.generators.common.GeneratorConstants.RESPONSE;
+import static io.ballerina.openapi.core.generators.common.GeneratorUtils.generateStatusCodeTypeInclusionRecord;
 
 /**
  * Mock function body generator.
@@ -63,7 +68,6 @@ public class MockFunctionBodyGenerator implements FunctionBodyGenerator {
     List diagnostics = new ArrayList<>();
     boolean isAdvanceClient;
 
-
     public MockFunctionBodyGenerator(String path, Map.Entry operation,
                                      OpenAPI openAPI, boolean isAdvanceClient) {
         this.path = path;
@@ -78,9 +82,11 @@ public Optional getFunctionBodyNode() {
         ApiResponses responses = operation.getValue().getResponses();
         //Get the successful response
         ApiResponse successResponse = null;
+        String code = null;
         for (Map.Entry response : responses.entrySet()) {
             if (response.getKey().startsWith("2")) {
                 successResponse = response.getValue();
+                code = response.getKey().trim();
                 break;
             }
         }
@@ -123,25 +129,25 @@ public Optional getFunctionBodyNode() {
         if (example == null) {
             example = examples.values().iterator().next();
         }
-
-        if (example.get$ref() != null) {
-            try {
+        String statement;
+        try {
+            if (example.get$ref() != null) {
                 String exampleName = GeneratorUtils.extractReferenceType(example.get$ref());
                 Map exampleMap = openAPI.getComponents().getExamples();
-                 example = exampleMap.get(exampleName);
-            } catch (InvalidReferenceException e) {
-                return Optional.empty();
+                example = exampleMap.get(exampleName);
             }
-        }
-        String exampleValue = example.getValue().toString();
-        String statement;
-        if (isAdvanceClient) {
-            statement = "return {\n" +
-                    "            body : " + exampleValue + ",\n" +
-                    "            headers: {}\n" +
-                    "        };";
-        } else {
-            statement = "return " + exampleValue + ";";
+            String exampleValue = example.getValue().toString();
+            //TODO implement if the response has header example
+            if (isAdvanceClient) {
+                List newDiagnostics = new ArrayList<>();
+                statement = getReturnForAdvanceClient(successResponse, code, exampleValue, newDiagnostics);
+                diagnostics.addAll(newDiagnostics.stream().map(ClientDiagnosticImp::new).toList());
+            } else {
+                statement = "return " + exampleValue + ";";
+            }
+        } catch (InvalidReferenceException e) {
+            diagnostics.add(new ClientDiagnosticImp(e.getDiagnostic()));
+            return Optional.empty();
         }
         StatementNode returnNode = NodeParser.parseStatement(statement);
         NodeList statementList = createNodeList(returnNode);
@@ -151,6 +157,19 @@ public Optional getFunctionBodyNode() {
         return Optional.of(fBodyBlock);
     }
 
+    private String getReturnForAdvanceClient(ApiResponse successResponse, String code, String exampleValue,
+                                             List newDiagnostics) throws InvalidReferenceException {
+        String statement;
+        code = GeneratorConstants.HTTP_CODES_DES.get(code);
+        String method = operation.getKey().toString().toLowerCase(Locale.ENGLISH);
+        TypeDescriptorNode typeDescriptorNode = generateStatusCodeTypeInclusionRecord(code,
+                successResponse, method, openAPI, path, newDiagnostics);
+        statement = "return  <" + typeDescriptorNode.toSourceCode() + " > {\n" +
+                "            body : " + exampleValue + "\n" +
+                "        };";
+        return statement;
+    }
+
     private Map getExamplesFromSchema(Schema schema) throws InvalidReferenceException {
         Map examples = new HashMap<>();
         if (schema.getExample() != null) {

From 88ebf8995c4ebd6698e0f8c203525a18792c703a Mon Sep 17 00:00:00 2001
From: lnash94 
Date: Tue, 4 Jun 2024 09:26:40 +0530
Subject: [PATCH 11/15] Fix checkstyle issue

---
 .../client/AdvanceMockClientGenerator.java         |  1 -
 ...lerinaClientGeneratorWithStatusCodeBinding.java | 14 ++++++++++----
 .../client/MockImplFunctionSignatureGenerator.java |  3 ++-
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java
index 8c5582aef..0c0649109 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java
@@ -43,7 +43,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
 import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList;
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java
index 303f7849e..9ab04bea7 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java
@@ -46,7 +46,6 @@
 import io.ballerina.compiler.syntax.tree.TypeDefinitionNode;
 import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnosticImp;
 import io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages;
-import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator;
 import io.ballerina.openapi.core.generators.client.model.OASClientConfig;
 import io.ballerina.openapi.core.generators.common.GeneratorConstants;
 import io.ballerina.openapi.core.generators.common.GeneratorUtils;
@@ -221,9 +220,12 @@ protected Optional createImplFunction(String path,
         Token functionKeyWord = createToken(FUNCTION_KEYWORD);
         IdentifierToken functionName = createIdentifierToken(operation.getValue().getOperationId() + "Impl");
         // Create function signature
-        ImplFunctionSignatureGenerator signatureGenerator = getImplFunctionSignatureGenerator(path, operation, openAPI, clientExternFunction);
+        ImplFunctionSignatureGenerator signatureGenerator = getImplFunctionSignatureGenerator(path, operation,
+                openAPI, clientExternFunction);
         //Create function body
-        FunctionBodyGenerator functionBodyGenerator = getFunctionBodyGeneratorImp(path, operation, openAPI, authConfigGeneratorImp, ballerinaUtilGenerator, hasDefaultResponse, nonDefaultStatusCodes, signatureGenerator);
+        FunctionBodyGenerator functionBodyGenerator = getFunctionBodyGeneratorImp(path, operation, openAPI,
+                authConfigGeneratorImp, ballerinaUtilGenerator, hasDefaultResponse, nonDefaultStatusCodes,
+                signatureGenerator);
         Optional functionBodyNodeResult = functionBodyGenerator.getFunctionBodyNode();
         diagnostics.addAll(functionBodyGenerator.getDiagnostics());
         if (functionBodyNodeResult.isEmpty()) {
@@ -236,7 +238,11 @@ protected Optional createImplFunction(String path,
                         functionKeyWord, functionName, createEmptyNodeList(), signatureNode, functionBodyNode));
     }
 
-    protected ImplFunctionSignatureGenerator getImplFunctionSignatureGenerator(String path, Map.Entry operation, OpenAPI openAPI, FunctionDefinitionNode clientExternFunction) {
+    protected ImplFunctionSignatureGenerator getImplFunctionSignatureGenerator(String path,
+                                                                               Map.Entry
+                                                                                       operation, OpenAPI openAPI,
+                                                                               FunctionDefinitionNode
+                                                                                       clientExternFunction) {
         return new ImplFunctionSignatureGenerator(operation.getValue(),
                 openAPI, operation.getKey().toString().toLowerCase(Locale.ROOT), path, clientExternFunction);
     }
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java
index 46066678a..3805bac1c 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java
@@ -74,7 +74,8 @@ private ReturnTypeDescriptorNode getReturnTypeDescriptorNode() {
     public Optional populateReturnTypeDesc(String responseCode, ApiResponse response) {
         String code = GeneratorConstants.HTTP_CODES_DES.get(responseCode);
         try {
-            return Optional.of(generateStatusCodeTypeInclusionRecord(code, response, httpMethod, openAPI, path, diagnostics));
+            return Optional.of(generateStatusCodeTypeInclusionRecord(code, response, httpMethod, openAPI, path,
+                    diagnostics));
         } catch (InvalidReferenceException e) {
             return Optional.empty();
         }

From 55d3b1e9ee42e7926ced90413443c2ad9efd4ee8 Mon Sep 17 00:00:00 2001
From: lnash94 
Date: Tue, 4 Jun 2024 11:03:16 +0530
Subject: [PATCH 12/15] Fix review suggestions

---
 .../openapi/cmd/BallerinaCodeGenerator.java   | 18 ++--
 .../client/mock/basic_response_example.bal    |  3 -
 .../mock_client_for_advance_return_type.bal   |  1 +
 .../client/mock/mock_client_for_remote.bal    |  2 -
 .../client/mock/reference_example.bal         |  3 -
 .../client/AdvanceMockClientGenerator.java    | 58 +------------
 .../client/BallerinaClientGenerator.java      | 31 ++++---
 ...aClientGeneratorWithStatusCodeBinding.java |  8 +-
 .../client/BallerinaMockClientGenerator.java  | 47 +++-------
 .../ImplFunctionSignatureGenerator.java       |  9 --
 .../MockImplFunctionSignatureGenerator.java   | 87 -------------------
 .../client/diagnostic/DiagnosticMessages.java |  5 +-
 .../mock/MockClientFunctionGenerator.java     | 15 +++-
 .../mock/MockFunctionBodyGenerator.java       | 33 +++++--
 14 files changed, 91 insertions(+), 229 deletions(-)
 delete mode 100644 openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java

diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java
index 53bbe817b..fabb88b4b 100644
--- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java
+++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java
@@ -139,8 +139,7 @@ public void generateClientAndService(String definitionPath, String serviceName,
                 .withResourceMode(isResource)
                 .withMock(isMock).build();
 
-        BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig, statusCodeBinding,
-                isMock);
+        BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig);
         String clientContent = Formatter.format(clientGenerator.generateSyntaxTree()).toSourceCode();
 
         //Update type definition list with auth related type definitions
@@ -395,8 +394,7 @@ private List generateClientFiles(Path openAPI, Filter filter, boolea
         //Take default DO NOT modify
         licenseHeader = licenseHeader.isBlank() ? DO_NOT_MODIFY_FILE_HEADER : licenseHeader;
         TypeHandler.createInstance(openAPIDef, nullable);
-        BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig,
-                statusCodeBinding, isMock);
+        BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig);
         String mainContent = Formatter.format(clientGenerator.generateSyntaxTree()).toSourceCode();
         //Update type definition list with auth related type definitions
         List authNodes = clientGenerator.getBallerinaAuthConfigGenerator()
@@ -445,13 +443,17 @@ private List generateClientFiles(Path openAPI, Filter filter, boolea
         return sourceFiles;
     }
 
-    private static BallerinaClientGenerator getBallerinaClientGenerator(OASClientConfig oasClientConfig,
-                                                                        boolean statusCodeBinding, boolean isMock) {
+    private static BallerinaClientGenerator getBallerinaClientGenerator(OASClientConfig oasClientConfig) {
+        boolean statusCodeBinding = oasClientConfig.isStatusCodeBinding();
+        boolean isMock = oasClientConfig.isMock();
+
         if (statusCodeBinding && isMock) {
             return new AdvanceMockClientGenerator(oasClientConfig);
-        } else if (statusCodeBinding) {
+        }
+        if (statusCodeBinding) {
             return new BallerinaClientGeneratorWithStatusCodeBinding(oasClientConfig);
-        } else if (isMock) {
+        }
+        if (isMock) {
             return new BallerinaMockClientGenerator(oasClientConfig);
         }
         return new BallerinaClientGenerator(oasClientConfig);
diff --git a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal
index 05390ea12..694269aa6 100644
--- a/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal
+++ b/openapi-cli/src/test/resources/generators/client/mock/basic_response_example.bal
@@ -1,7 +1,4 @@
-import ballerina/http;
-
 public isolated client class Client {
-    final http:Client clientEp;
     # Gets invoked to initialize the `connector`.
     #
     # + config - The configurations to be used when initializing the `connector`
diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal
index 8773125ab..b0478e3d9 100644
--- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal
+++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal
@@ -16,6 +16,7 @@ annotation ClientMethodImpl MethodImpl on function;
 type ClientMethodInvocationError http:ClientError;
 
 public isolated client class Client {
+    final http:StatusCodeClient clientEp;
     # Gets invoked to initialize the `connector`.
     #
     # + config - The configurations to be used when initializing the `connector`
diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal
index 29a607577..d7569004f 100644
--- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal
+++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_remote.bal
@@ -1,7 +1,5 @@
-import ballerina/http;
 
 public isolated client class Client {
-    final http:Client clientEp;
     # Gets invoked to initialize the `connector`.
     #
     # + config - The configurations to be used when initializing the `connector`
diff --git a/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal b/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal
index da852245d..2ef4fd7d0 100644
--- a/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal
+++ b/openapi-cli/src/test/resources/generators/client/mock/reference_example.bal
@@ -1,7 +1,4 @@
-import ballerina/http;
-
 public isolated client class Client {
-    final http:Client clientEp;
     final readonly & ApiKeysConfig apiKeyConfig;
     # Gets invoked to initialize the `connector`.
     #
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java
index 0c0649109..28a345418 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java
@@ -18,25 +18,12 @@
 
 package io.ballerina.openapi.core.generators.client;
 
-import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode;
-import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode;
-import io.ballerina.compiler.syntax.tree.FunctionSignatureNode;
-import io.ballerina.compiler.syntax.tree.IdentifierToken;
-import io.ballerina.compiler.syntax.tree.ImportDeclarationNode;
-import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode;
-import io.ballerina.compiler.syntax.tree.ModulePartNode;
+import io.ballerina.compiler.syntax.tree.FunctionBodyNode;
 import io.ballerina.compiler.syntax.tree.NodeList;
 import io.ballerina.compiler.syntax.tree.ReturnStatementNode;
 import io.ballerina.compiler.syntax.tree.StatementNode;
-import io.ballerina.compiler.syntax.tree.SyntaxTree;
-import io.ballerina.compiler.syntax.tree.Token;
-import io.ballerina.openapi.core.generators.client.exception.ClientException;
 import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator;
 import io.ballerina.openapi.core.generators.client.model.OASClientConfig;
-import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException;
-import io.ballerina.openapi.core.generators.document.ClientDocCommentGenerator;
-import io.ballerina.tools.text.TextDocument;
-import io.ballerina.tools.text.TextDocuments;
 import io.swagger.v3.oas.models.OpenAPI;
 import io.swagger.v3.oas.models.Operation;
 import io.swagger.v3.oas.models.PathItem;
@@ -45,21 +32,12 @@
 import java.util.List;
 import java.util.Map;
 
-import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList;
-import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createIdentifierToken;
 import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createNodeList;
 import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken;
 import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode;
-import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionDefinitionNode;
-import static io.ballerina.compiler.syntax.tree.NodeFactory.createModulePartNode;
 import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnStatementNode;
 import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN;
-import static io.ballerina.compiler.syntax.tree.SyntaxKind.EOF_TOKEN;
-import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_DEFINITION;
-import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_KEYWORD;
-import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD;
 import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN;
-import static io.ballerina.compiler.syntax.tree.SyntaxKind.PUBLIC_KEYWORD;
 import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURN_KEYWORD;
 import static io.ballerina.compiler.syntax.tree.SyntaxKind.SEMICOLON_TOKEN;
 
@@ -74,44 +52,14 @@ public AdvanceMockClientGenerator(OASClientConfig oasClientConfig) {
     }
 
     @Override
-    public FunctionDefinitionNode createInitFunction() {
-        FunctionSignatureNode functionSignatureNode = super.getInitFunctionSignatureNode();
-        NodeList qualifierList = createNodeList(createToken(PUBLIC_KEYWORD), createToken(ISOLATED_KEYWORD));
-        IdentifierToken functionName = createIdentifierToken("init");
+    public FunctionBodyNode getInitFunctionBodyNode() {
         List assignmentNodes = new ArrayList<>();
         ReturnStatementNode returnStatementNode = createReturnStatementNode(createToken(
                 RETURN_KEYWORD), null, createToken(SEMICOLON_TOKEN));
         assignmentNodes.add(returnStatementNode);
         NodeList statementList = createNodeList(assignmentNodes);
-        FunctionBodyBlockNode functionBodyNode = createFunctionBodyBlockNode(createToken(OPEN_BRACE_TOKEN),
+        return createFunctionBodyBlockNode(createToken(OPEN_BRACE_TOKEN),
                 null, statementList, createToken(CLOSE_BRACE_TOKEN), null);
-        return createFunctionDefinitionNode(FUNCTION_DEFINITION, super.getInitDocComment(), qualifierList,
-                createToken(FUNCTION_KEYWORD), functionName, createEmptyNodeList(), functionSignatureNode,
-                functionBodyNode);
-    }
-
-    /**
-     * This method for generate the client syntax tree.
-     *
-     * @return return Syntax tree for the ballerina code.
-     * @throws BallerinaOpenApiException When function fail in process.
-     */
-    @Override
-    public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException {
-
-        List importForHttp = getImportDeclarationNodes();
-        imports.addAll(importForHttp);
-        authConfigGeneratorImp.addAuthRelatedRecords(openAPI);
-        List nodes = getModuleMemberDeclarationNodes();
-        NodeList importsList = createNodeList(imports);
-        ModulePartNode modulePartNode =
-                createModulePartNode(importsList, createNodeList(nodes), createToken(EOF_TOKEN));
-        TextDocument textDocument = TextDocuments.from("");
-        SyntaxTree syntaxTree = SyntaxTree.from(textDocument);
-        syntaxTree = syntaxTree.modifyWith(modulePartNode);
-        ClientDocCommentGenerator clientDocCommentGenerator = new ClientDocCommentGenerator(syntaxTree, openAPI,
-                oasClientConfig.isResourceMode());
-        return clientDocCommentGenerator.updateSyntaxTreeWithDocComments();
     }
 
     @Override
diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java
index a30ba3da0..00b55e8a7 100644
--- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java
+++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java
@@ -184,14 +184,13 @@ public BallerinaClientGenerator(OASClientConfig oasClientConfig) {
      * @throws BallerinaOpenApiException When function fail in process.
      */
     public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException {
+        generateHttpImport();
+        return getSyntaxTree();
+    }
 
-        // Create `ballerina/http` import declaration node
-        List importForHttp = getImportDeclarationNodes();
-        imports.addAll(importForHttp);
-
+    SyntaxTree getSyntaxTree() throws ClientException, BallerinaOpenApiException {
         // Add authentication related records
         authConfigGeneratorImp.addAuthRelatedRecords(openAPI);
-
         List nodes = getModuleMemberDeclarationNodes();
         NodeList importsList = createNodeList(imports);
         ModulePartNode modulePartNode =
@@ -205,6 +204,12 @@ public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientE
         return clientDocCommentGenerator.updateSyntaxTreeWithDocComments();
     }
 
+    private void generateHttpImport() {
+        // Create `ballerina/http` import declaration node
+        List importForHttp = getImportDeclarationNodes();
+        imports.addAll(importForHttp);
+    }
+
     protected List getModuleMemberDeclarationNodes() throws BallerinaOpenApiException {
         List nodes = new ArrayList<>();
         // Add class definition node to module member nodes
@@ -241,13 +246,11 @@ public BallerinaUtilGenerator getBallerinaUtilGenerator() {
      * }
      * 
*/ - private ClassDefinitionNode getClassDefinitionNode() { + protected ClassDefinitionNode getClassDefinitionNode() { // Collect members for class definition node List memberNodeList = new ArrayList<>(); // Add instance variable to class definition node - if (!oasClientConfig.isMock()) { - memberNodeList.addAll(createClassInstanceVariables()); - } + memberNodeList.addAll(createClassInstanceVariables()); // Add init function to class definition node memberNodeList.add(createInitFunction()); Map> filteredOperations = filterOperations(); @@ -373,7 +376,7 @@ protected MetadataNode getClassMetadataNode() { * @return {@link FunctionDefinitionNode} Class init function * @throws BallerinaOpenApiException When invalid server URL is provided */ - protected FunctionDefinitionNode createInitFunction() { + FunctionDefinitionNode createInitFunction() { FunctionSignatureNode functionSignatureNode = getInitFunctionSignatureNode(); FunctionBodyNode functionBodyNode = getInitFunctionBodyNode(); @@ -389,7 +392,7 @@ protected FunctionDefinitionNode createInitFunction() { * * @return {@link FunctionBodyNode} */ - private FunctionBodyNode getInitFunctionBodyNode() { + protected FunctionBodyNode getInitFunctionBodyNode() { List assignmentNodes = new ArrayList<>(); @@ -586,8 +589,8 @@ protected QualifiedNameReferenceNode getHttpClientTypeName() { createIdentifierToken(GeneratorConstants.CLIENT)); } - private List createRemoteFunctions(Map> - filteredOperations) { + List createRemoteFunctions(Map> + filteredOperations) { List remoteFunctionNodes = new ArrayList<>(); for (Map.Entry> operation : filteredOperations.entrySet()) { for (Map.Entry operationEntry : operation.getValue().entrySet()) { @@ -632,7 +635,7 @@ protected RemoteFunctionGenerator getRemoteFunctionGenerator(Map.Entry createResourceFunctions(Map createResourceFunctions(Map> filteredOperations) { List resourceFunctionNodes = new ArrayList<>(); for (Map.Entry> operation : filteredOperations.entrySet()) { diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java index 9ab04bea7..b8d9da4b7 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGeneratorWithStatusCodeBinding.java @@ -271,7 +271,7 @@ protected FunctionBodyGenerator getFunctionBodyGeneratorImp(String path, * * @return {@link FunctionDefinitionNode} FunctionDefinitionNode */ - FunctionDefinitionNode getSetModuleFunction() { + private FunctionDefinitionNode getSetModuleFunction() { NodeList emptyQualifiers = createEmptyNodeList(); NodeList emptyNodeList = createEmptyNodeList(); SeparatedNodeList emptyParamList = createSeparatedNodeList(); @@ -306,7 +306,7 @@ FunctionDefinitionNode getSetModuleFunction() { * * @return {@link FunctionDefinitionNode} FunctionDefinitionNode */ - FunctionDefinitionNode getModuleInitFunction() { + private FunctionDefinitionNode getModuleInitFunction() { NodeList emptyQualifiers = createEmptyNodeList(); NodeList emptyNodeList = createEmptyNodeList(); SeparatedNodeList emptyParamList = createSeparatedNodeList(); @@ -334,7 +334,7 @@ FunctionDefinitionNode getModuleInitFunction() { * * @return {@link TypeDefinitionNode} TypeDefinitionNode */ - TypeDefinitionNode getClientMethodImplType() { + private TypeDefinitionNode getClientMethodImplType() { RecordFieldNode nameFieldNode = createRecordFieldNode(null, null, createIdentifierToken("string"), createIdentifierToken("name"), null, createToken(SEMICOLON_TOKEN)); RecordTypeDescriptorNode recordDescriptor = createRecordTypeDescriptorNode(createToken(RECORD_KEYWORD), @@ -352,7 +352,7 @@ TypeDefinitionNode getClientMethodImplType() { * * @return {@link AnnotationDeclarationNode} AnnotationDeclarationNode */ - AnnotationDeclarationNode getMethodImplAnnotation() { + private AnnotationDeclarationNode getMethodImplAnnotation() { return createAnnotationDeclarationNode(null, null, null, createToken(ANNOTATION_KEYWORD), createIdentifierToken("ClientMethodImpl"), createIdentifierToken("MethodImpl"), createToken(ON_KEYWORD), createSeparatedNodeList(createToken(FUNCTION_KEYWORD)), diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java index be7130fb8..ba9a397cb 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java @@ -22,12 +22,10 @@ import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; import io.ballerina.compiler.syntax.tree.FunctionSignatureNode; import io.ballerina.compiler.syntax.tree.IdentifierToken; -import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; import io.ballerina.compiler.syntax.tree.MetadataNode; -import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode; -import io.ballerina.compiler.syntax.tree.ModulePartNode; import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ObjectFieldNode; import io.ballerina.compiler.syntax.tree.ReturnStatementNode; import io.ballerina.compiler.syntax.tree.StatementNode; import io.ballerina.compiler.syntax.tree.SyntaxTree; @@ -37,9 +35,6 @@ import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.GeneratorConstants; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; -import io.ballerina.openapi.core.generators.document.ClientDocCommentGenerator; -import io.ballerina.tools.text.TextDocument; -import io.ballerina.tools.text.TextDocuments; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -55,12 +50,10 @@ import static io.ballerina.compiler.syntax.tree.NodeFactory.createClassDefinitionNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionDefinitionNode; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createModulePartNode; import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnStatementNode; import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLASS_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLIENT_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN; -import static io.ballerina.compiler.syntax.tree.SyntaxKind.EOF_TOKEN; import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_DEFINITION; import static io.ballerina.compiler.syntax.tree.SyntaxKind.FUNCTION_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.ISOLATED_KEYWORD; @@ -95,7 +88,8 @@ public FunctionDefinitionNode getInitFunction() { functionBodyNode); } - public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException { + @Override + public ClassDefinitionNode getClassDefinitionNode() { List memberNodeList = new ArrayList<>(); memberNodeList.addAll(createClassInstanceVariables()); memberNodeList.add(getInitFunction()); @@ -123,31 +117,18 @@ public ClassDefinitionNode getClientFunction() throws BallerinaOpenApiException } @Override - protected List getModuleMemberDeclarationNodes() throws BallerinaOpenApiException { - List nodes = new ArrayList<>(); - nodes.add(getClientFunction()); - return nodes; + public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException { + return getSyntaxTree(); } - /** - * This method for generate the client syntax tree. - * - * @return return Syntax tree for the ballerina code. - * @throws BallerinaOpenApiException When function fail in process. - */ - public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientException { - List importForHttp = getImportDeclarationNodes(); - imports.addAll(importForHttp); - authConfigGeneratorImp.addAuthRelatedRecords(openAPI); - List nodes = getModuleMemberDeclarationNodes(); - NodeList importsList = createNodeList(imports); - ModulePartNode modulePartNode = - createModulePartNode(importsList, createNodeList(nodes), createToken(EOF_TOKEN)); - TextDocument textDocument = TextDocuments.from(""); - SyntaxTree syntaxTree = SyntaxTree.from(textDocument); - syntaxTree = syntaxTree.modifyWith(modulePartNode); - ClientDocCommentGenerator clientDocCommentGenerator = new ClientDocCommentGenerator(syntaxTree, openAPI, - oasClientConfig.isResourceMode()); - return clientDocCommentGenerator.updateSyntaxTreeWithDocComments(); + @Override + public List createClassInstanceVariables() { + List fieldNodeList = new ArrayList<>(); + // add apiKey instance variable when API key security schema is given + ObjectFieldNode apiKeyFieldNode = authConfigGeneratorImp.getApiKeyMapClassVariable(); + if (apiKeyFieldNode != null) { + fieldNodeList.add(apiKeyFieldNode); + } + return fieldNodeList; } } diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java index 284242ecc..3816d1c5e 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/ImplFunctionSignatureGenerator.java @@ -60,18 +60,9 @@ public class ImplFunctionSignatureGenerator { List parameterNodes = new ArrayList<>(); ReturnTypeDescriptorNode returnTypeDescriptorNode; ResourceFunctionSignatureGenerator resourceFunctionSignatureGenerator; - Operation operation; - OpenAPI openAPI; - String path; - String httpMethod; public ImplFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, String httpMethod, String path, FunctionDefinitionNode clientExternFunction) { - this.operation = operation; - this.path = path; - this.httpMethod = httpMethod; - this.openAPI = openAPI; - FunctionSignatureNode functionSignatureNode = clientExternFunction.functionSignature(); if (Objects.isNull(functionSignatureNode)) { return; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java deleted file mode 100644 index 3805bac1c..000000000 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/MockImplFunctionSignatureGenerator.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org). - * - * WSO2 LLC. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package io.ballerina.openapi.core.generators.client; - -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; -import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.TypeDescriptorNode; -import io.ballerina.openapi.core.generators.common.GeneratorConstants; -import io.ballerina.openapi.core.generators.common.exception.InvalidReferenceException; -import io.ballerina.tools.diagnostics.Diagnostic; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.responses.ApiResponse; -import io.swagger.v3.oas.models.responses.ApiResponses; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createEmptyNodeList; -import static io.ballerina.compiler.syntax.tree.AbstractNodeFactory.createToken; -import static io.ballerina.compiler.syntax.tree.NodeFactory.createReturnTypeDescriptorNode; -import static io.ballerina.compiler.syntax.tree.SyntaxKind.RETURNS_KEYWORD; -import static io.ballerina.openapi.core.generators.common.GeneratorUtils.generateStatusCodeTypeInclusionRecord; - -/** - * This class is for generating the mock advance client method signature. - * - * @since 2.1.0 - */ -public class MockImplFunctionSignatureGenerator extends ImplFunctionSignatureGenerator { - List diagnostics = new ArrayList<>(); - public MockImplFunctionSignatureGenerator(Operation operation, OpenAPI openAPI, String httpMethod, String path, - FunctionDefinitionNode clientExternFunction) { - super(operation, openAPI, httpMethod, path, clientExternFunction); - returnTypeDescriptorNode = getReturnTypeDescriptorNode(); - } - - private ReturnTypeDescriptorNode getReturnTypeDescriptorNode() { - ApiResponses responses = operation.getResponses(); - ApiResponse successResponse = null; - String code = null; - for (Map.Entry response : responses.entrySet()) { - if (response.getKey().startsWith("2")) { - code = response.getKey().trim(); - successResponse = response.getValue(); - break; - } - } - if (code == null) { - return null; - } - Optional typeDescriptorNode = populateReturnTypeDesc(code, successResponse); - return typeDescriptorNode.map(descriptorNode -> createReturnTypeDescriptorNode(createToken(RETURNS_KEYWORD), - createEmptyNodeList(), descriptorNode)).orElse(null); - } - - public Optional populateReturnTypeDesc(String responseCode, ApiResponse response) { - String code = GeneratorConstants.HTTP_CODES_DES.get(responseCode); - try { - return Optional.of(generateStatusCodeTypeInclusionRecord(code, response, httpMethod, openAPI, path, - diagnostics)); - } catch (InvalidReferenceException e) { - return Optional.empty(); - } - } - - public List getDiagnostics () { - return diagnostics; - } -} diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java index 65a57a458..6b8844dd7 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/diagnostic/DiagnosticMessages.java @@ -56,8 +56,9 @@ public enum DiagnosticMessages { OAS_CLIENT_114("OAS_CLIENT_114", "the operation: '%s' is skipped in the client generation since only a default" + " response found for the operation which is not supported with status code binding option", DiagnosticSeverity.WARNING), - OAS_CLIENT_115("OAS_CLIENT_115", "the 'default' response for the operation: '%s' is skipped in the client " + - "generation, since it is not supported with status code binding option", DiagnosticSeverity.WARNING), + OAS_CLIENT_115("OAS_CLIENT_115", "the operation for given path `%s` , " + + "method `%s` is skipped in the mock client function generation since it is not provided success response", + DiagnosticSeverity.WARNING), OAS_CLIENT_116("OAS_CLIENT_116", "the operation for given path `%s` , method `%s` is skipped in " + "the mock client function generation since it is not provided with examples", DiagnosticSeverity.WARNING), OAS_CLIENT_117("OAS_CLIENT_117", "the operation for given path `%s` , method `%s` is skipped in " + diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java index 63b1a44b7..c1f2c7028 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockClientFunctionGenerator.java @@ -57,6 +57,7 @@ import static io.ballerina.compiler.syntax.tree.SyntaxKind.REMOTE_KEYWORD; import static io.ballerina.compiler.syntax.tree.SyntaxKind.RESOURCE_ACCESSOR_DEFINITION; import static io.ballerina.compiler.syntax.tree.SyntaxKind.RESOURCE_KEYWORD; +import static io.ballerina.openapi.core.generators.client.diagnostic.DiagnosticMessages.OAS_CLIENT_107; /** * Mock client function generator. @@ -85,7 +86,7 @@ public MockClientFunctionGenerator(String path, Map.Entry generateFunction() throws BallerinaOpenApiException { + public Optional generateFunction() { if (isResourceFunction) { NodeList qualifierList = createNodeList(createToken(RESOURCE_KEYWORD), createToken(ISOLATED_KEYWORD)); @@ -94,8 +95,16 @@ public Optional generateFunction() throws BallerinaOpenA IdentifierToken functionName = createIdentifierToken(method); List pathDiagnostics = new ArrayList<>(); - NodeList relativeResourcePath = GeneratorUtils.getRelativeResourcePath(path, operation.getValue(), - openAPI.getComponents(), false, pathDiagnostics); + NodeList relativeResourcePath; + try { + relativeResourcePath = GeneratorUtils.getRelativeResourcePath(path, operation.getValue(), + openAPI.getComponents(), false, pathDiagnostics); + } catch (BallerinaOpenApiException e) { + DiagnosticMessages diagnosticMessages = OAS_CLIENT_107; + ClientDiagnosticImp clientDiagnosticImp = new ClientDiagnosticImp(diagnosticMessages); + diagnostics.add(clientDiagnosticImp); + return Optional.empty(); + } if (!pathDiagnostics.isEmpty()) { pathDiagnostics.forEach(diagnostic -> { if (diagnostic.diagnosticInfo().code().equals("OAS_COMMON_204")) { diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java index bd50ca7c8..d1b7e0f89 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/MockFunctionBodyGenerator.java @@ -53,6 +53,8 @@ import static io.ballerina.compiler.syntax.tree.NodeFactory.createFunctionBodyBlockNode; import static io.ballerina.compiler.syntax.tree.SyntaxKind.CLOSE_BRACE_TOKEN; import static io.ballerina.compiler.syntax.tree.SyntaxKind.OPEN_BRACE_TOKEN; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.HTTP_201; +import static io.ballerina.openapi.core.generators.common.GeneratorConstants.POST; import static io.ballerina.openapi.core.generators.common.GeneratorConstants.RESPONSE; import static io.ballerina.openapi.core.generators.common.GeneratorUtils.generateStatusCodeTypeInclusionRecord; @@ -80,18 +82,37 @@ public MockFunctionBodyGenerator(String path, Map.Entry getFunctionBodyNode() { ApiResponses responses = operation.getValue().getResponses(); + String method = operation.getKey().toString().toLowerCase(Locale.ENGLISH); //Get the successful response - ApiResponse successResponse = null; - String code = null; + ApiResponse successResponse; + String code; + //Collect all success responses + Map successResponses = new HashMap<>(); for (Map.Entry response : responses.entrySet()) { if (response.getKey().startsWith("2")) { - successResponse = response.getValue(); - code = response.getKey().trim(); - break; + successResponses.put(response.getKey(), response.getValue()); } } + if (successResponses.isEmpty()) { + ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_115, + path, operation.getKey().toString()); + diagnostics.add(diagnosticImp); + return Optional.empty(); + } + if (method.equals(POST) && successResponses.containsKey(HTTP_201)) { + successResponse = successResponses.get(HTTP_201); + code = HTTP_201; + } else { + Optional> firstRes = successResponses.entrySet().stream().findFirst(); + successResponse = firstRes.get().getValue(); + code = firstRes.get().getKey().toLowerCase(Locale.ENGLISH); + } + // Here only consider 2xx response, since this range consider for success status code - if (successResponse == null || successResponse.getContent() == null) { + if (successResponse.getContent() == null) { + ClientDiagnosticImp diagnosticImp = new ClientDiagnosticImp(DiagnosticMessages.OAS_CLIENT_115, + path, operation.getKey().toString()); + diagnostics.add(diagnosticImp); return Optional.empty(); } Map examples = new HashMap<>(); From 001be73d121a605de97402005181f00f36152df0 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 4 Jun 2024 12:17:52 +0530 Subject: [PATCH 13/15] Move mock client generator to package --- .../openapi/bal/tool/OpenAPICodeGeneratorTool.java | 4 ++-- .../io/ballerina/openapi/cmd/BallerinaCodeGenerator.java | 4 ++-- .../generators/client/MockClientGenerationTests.java | 4 ++-- .../core/generators/client/BallerinaClientGenerator.java | 2 +- .../client/{ => mock}/AdvanceMockClientGenerator.java | 8 ++++++-- .../client/{ => mock}/BallerinaMockClientGenerator.java | 4 ++-- 6 files changed, 15 insertions(+), 11 deletions(-) rename openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/{ => mock}/AdvanceMockClientGenerator.java (88%) rename openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/{ => mock}/BallerinaMockClientGenerator.java (98%) diff --git a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java index ed3f1583a..0f6650655 100644 --- a/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java +++ b/openapi-bal-task-plugin/src/main/java/io/ballerina/openapi/bal/tool/OpenAPICodeGeneratorTool.java @@ -19,12 +19,12 @@ import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; import io.ballerina.openapi.bal.tool.Constants.DiagnosticMessages; -import io.ballerina.openapi.core.generators.client.AdvanceMockClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGeneratorWithStatusCodeBinding; -import io.ballerina.openapi.core.generators.client.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; import io.ballerina.openapi.core.generators.client.exception.ClientException; +import io.ballerina.openapi.core.generators.client.mock.AdvanceMockClientGenerator; +import io.ballerina.openapi.core.generators.client.mock.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.TypeHandler; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java index fabb88b4b..4fe8c0d10 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java @@ -20,13 +20,13 @@ import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.openapi.core.generators.client.AdvanceMockClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaClientGeneratorWithStatusCodeBinding; -import io.ballerina.openapi.core.generators.client.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.BallerinaTestGenerator; import io.ballerina.openapi.core.generators.client.diagnostic.ClientDiagnostic; import io.ballerina.openapi.core.generators.client.exception.ClientException; +import io.ballerina.openapi.core.generators.client.mock.AdvanceMockClientGenerator; +import io.ballerina.openapi.core.generators.client.mock.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.GeneratorUtils; import io.ballerina.openapi.core.generators.common.TypeHandler; diff --git a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java index 05470766c..c6b53910a 100644 --- a/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java +++ b/openapi-cli/src/test/java/io/ballerina/openapi/generators/client/MockClientGenerationTests.java @@ -20,9 +20,9 @@ import io.ballerina.compiler.syntax.tree.FunctionBodyNode; import io.ballerina.compiler.syntax.tree.SyntaxTree; -import io.ballerina.openapi.core.generators.client.AdvanceMockClientGenerator; -import io.ballerina.openapi.core.generators.client.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.exception.ClientException; +import io.ballerina.openapi.core.generators.client.mock.AdvanceMockClientGenerator; +import io.ballerina.openapi.core.generators.client.mock.BallerinaMockClientGenerator; import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.TypeHandler; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java index 00b55e8a7..0e0fd1065 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaClientGenerator.java @@ -188,7 +188,7 @@ public SyntaxTree generateSyntaxTree() throws BallerinaOpenApiException, ClientE return getSyntaxTree(); } - SyntaxTree getSyntaxTree() throws ClientException, BallerinaOpenApiException { + protected SyntaxTree getSyntaxTree() throws ClientException, BallerinaOpenApiException { // Add authentication related records authConfigGeneratorImp.addAuthRelatedRecords(openAPI); List nodes = getModuleMemberDeclarationNodes(); diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java similarity index 88% rename from openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java rename to openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java index 28a345418..4ad06e08d 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/AdvanceMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java @@ -16,13 +16,17 @@ * under the License. */ -package io.ballerina.openapi.core.generators.client; +package io.ballerina.openapi.core.generators.client.mock; import io.ballerina.compiler.syntax.tree.FunctionBodyNode; import io.ballerina.compiler.syntax.tree.NodeList; import io.ballerina.compiler.syntax.tree.ReturnStatementNode; import io.ballerina.compiler.syntax.tree.StatementNode; -import io.ballerina.openapi.core.generators.client.mock.MockFunctionBodyGenerator; +import io.ballerina.openapi.core.generators.client.AuthConfigGeneratorImp; +import io.ballerina.openapi.core.generators.client.BallerinaClientGeneratorWithStatusCodeBinding; +import io.ballerina.openapi.core.generators.client.BallerinaUtilGenerator; +import io.ballerina.openapi.core.generators.client.FunctionBodyGenerator; +import io.ballerina.openapi.core.generators.client.ImplFunctionSignatureGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/BallerinaMockClientGenerator.java similarity index 98% rename from openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java rename to openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/BallerinaMockClientGenerator.java index ba9a397cb..1bae074a5 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/BallerinaMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/BallerinaMockClientGenerator.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package io.ballerina.openapi.core.generators.client; +package io.ballerina.openapi.core.generators.client.mock; import io.ballerina.compiler.syntax.tree.ClassDefinitionNode; import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; @@ -30,8 +30,8 @@ import io.ballerina.compiler.syntax.tree.StatementNode; import io.ballerina.compiler.syntax.tree.SyntaxTree; import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.openapi.core.generators.client.BallerinaClientGenerator; import io.ballerina.openapi.core.generators.client.exception.ClientException; -import io.ballerina.openapi.core.generators.client.mock.MockClientFunctionGenerator; import io.ballerina.openapi.core.generators.client.model.OASClientConfig; import io.ballerina.openapi.core.generators.common.GeneratorConstants; import io.ballerina.openapi.core.generators.common.exception.BallerinaOpenApiException; From e838ed2242d294b09fddf91cf5d124f692d34dce Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 4 Jun 2024 12:33:00 +0530 Subject: [PATCH 14/15] [Automated] Update the toml files for client native tests --- openapi-client-native/ballerina-tests/Dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openapi-client-native/ballerina-tests/Dependencies.toml b/openapi-client-native/ballerina-tests/Dependencies.toml index c7db50130..e9cd5368b 100644 --- a/openapi-client-native/ballerina-tests/Dependencies.toml +++ b/openapi-client-native/ballerina-tests/Dependencies.toml @@ -55,7 +55,7 @@ dependencies = [ [[package]] org = "ballerina" name = "crypto" -version = "2.7.1" +version = "2.7.2" dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "time"} @@ -75,7 +75,7 @@ dependencies = [ [[package]] org = "ballerina" name = "http" -version = "2.11.0" +version = "2.11.1" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, From b539504ffeb4dc9a46e96941ce0c2e02e6e72423 Mon Sep 17 00:00:00 2001 From: lnash94 Date: Tue, 4 Jun 2024 14:20:02 +0530 Subject: [PATCH 15/15] Remove unnecessary dependency --- .../openapi/cmd/BallerinaCodeGenerator.java | 1 + .../mock/mock_client_for_advance_return_type.bal | 1 - openapi-core/build.gradle | 1 - .../client/mock/AdvanceMockClientGenerator.java | 13 +++++++++++++ openapi-core/src/main/java/module-info.java | 1 - 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java index 4fe8c0d10..5889adc39 100644 --- a/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java +++ b/openapi-cli/src/main/java/io/ballerina/openapi/cmd/BallerinaCodeGenerator.java @@ -137,6 +137,7 @@ public void generateClientAndService(String definitionPath, String serviceName, .withPlugin(false) .withOpenAPI(openAPIDef) .withResourceMode(isResource) + .withStatusCodeBinding(statusCodeBinding) .withMock(isMock).build(); BallerinaClientGenerator clientGenerator = getBallerinaClientGenerator(oasClientConfig); diff --git a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal index b0478e3d9..8773125ab 100644 --- a/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal +++ b/openapi-cli/src/test/resources/generators/client/mock/mock_client_for_advance_return_type.bal @@ -16,7 +16,6 @@ annotation ClientMethodImpl MethodImpl on function; type ClientMethodInvocationError http:ClientError; public isolated client class Client { - final http:StatusCodeClient clientEp; # Gets invoked to initialize the `connector`. # # + config - The configurations to be used when initializing the `connector` diff --git a/openapi-core/build.gradle b/openapi-core/build.gradle index cd5731a71..53074bbcb 100644 --- a/openapi-core/build.gradle +++ b/openapi-core/build.gradle @@ -32,7 +32,6 @@ configurations { dependencies { implementation project(':ballerina-to-openapi') - implementation "com.fasterxml.jackson.core:jackson-databind" implementation ("io.swagger.parser.v3:swagger-parser:${swaggerParserVersion}") { exclude group: "io.swagger", module: "swagger-compat-spec-parser" exclude group: "org.slf4j", module: "slf4j-ext" diff --git a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java index 4ad06e08d..8ea661804 100644 --- a/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java +++ b/openapi-core/src/main/java/io/ballerina/openapi/core/generators/client/mock/AdvanceMockClientGenerator.java @@ -20,6 +20,7 @@ import io.ballerina.compiler.syntax.tree.FunctionBodyNode; import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ObjectFieldNode; import io.ballerina.compiler.syntax.tree.ReturnStatementNode; import io.ballerina.compiler.syntax.tree.StatementNode; import io.ballerina.openapi.core.generators.client.AuthConfigGeneratorImp; @@ -77,4 +78,16 @@ public FunctionBodyGenerator getFunctionBodyGeneratorImp(String path, ImplFunctionSignatureGenerator signatureGenerator) { return new MockFunctionBodyGenerator(path, operation, openAPI, true); } + + @Override + public List createClassInstanceVariables() { + List fieldNodeList = new ArrayList<>(); + // add apiKey instance variable when API key security schema is given + ObjectFieldNode apiKeyFieldNode = authConfigGeneratorImp.getApiKeyMapClassVariable(); + if (apiKeyFieldNode != null) { + fieldNodeList.add(apiKeyFieldNode); + } + return fieldNodeList; + } + } diff --git a/openapi-core/src/main/java/module-info.java b/openapi-core/src/main/java/module-info.java index 322fdfe99..8c2585f81 100644 --- a/openapi-core/src/main/java/module-info.java +++ b/openapi-core/src/main/java/module-info.java @@ -37,7 +37,6 @@ requires swagger.parser.core; requires swagger.parser.v3; requires org.apache.commons.lang3; - requires com.fasterxml.jackson.databind; exports io.ballerina.openapi.core.generators.common.model; exports io.ballerina.openapi.core.generators.common.exception;