Skip to content

Commit

Permalink
Feature put asset (#3)
Browse files Browse the repository at this point in the history
* Implemented asset put api for update asset

* Resolve linting errors
  • Loading branch information
sammrai authored Dec 3, 2023
1 parent 6e260c7 commit e60a8ba
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 24 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
name: Build docs
on:
push:
branches:
- main
release:
types: [ published ]

jobs:
build:
Expand Down
14 changes: 12 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@ version: '3.8'

services:
app:
build: .
image: sammrai/mfapi:latest
container_name: mfapi
ports:
- 3001:3001
volumes:
- type: bind
source: ./data
target: /data
- type: bind
source: ./config.json
target: /app/config.json
target: /app/config.json
# 開発用
# - type: bind
# source: ./src
# target: /app/src
# build: .
# command: /bin/sh
# tty: true
8 changes: 7 additions & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#!/bin/sh

yarn start || true
while :
do
yarn start || true

echo "Waiting 10s before restarting..."
sleep 10
done
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mfapi",
"version": "0.0.1",
"version": "0.0.2",
"description": "",
"main": "dist/main.js",
"repository": "[email protected]:sammrai/mfapi.git",
Expand Down
4 changes: 2 additions & 2 deletions src/actions/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export abstract class ApiResponseHandler {
try {
const response = await this.axiosInstance.post<U>(url, data);
// console.log("SUCCESS:", response.data);
console.log("Status Code: ", response.status);
console.log("post", url, response.status);
// console.log("Response Headers: ", response.headers);
return response.data;
} catch (error) {
Expand All @@ -58,7 +58,7 @@ export abstract class ApiResponseHandler {
decorator: (cheerio: CheerioAPI) => T
): Promise<T> {
const response = await this.axiosInstance.get(url);
console.log("Status Code: ", response.status);
console.log("get", url, response.status);
// console.log("Response Headers: ", response.headers);
const $ = cheerio.load(response.data);
return decorator($);
Expand Down
32 changes: 30 additions & 2 deletions src/actions/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export class Asset extends ApiResponseHandler {

$('form.form-horizontal[action="/bs/portfolio/edit"]').each((_, form) => {
const formId = $(form).attr("id")?.replace("new_user_asset_det_", "");
const formInputs = $(form).find(".control-group input[id]");
const formInputs = $(form).find("input[id]");
const detail: Partial<AssetModel> = {};

if (formId) {
Expand All @@ -156,6 +156,9 @@ export class Asset extends ApiResponseHandler {
switch (id.replace("user_asset_det_", "")) {
case "sub_account_id_hash":
break;
case "id":
detail.assetId += `@${value}`;
break;
case "temp_asset_subclass_id":
break;
case "asset_subclass_id":
Expand Down Expand Up @@ -190,12 +193,37 @@ export class Asset extends ApiResponseHandler {
accountString: string,
assetId: string
): Promise<void> {
const url = `/bs/portfolio/${assetId}?sub_account_id_hash=${
const url = `/bs/portfolio/${assetId.split("@")[0]}?sub_account_id_hash=${
accountString.split("@")[1]
}`;
const postData = {
_method: "delete",
};
return this.post(url, postData);
}

public async updateAsset(
accountString: string,
assetId: string,
assetSubclassId: AssetSubclass,
assetName: string,
assetValue: number,
assetEntryValue?: number,
assetEntryAt?: Date
): Promise<void> {
const postData = {
_method: "put",
"user_asset_det[id]": assetId.split("@")[1],
"user_asset_det[sub_account_id_hash]": accountString.split("@")[1],
"user_asset_det[asset_subclass_id]": assetSubclassId,
"user_asset_det[name]": assetName,
"user_asset_det[value]": assetValue,
"user_asset_det[entried_price]":
assetEntryValue !== undefined ? assetEntryValue : "",
"user_asset_det[entried_at]": assetEntryAt
? this.formatDate(assetEntryAt)
: "",
};
return this.post("/bs/portfolio/edit", postData);
}
}
45 changes: 38 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,15 @@ async function main() {
app.get(
"/accounts/:accountString/assets",
async (req: Request, res: Response) => {
const { accountString } = req.params;
const portfolios: AssetModel[] = await assetController.getAssets(
accountString
);
res.status(200).json(portfolios);
try {
const { accountString } = req.params;
const portfolios: AssetModel[] = await assetController.getAssets(
accountString
);
res.status(200).json(portfolios);
} catch (error) {
res.status(500).send();
}
}
);

Expand Down Expand Up @@ -110,9 +114,36 @@ async function main() {
try {
const { accountString, assetId } = req.params;
await assetController.deleteAsset(accountString, assetId);
res.status(200).send();
res.status(204).send();
} catch (error) {
const err = error as CustomError;
if (err.status === 500) {
res.status(404).send();
} else {
res.status(500).send();
}
}
}
);

app.put(
"/accounts/:accountString/assets/:assetId",
async (req: Request, res: Response) => {
try {
const { accountString, assetId } = req.params;
const { assetSubclassId, name, value } = req.body;
const _assetSubclassId =
AssetSubclass[assetSubclassId as keyof typeof AssetSubclass];
await assetController.updateAsset(
accountString,
assetId,
_assetSubclassId,
name,
value
);
res.status(204).send();
} catch (error) {
res.status(404).send();
res.status(500).send();
}
}
);
Expand Down
62 changes: 56 additions & 6 deletions src/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
openapi: 3.0.0
info:
title: マネーフォワード操作API
version: 0.0.1
version: 0.0.2
description: |
マネーフォワードME を操作するAPIラッパーを提供。参照系は問題なく動作しますが更新系は更新結果の応答をサイトから得られないため実際に更新できているか確認が必要です。
マネーフォワードMEのデータを操作するためのREST APIです。このAPIは、マネーフォワードMEの資産管理機能を拡張し、プログラムによる自動操作を可能にします。
# ensureオプション(開発中)
現状では、更新系API(追加、更新、削除など)では、2xx応答が返ってきても、それはサイトにリクエストを投げたことを示すだけで、実際に作成、更新、削除が行われたことの保証はされません。そのため、操作後にリソースの状態を確認し、変更が正確に反映されているかを確かめることが重要です。この確認プロセスを効率化するために、`ensure` オプションが推奨されます。`ensure` オプションを有効化すると、操作後にリソースの状態を自動的に確認する追加のリクエストが発行されますが、これにより全体のリクエスト量が増加し、応答時間が遅くなる可能性があります。また、、サイトへの追加的な負荷も考慮に入れる必要があります。クライアントの要件に応じて、`ensure` オプションの使用要否を検討してください。
contact:
url: https://github.com/sammrai/mfapi

servers:
- url: http://192.168.32.70:3001
description: Local server
- url: http://localhost:3000/api
- url: http://localhost:3001/api
description: Local machinie

paths:
Expand Down Expand Up @@ -50,6 +53,8 @@ paths:
type: array
items:
$ref: "#/components/schemas/Asset"
"500":
description: サーバエラー
post:
tags: [資産]
summary: 資産作成
Expand All @@ -71,6 +76,10 @@ paths:
description: 資産を作成しました
"400":
description: 入力パラメータが誤っています
"409":
description: 作成に失敗しました
"500":
description: サーバエラー

/accounts/{accountString}/assets/{assetId}:
delete:
Expand All @@ -90,10 +99,48 @@ paths:
schema:
type: string
responses:
"200":
"204":
description: 資産を削除しました
"409":
description: 削除に失敗しました
"404":
description: 削除する資産が見つかりません
"500":
description: サーバエラー
put:
tags: [資産]
summary: 資産変更
parameters:
- name: assetId
description: 資産の一意識別子
in: path
required: true
schema:
type: string
- name: accountString
description: 口座の接続文字列
in: path
required: true
schema:
type: string
requestBody:
description: assetSubclassIdは変更することができず、変更前と同じにする必要があります。
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/AssetPost"
responses:
"204":
description: 資産を更新しました
"400":
description: 入力パラメータが誤っています
"404":
description: 更新する資産が見つかりません
"409":
description: 更新に失敗しました
"500":
description: サーバエラー

components:
schemas:
Expand All @@ -103,7 +150,7 @@ components:
assetId:
type: string
description: 資産のユニーク識別子
example: "3GF7x1J_fYqVP90bzOT9CQ3gW-rwRV7PpNpjg1u3CEI"
example: "rwR7x1J_fYqVP90bV7PpN3GFzOT9CQ3gW-pjg1u3CEI"
assetSubclassId:
$ref: "#/components/schemas/AssetSubclass"
name:
Expand All @@ -123,7 +170,6 @@ components:
nullable: true
entriedAt:
type: string
format: string
description: システム登録日
example: "2022/01/01"
nullable: true
Expand Down Expand Up @@ -208,12 +254,16 @@ components:
name:
type: string
description: 口座の名前
example: カスタムテスト口座名
id:
type: string
description: 口座の一意識別子
example: 1oSPZ6UHFklEcqxptwmUi8AsOLXZ-c895CO9eXbmo9j
subAccountIdHash:
type: string
description: 口座制御の一意識別子
example: Slt9Ua10VeSgHLsvDDxmuHwNrufWSVgUc8Ntzl1yNxL
accountString:
type: string
description: 口座の接続文字列
example: 1oSPZ6UHFklEcqxptwmUi8AsOLXZ-c895CO9eXbmo9j@Slt9Ua10VeSgHLsvDDxmuHwNrufWSVgUc8Ntzl1yNxL

0 comments on commit e60a8ba

Please sign in to comment.