From deac6e64f7a3e6c44b820822e73c6ae443627bd9 Mon Sep 17 00:00:00 2001 From: Ashutosh Muley <58973401+muleyashutosh@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:13:52 +0530 Subject: [PATCH] feat: added POST `/admin/expenses` API (#377) * feat: added POST /admin/expenses API * Auto generate API docs * added tax_amount cannot be greater than expense amount note * Auto generate API docs --------- Co-authored-by: Siva --- reference/admin.yaml | 245 ++++++++++++++++++++++------ reference/approver.yaml | 10 +- reference/spender.yaml | 20 ++- src/admin/paths/admin@expenses.yaml | 88 +++++----- src/components/schemas/expense.yaml | 121 ++++++++++++-- 5 files changed, 367 insertions(+), 117 deletions(-) diff --git a/reference/admin.yaml b/reference/admin.yaml index fc1281cc1..8bacff1d6 100644 --- a/reference/admin.yaml +++ b/reference/admin.yaml @@ -3385,7 +3385,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organisation. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' @@ -3732,6 +3735,147 @@ components: nullable: true description: | Signifies if and when report of this expense was approved. + source: + type: string + enum: + - WEBAPP + - SLACK + - TPA + - CORPORATE_CARD + description: | + Enum value signifying the client from which this expense was created + example: SLACK + is_reimbursable: + type: boolean + nullable: true + description: This field marks whether a given expense is reimbursable or not. + example: true + distance: + type: number + nullable: true + description: Actual distance travelled by employee in travel related expenses. + distance_unit: + type: string + nullable: true + description: Unit of distance travelled. + enum: + - KM + - MILES + example: MILES + travel_classes: + description: | + This field is applicable only for `Flight`, `Train`, `Bus` category. + Index 0 holds onward journey travel class, index 1 holds return journey travel class. + type: array + minItems: 0 + maxItems: 2 + nullable: true + items: + type: string + example: + - ECONOMY + - BUSINESS + locations: + description: | + This field will be present for travel related categories. + For travel between Place A to Place B, this array will contain two items. From location at array index i and To location at array index i+1. + type: array + nullable: true + minItems: 0 + maxItems: 10 + items: + $ref: '#/components/schemas/location' + admin_expense_in: + type: object + additionalProperties: false + required: + - admin_amount + - spent_at + - assignee_user_email + properties: + id: + allOf: + - $ref: '#/components/schemas/id_string' + description: | + This id is provided by Fyle to identify an object + - When `id` is sent, default action is to update the expense + admin_amount: + type: number + nullable: false + description: | + The expense amount which is added or modified by admin or approver. + example: 1900 + spent_at: + $ref: '#/components/schemas/spent_at' + assignee_user_email: + allOf: + - $ref: '#/components/schemas/email' + description: | + An immutable field that represents the email address of the employee. + Must be compliant with RFC + 822. + - _Note:_ + - The expense will be assigned/re-assigned to this particular `employee`. _Not required when updating an expense, but is non-nullable_. + - Admins can't assign the expense to self. + source: + $ref: '#/components/schemas/source' + merchant: + $ref: '#/components/schemas/merchant' + foreign_currency: + $ref: '#/components/schemas/foreign_currency' + foreign_amount: + $ref: '#/components/schemas/foreign_amount' + purpose: + type: string + example: Team lunch + cost_center_id: + allOf: + - $ref: '#/components/schemas/fk_integer' + nullable: true + example: 1049 + category_id: + allOf: + - $ref: '#/components/schemas/fk_integer' + nullable: true + example: 49058 + project_id: + allOf: + - $ref: '#/components/schemas/fk_integer' + nullable: true + example: 92895 + source_account_id: + allOf: + - $ref: '#/components/schemas/fk_string' + example: acwbl222wlg + tax_amount: + type: number + nullable: true + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. + tax_group_id: + allOf: + - $ref: '#/components/schemas/fk_string' + nullable: true + is_billable: + $ref: '#/components/schemas/is_billable' + is_reimbursable: + $ref: '#/components/schemas/is_reimbursable' + distance: + $ref: '#/components/schemas/distance' + distance_unit: + $ref: '#/components/schemas/distance_unit' + started_at: + $ref: '#/components/schemas/timestamptz_pst' + ended_at: + $ref: '#/components/schemas/timestamptz_pst' + travel_classes: + $ref: '#/components/schemas/travel_classes' + locations: + $ref: '#/components/schemas/locations' + custom_fields: + $ref: '#/components/schemas/custom_fields' expense_assign_in: type: object required: @@ -9408,10 +9552,6 @@ components: - LIFETIME - null example: MONTHLY - distance: - type: number - nullable: true - description: Actual distance travelled by employee in travel related expenses. contains_operator: nullable: true type: string @@ -11557,57 +11697,11 @@ components: properties: id: $ref: '#/components/schemas/id_string' - source: - type: string - enum: - - WEBAPP - - SLACK - - TPA - - CORPORATE_CARD - description: | - Enum value signifying the client from which this expense was created - example: SLACK claim_amount: type: number description: | The expense amount as claimed by user. example: 1984.18 - is_reimbursable: - type: boolean - nullable: true - description: This field marks whether a given expense is reimbursable or not. - example: true - distance_unit: - type: string - nullable: true - description: Unit of distance travelled. - enum: - - KM - - MILES - example: MILES - travel_classes: - description: | - This field is applicable only for `Flight`, `Train`, `Bus` category. - Index 0 holds onward journey travel class, index 1 holds return journey travel class. - type: array - minItems: 0 - maxItems: 2 - nullable: true - items: - type: string - example: - - ECONOMY - - BUSINESS - locations: - description: | - This field will be present for travel related categories. - For travel between Place A to Place B, this array will contain two items. From location at array index i and To location at array index i+1. - type: array - nullable: true - minItems: 0 - maxItems: 10 - items: - $ref: '#/components/schemas/location' spender_expense_check_mandatory_fields_in: type: object additionalProperties: false @@ -11665,7 +11759,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' @@ -14530,6 +14627,50 @@ paths: application/json: schema: $ref: '#/components/schemas/401' + post: + tags: + - Expenses + summary: Create or update an expense + description: | + Create or update an expense. + operationId: expenses_post + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + data: + $ref: '#/components/schemas/admin_expense_in' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + data: + $ref: '#/components/schemas/expense_out' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/400' + '401': + description: Unauthorized request + content: + application/json: + schema: + $ref: '#/components/schemas/401' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/403' /admin/expenses/assign: post: tags: diff --git a/reference/approver.yaml b/reference/approver.yaml index 85514fc63..24a5e0bf9 100644 --- a/reference/approver.yaml +++ b/reference/approver.yaml @@ -1459,7 +1459,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organisation. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' @@ -2357,7 +2360,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' diff --git a/reference/spender.yaml b/reference/spender.yaml index c860e66f8..db0fb1c51 100644 --- a/reference/spender.yaml +++ b/reference/spender.yaml @@ -1603,7 +1603,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organisation. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' @@ -2051,7 +2054,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' @@ -5849,7 +5855,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' @@ -6110,7 +6119,10 @@ components: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: '#/components/schemas/fk_string' diff --git a/src/admin/paths/admin@expenses.yaml b/src/admin/paths/admin@expenses.yaml index 3c3d4e33f..e35f8b7c6 100644 --- a/src/admin/paths/admin@expenses.yaml +++ b/src/admin/paths/admin@expenses.yaml @@ -35,47 +35,47 @@ get: application/json: schema: $ref: '../../components/schemas/401.yaml' -# post: -# tags: -# - Expenses -# summary: Create or update an expense -# description: | -# Create or update an expense. -# operationId: expenses_post -# requestBody: -# required: true -# content: -# application/json: -# schema: -# type: object -# properties: -# data: -# $ref: '../../components/schemas/expense.yaml#/admin_expense_in' -# responses: -# '200': -# description: OK -# content: -# application/json: -# schema: -# type: object -# properties: -# data: -# $ref: '../../components/schemas/expense.yaml#/expense_out' -# '400': -# description: Bad request -# content: -# application/json: -# schema: -# $ref: '../../components/schemas/400.yaml' -# '401': -# description: Unauthorized request -# content: -# application/json: -# schema: -# $ref: '../../components/schemas/401.yaml' -# '403': -# description: Forbidden -# content: -# application/json: -# schema: -# $ref: '../../components/schemas/403.yaml' +post: + tags: + - Expenses + summary: Create or update an expense + description: | + Create or update an expense. + operationId: expenses_post + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + data: + $ref: '../../components/schemas/expense.yaml#/admin_expense_in' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + data: + $ref: '../../components/schemas/expense.yaml#/expense_out' + '400': + description: Bad request + content: + application/json: + schema: + $ref: '../../components/schemas/400.yaml' + '401': + description: Unauthorized request + content: + application/json: + schema: + $ref: '../../components/schemas/401.yaml' + '403': + description: Forbidden + content: + application/json: + schema: + $ref: '../../components/schemas/403.yaml' diff --git a/src/components/schemas/expense.yaml b/src/components/schemas/expense.yaml index b9460f3c0..c188ae6b3 100644 --- a/src/components/schemas/expense.yaml +++ b/src/components/schemas/expense.yaml @@ -184,7 +184,10 @@ expense_out: tax_amount: type: number nullable: true - description: Tax amount as setup by your organisation. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: './fields.yaml#/fk_string' @@ -735,7 +738,10 @@ spender_expense_in: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: './fields.yaml#/fk_string' @@ -760,17 +766,96 @@ spender_expense_in: $ref: './fields.yaml#/custom_fields' admin_expense_in: - allOf: - - type: object - required: [ 'admin_amount', 'user_id' ] - properties: - admin_amount: - $ref: './fields.yaml#/amount' - user_id: - allOf: - - $ref: './fields.yaml#/user_id' - readOnly: false - - $ref: '#/expense_in' + type: object + additionalProperties: false + required: + - admin_amount + - spent_at + - assignee_user_email + properties: + id: + allOf: + - $ref: './fields.yaml#/id_string' + description: | + This id is provided by Fyle to identify an object + - When `id` is sent, default action is to update the expense + admin_amount: + type: number + nullable: false + description: | + The expense amount which is added or modified by admin or approver. + example: 1900 + spent_at: + $ref: './fields.yaml#/spent_at' + assignee_user_email: + allOf: + - $ref: './fields.yaml#/email' + description: | + An immutable field that represents the email address of the employee. + Must be compliant with RFC + 822. + - _Note:_ + - The expense will be assigned/re-assigned to this particular `employee`. _Not required when updating an expense, but is non-nullable_. + - Admins can't assign the expense to self. + source: + $ref: './fields.yaml#/source' + merchant: + $ref: './fields.yaml#/merchant' + foreign_currency: + $ref: './fields.yaml#/foreign_currency' + foreign_amount: + $ref: './fields.yaml#/foreign_amount' + purpose: + type: string + example: Team lunch + cost_center_id: + allOf: + - $ref: './fields.yaml#/fk_integer' + nullable: true + example: 1049 + category_id: + allOf: + - $ref: './fields.yaml#/fk_integer' + nullable: true + example: 49058 + project_id: + allOf: + - $ref: './fields.yaml#/fk_integer' + nullable: true + example: 92895 + source_account_id: + allOf: + - $ref: './fields.yaml#/fk_string' + example: acwbl222wlg + tax_amount: + type: number + nullable: true + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. + tax_group_id: + allOf: + - $ref: './fields.yaml#/fk_string' + nullable: true + is_billable: + $ref: './fields.yaml#/is_billable' + is_reimbursable: + $ref: './fields.yaml#/is_reimbursable' + distance: + $ref: './fields.yaml#/distance' + distance_unit: + $ref: './fields.yaml#/distance_unit' + started_at: + $ref: './fields.yaml#/timestamptz_pst' + ended_at: + $ref: './fields.yaml#/timestamptz_pst' + travel_classes: + $ref: './fields.yaml#/travel_classes' + locations: + $ref: './fields.yaml#/locations' + custom_fields: + $ref: './fields.yaml#/custom_fields' expense_out_embed: type: object @@ -1082,7 +1167,10 @@ expense_check_policies_in: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: './fields.yaml#/fk_string' @@ -1301,7 +1389,10 @@ spender_expense_check_mandatory_fields_in: tax_amount: type: number nullable: true - description: Tax amount as setup by your organization. + description: | + Tax amount as setup by your organization. + - _Note:_ + - Tax amount cannot be greater than the expense amount. tax_group_id: allOf: - $ref: './fields.yaml#/fk_string'