From 476473b7297edd4c11d24bfebbe049fd959ab908 Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Wed, 4 Nov 2026 14:16:08 +0300 Subject: [PATCH] refactor(api): consume bank operation oneOf contract (WealthLedger/frontend#144) --- .../card/ui/OperationForm/OperationForm.vm.ts | 49 +++- src/shared/api/generated/schema.d.ts | 96 ++++-- src/shared/api/spec/openapi.json | 276 +++++++++++++----- 3 files changed, 321 insertions(+), 100 deletions(-) diff --git a/src/pages/card/ui/OperationForm/OperationForm.vm.ts b/src/pages/card/ui/OperationForm/OperationForm.vm.ts index bae39b7..e91139d 100644 --- a/src/pages/card/ui/OperationForm/OperationForm.vm.ts +++ b/src/pages/card/ui/OperationForm/OperationForm.vm.ts @@ -120,11 +120,52 @@ const useOperationFormVm = (props: OperationFormProps) => { body: { ...body, version }, id: props.operation.id, }); - else - await operationCreation.mutateAsync({ + else { + const base = { + amount: body.amount, + cardId: values.cardId, + date: values.date, + description: values.description, id: intent, - ...body, - }); + }; + + switch (values.kind) { + case "expense": { + await operationCreation.mutateAsync({ + ...base, + categoryId: values.categoryId || defaultCategoryId, + kind: values.kind, + }); + break; + } + + case "refund": { + await operationCreation.mutateAsync({ + ...base, + kind: values.kind, + originalExpenseId: values.originalExpenseId, + }); + break; + } + + case "topup": { + await operationCreation.mutateAsync({ + ...base, + kind: values.kind, + }); + break; + } + + case "transfer": { + await operationCreation.mutateAsync({ + ...base, + kind: values.kind, + targetCardId: values.targetCardId, + }); + break; + } + } + } notifications.show({ id: "bank-operation-saved-" + actionId, diff --git a/src/shared/api/generated/schema.d.ts b/src/shared/api/generated/schema.d.ts index 897caf0..05ca2e8 100644 --- a/src/shared/api/generated/schema.d.ts +++ b/src/shared/api/generated/schema.d.ts @@ -775,6 +775,77 @@ export interface components { */ password: string; }; + RubMoneyInputDto: { + /** @enum {string} */ + currency: "RUB"; + value: string; + }; + CreateExpenseOperationDto: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + cardId: string; + amount: components["schemas"]["RubMoneyInputDto"]; + /** Format: date */ + date: string; + description?: string; + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + kind: "expense"; + /** Format: uuid */ + categoryId?: string; + }; + CreateTopupOperationDto: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + cardId: string; + amount: components["schemas"]["RubMoneyInputDto"]; + /** Format: date */ + date: string; + description?: string; + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + kind: "topup"; + }; + CreateTransferOperationDto: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + cardId: string; + amount: components["schemas"]["RubMoneyInputDto"]; + /** Format: date */ + date: string; + description?: string; + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + kind: "transfer"; + /** Format: uuid */ + targetCardId: string; + }; + CreateRefundOperationDto: { + /** Format: uuid */ + id: string; + /** Format: uuid */ + cardId: string; + amount: components["schemas"]["RubMoneyInputDto"]; + /** Format: date */ + date: string; + description?: string; + /** + * @description discriminator enum property added by openapi-typescript + * @enum {string} + */ + kind: "refund"; + /** Format: uuid */ + originalExpenseId: string; + }; MoneyDto: { currency: string; value: string; @@ -792,11 +863,6 @@ export interface components { archivedAt: string | null; version: number; }; - RubMoneyInputDto: { - /** @enum {string} */ - currency: "RUB"; - value: string; - }; CreateBankCardDto: { /** Format: uuid */ id: string; @@ -841,24 +907,6 @@ export interface components { net: components["schemas"]["MoneyDto"]; categories: components["schemas"]["BankSummaryCategoryDto"][]; }; - CreateBankOperationDto: { - /** Format: uuid */ - id: string; - /** @enum {string} */ - kind: "expense" | "topup" | "transfer" | "refund"; - /** Format: uuid */ - cardId: string; - /** Format: uuid */ - targetCardId?: string; - /** Format: uuid */ - categoryId?: string; - /** Format: uuid */ - originalExpenseId?: string; - amount: components["schemas"]["RubMoneyInputDto"]; - /** Format: date */ - date: string; - description?: string; - }; BankOperationDto: { id: string; /** @enum {string} */ @@ -2598,7 +2646,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CreateBankOperationDto"]; + "application/json": components["schemas"]["CreateExpenseOperationDto"] | components["schemas"]["CreateTopupOperationDto"] | components["schemas"]["CreateTransferOperationDto"] | components["schemas"]["CreateRefundOperationDto"]; }; }; responses: { diff --git a/src/shared/api/spec/openapi.json b/src/shared/api/spec/openapi.json index b5b5e6c..128b737 100644 --- a/src/shared/api/spec/openapi.json +++ b/src/shared/api/spec/openapi.json @@ -1053,7 +1053,29 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateBankOperationDto" + "oneOf": [ + { + "$ref": "#/components/schemas/CreateExpenseOperationDto" + }, + { + "$ref": "#/components/schemas/CreateTopupOperationDto" + }, + { + "$ref": "#/components/schemas/CreateTransferOperationDto" + }, + { + "$ref": "#/components/schemas/CreateRefundOperationDto" + } + ], + "discriminator": { + "propertyName": "kind", + "mapping": { + "expense": "#/components/schemas/CreateExpenseOperationDto", + "topup": "#/components/schemas/CreateTopupOperationDto", + "transfer": "#/components/schemas/CreateTransferOperationDto", + "refund": "#/components/schemas/CreateRefundOperationDto" + } + } } } } @@ -5340,6 +5362,187 @@ "password" ] }, + "RubMoneyInputDto": { + "type": "object", + "properties": { + "currency": { + "type": "string", + "enum": [ + "RUB" + ] + }, + "value": { + "type": "string", + "pattern": "^-?[0-9]+(\\.[0-9]{1,2})?$" + } + }, + "required": [ + "currency", + "value" + ] + }, + "CreateExpenseOperationDto": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "cardId": { + "type": "string", + "format": "uuid" + }, + "amount": { + "$ref": "#/components/schemas/RubMoneyInputDto" + }, + "date": { + "type": "string", + "format": "date" + }, + "description": { + "type": "string", + "maxLength": 500 + }, + "kind": { + "type": "string", + "enum": [ + "expense" + ] + }, + "categoryId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "id", + "cardId", + "amount", + "date", + "kind" + ] + }, + "CreateTopupOperationDto": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "cardId": { + "type": "string", + "format": "uuid" + }, + "amount": { + "$ref": "#/components/schemas/RubMoneyInputDto" + }, + "date": { + "type": "string", + "format": "date" + }, + "description": { + "type": "string", + "maxLength": 500 + }, + "kind": { + "type": "string", + "enum": [ + "topup" + ] + } + }, + "required": [ + "id", + "cardId", + "amount", + "date", + "kind" + ] + }, + "CreateTransferOperationDto": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "cardId": { + "type": "string", + "format": "uuid" + }, + "amount": { + "$ref": "#/components/schemas/RubMoneyInputDto" + }, + "date": { + "type": "string", + "format": "date" + }, + "description": { + "type": "string", + "maxLength": 500 + }, + "kind": { + "type": "string", + "enum": [ + "transfer" + ] + }, + "targetCardId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "id", + "cardId", + "amount", + "date", + "kind", + "targetCardId" + ] + }, + "CreateRefundOperationDto": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "cardId": { + "type": "string", + "format": "uuid" + }, + "amount": { + "$ref": "#/components/schemas/RubMoneyInputDto" + }, + "date": { + "type": "string", + "format": "date" + }, + "description": { + "type": "string", + "maxLength": 500 + }, + "kind": { + "type": "string", + "enum": [ + "refund" + ] + }, + "originalExpenseId": { + "type": "string", + "format": "uuid" + } + }, + "required": [ + "id", + "cardId", + "amount", + "date", + "kind", + "originalExpenseId" + ] + }, "MoneyDto": { "type": "object", "properties": { @@ -5411,25 +5614,6 @@ "version" ] }, - "RubMoneyInputDto": { - "type": "object", - "properties": { - "currency": { - "type": "string", - "enum": [ - "RUB" - ] - }, - "value": { - "type": "string", - "pattern": "^-?[0-9]+(\\.[0-9]{1,2})?$" - } - }, - "required": [ - "currency", - "value" - ] - }, "CreateBankCardDto": { "type": "object", "properties": { @@ -5599,58 +5783,6 @@ "categories" ] }, - "CreateBankOperationDto": { - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uuid" - }, - "kind": { - "type": "string", - "enum": [ - "expense", - "topup", - "transfer", - "refund" - ] - }, - "cardId": { - "type": "string", - "format": "uuid" - }, - "targetCardId": { - "type": "string", - "format": "uuid" - }, - "categoryId": { - "type": "string", - "format": "uuid" - }, - "originalExpenseId": { - "type": "string", - "format": "uuid" - }, - "amount": { - "$ref": "#/components/schemas/RubMoneyInputDto" - }, - "date": { - "type": "string", - "format": "date" - }, - "description": { - "type": "string", - "maxLength": 500 - } - }, - "required": [ - "id", - "kind", - "cardId", - "amount", - "date" - ] - }, "BankOperationDto": { "type": "object", "properties": { -- 2.54.0