Skip to content

Commit

Permalink
feat: workflow.getRequests (#41)
Browse files Browse the repository at this point in the history
  • Loading branch information
miyajan authored Jul 12, 2020
1 parent f2b3141 commit ede148c
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ See [Error Handling](https://github.com/miyajan/garoon-rest/tree/master/docs/err
## References

- [Schedule](https://github.com/miyajan/garoon-rest/tree/master/docs/schedule.md)
- [Workflow](https://github.com/miyajan/garoon-rest/tree/master/docs/workflow.md)

## Contribution Guide

Expand Down
49 changes: 49 additions & 0 deletions docs/workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Workflow

- [getRequests](#getrequests)

## Overview

```ts
const client = new GaroonRestAPIClient();

(async () => {
try {
console.log(await client.workflow.getRequests());
} catch (error) {
console.log(error);
}
})();
```

- All methods are defined on the `workflow` property.
- This method returns a Promise object that is resolved with an object having properties in each `Returns` section.

## Methods

### getRequests

Get the all request data.

#### Parameters

| Name | Type | Required | Description |
| -------------------- | :--------------: | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| limit | Number | | The number of requests to retrieve.<br />Must be between `1` and `1000`.<br />If nothing is specified, it will default to `100`. |
| offset | Number | | The number of retrievals that will be skipped.<br />Must be between `0` and `2147483647`. If nothing is specified, it will default to `0`. |
| fields | Array\<String\> | | The response properties to get. |
| orderBy | Object | | An object containing data of sort settings. |
| orderBy.property | String | Yes | The property name. Possible values are: `createdAt`. If nothing is specified, it will default to `createdAt`. |
| orderBy.order | String | Yes | The sort order. Possible values are: `asc`, `desc`. If nothing is specified, it will default to `asc`. |
| rangeStartApprovedAt | String | | The start approved datetime for the search. The format is RFC3339. (e.g. `2020-01-01T00:00:00Z`)<br />If `rangeEndApprovedAt` is specified, `rangeStartApprovedAt` must be before the `rangeEndApprovedAt`. |
| rangeEndApprovedAt | String | | The end approved datetime for the search. The format is RFC3339. (e.g. `2020-01-01T00:00:00Z`)<br />If `rangeStartApprovedAt` is specified, `rangeEndApprovedAt` must be later than `rangeStartApprovedAt`. |
| form | Number or String | | The form ID. |
| status | Array\<String\> | | The request status. Possible values are: `UNPROCESSING`, `IN_PROGRESS`, `REJECTED`, `WITHDRAWN`, `SENT_BACK`, `CANCELLED`, `APPROVED`, `COMPLETED`. If nothing is specified, it will default to all statuses. |

#### Returns

See the example response in the `Reference`.

#### Reference

- https://developer.cybozu.io/hc/ja/articles/360031071011#step1
3 changes: 3 additions & 0 deletions src/GaroonRestAPIClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { GaroonErrorResponse, GaroonRestAPIError } from "./GaroonRestAPIError";
import { platformDeps } from "./platform";
import { UnsupportedPlatformError } from "./platform/UnsupportedPlatformError";
import { GaroonRequestConfigBuilder } from "./GaroonRequestConfigBuilder";
import { WorkflowClient } from "./client/WorkflowClient";

export type DiscriminatedAuth = PasswordAuth | SessionAuth | OAuthTokenAuth;

Expand Down Expand Up @@ -93,6 +94,7 @@ const buildDiscriminatedAuth = (auth: Auth): DiscriminatedAuth => {

export class GaroonRestAPIClient {
readonly schedule: ScheduleClient;
readonly workflow: WorkflowClient;
private readonly baseUrl: string;

constructor(options: Options = {}) {
Expand All @@ -109,6 +111,7 @@ export class GaroonRestAPIClient {
requestConfigBuilder,
});
this.schedule = new ScheduleClient(httpClient);
this.workflow = new WorkflowClient(httpClient);
}

public getBaseUrl(): string {
Expand Down
2 changes: 1 addition & 1 deletion src/client/ScheduleClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class ScheduleClient {
}

const { fields, orderBy, excludeFromSearch, ...rest } = params;
const data: any = rest;
const data: Record<string, unknown> = rest as Record<string, unknown>;
if (fields) {
data.fields = fields.join(",");
}
Expand Down
103 changes: 103 additions & 0 deletions src/client/WorkflowClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { HttpClient } from "../http";
import { Item, Operation, Status } from "./types";
import { buildPath } from "../url";

export class WorkflowClient {
private readonly client: HttpClient;

constructor(client: HttpClient) {
this.client = client;
}

public getRequests(params?: {
limit?: number;
offset?: number;
fields?: string[];
orderBy?: {
property: "createdAt";
order: "asc" | "desc";
};
rangeStartApprovedAt?: string;
rangeEndApprovedAt?: string;
form?: string | number;
status?: Status[];
}): Promise<{
requests: Array<{
id: string;
status: {
name: string;
type: Status;
};
createdAt: string;
processingStepCode: string;
name: string;
number: string;
isUrgent: boolean;
applicant: {
id: string;
code: string;
name: string;
proxy?: {
id: string;
code: string;
name: string;
};
};
form: {
id: string;
name: string;
};
items: {
[itemCode: string]: Item;
};
steps: {
[stepCode: string]: {
id: string;
name: string;
requirement: string;
isApprovalStep: 0 | 1;
processors: Array<{
id: string;
code: string;
name: string;
result: string;
date: string;
comment: string;
proxy: {
id: string;
code: string;
name: string;
};
}>;
};
};
availableOperations: {
list: Operation[];
sentBackTargets: string[];
};
folder: Array<{
id: string;
type: "UNPROCESSED" | "SENT" | "RECEIVED" | "DRAFT" | "FINISH";
}>;
}>;
}> {
const path = buildPath({ endpointName: "workflow/admin/requests" });

if (!params) {
return this.client.get(path, {});
}

const { fields, orderBy, status, ...rest } = params;
const data: Record<string, unknown> = rest as Record<string, unknown>;
if (fields) {
data.fields = fields.join(",");
}
if (orderBy) {
data.orderBy = `${orderBy.property} ${orderBy.order}`;
}
if (status) {
data.status = status.join(",");
}
return this.client.get(path, data);
}
}
62 changes: 62 additions & 0 deletions src/client/__tests__/WorkflowClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { MockClient } from "../../http/MockClient";
import { GaroonRequestConfigBuilder } from "../../GaroonRequestConfigBuilder";
import { errorResponseHandler } from "../../GaroonRestAPIClient";
import { WorkflowClient } from "../WorkflowClient";
import { Status } from "../types/workflow";

describe("WorkflowClient", () => {
let mockClient: MockClient;
let workflowClient: WorkflowClient;

beforeEach(() => {
const requestConfigBuilder = new GaroonRequestConfigBuilder({
baseUrl: "https://example.cybozu.com/g",
auth: {
type: "password",
username: "cybozu",
password: "cybozu",
},
});
mockClient = new MockClient({ requestConfigBuilder, errorResponseHandler });
workflowClient = new WorkflowClient(mockClient);
});

describe("getRequests", () => {
const params = {
limit: 100,
offset: 0,
fields: ["id", "number"],
orderBy: {
property: "createdAt" as const,
order: "desc" as const,
},
rangeStartApprovedAt: "2020-01-01T00:00:00Z",
rangeEndApprovedAt: "2020-12-30T00:00:00Z",
form: 1,
status: ["UNPROCESSING" as const, "IN_PROGRESS" as const],
};
beforeEach(async () => {
await workflowClient.getRequests(params);
});
it("should pass the path to the http client", () => {
expect(mockClient.getLogs()[0].path).toBe(
"/api/v1/workflow/admin/requests"
);
});
it("should send a get request", () => {
expect(mockClient.getLogs()[0].method).toBe("get");
});
it("should pass limit, offset, fields, orderBy, rangeStartApprovedAt, rangeEndApprovedAt, form and status as a param to the http client", () => {
expect(mockClient.getLogs()[0].params).toEqual({
limit: 100,
offset: 0,
fields: "id,number",
orderBy: "createdAt desc",
rangeStartApprovedAt: "2020-01-01T00:00:00Z",
rangeEndApprovedAt: "2020-12-30T00:00:00Z",
form: 1,
status: "UNPROCESSING,IN_PROGRESS",
});
});
});
});
1 change: 1 addition & 0 deletions src/client/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./schedule";
export * from "./workflow";
95 changes: 95 additions & 0 deletions src/client/types/workflow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
export type Status =
| "UNPROCESSING"
| "IN_PROGRESS"
| "REJECTED"
| "WITHDRAWN"
| "SENT_BACK"
| "CANCELLED"
| "APPROVED"
| "COMPLETED";
export type Operation =
| "SENT_BACK"
| "APPROVE"
| "REJECT"
| "WITHDRAW"
| "CANCEL"
| "CONFIRM"
| "ACKNOWLEDGE";
export type Item =
| SingleLineTextItem
| MultiLineTextItem
| NumberItem
| CalcItem
| CheckBoxItem
| RadioButtonItem
| DropDownItem
| FileItem
| DateItem
| DateTimeItem
| RouteNaviItem;
export type SingleLineTextItem = {
name: string;
type: "SINGLE_LINE_TEXT";
value: string;
};
export type MultiLineTextItem = {
name: string;
type: "MULTI_LINE_TEXT";
value: string;
};
export type NumberItem = {
name: string;
type: "NUMBER";
value: string;
};
export type CalcItem = {
name: string;
type: "CALC";
value: string;
};
export type CheckBoxItem = {
name: string;
type: "CHECK_BOX";
value: boolean;
};
export type RadioButtonItem = {
name: string;
type: "RADIO_BUTTON";
value: string;
};
export type DropDownItem = {
name: string;
type: "DROP_DOWN";
value: string;
};
export type FileItem = {
name: string;
type: "FILE";
value: Array<{
id: string;
contentType: string;
name: string;
size: string;
}>;
};
export type DateItem = {
name: string;
type: "DATE";
value: string;
};
export type DateTimeItem = {
name: string;
type: "DATETIME";
value: {
date: string;
time: string;
};
};
export type RouteNaviItem = {
name: string;
type: "ROUTE_NAVI";
value: {
route: string;
expense: string;
};
};

0 comments on commit ede148c

Please sign in to comment.