gm-mcp 2.0.6 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ const tools_1 = require("./tools");
20
20
  const zod_1 = __importDefault(require("zod"));
21
21
  const env_1 = require("./env");
22
22
  const lark_tool_1 = require("./tools/lark-tool");
23
- const accessible_tools_1 = require("./tools/accessible-tools");
23
+ const eligibility_tools_1 = require("./tools/eligibility-tools");
24
24
  exports.server = new mcp_js_1.McpServer({
25
25
  name: "mcp-server",
26
26
  version: "1.0.0",
@@ -85,7 +85,7 @@ exports.server.tool("check_eligibility", "Check customer's eligibility for salar
85
85
  phone_number: zod_1.default.string({ description: "Customer's phone number" }),
86
86
  }, (args) => __awaiter(void 0, void 0, void 0, function* () {
87
87
  const { phone_number } = args;
88
- return (0, accessible_tools_1.accessibleTool)(phone_number);
88
+ return (0, eligibility_tools_1.elgibilityTool)(phone_number);
89
89
  }));
90
90
  function bootstap() {
91
91
  (0, env_1.ensureEnvVariables)();
@@ -1,15 +1,30 @@
1
1
  import { Gimo } from "./types";
2
- import { PayPeriod } from "./types/pay-period";
2
+ import { PayPeriod, PayperiodInfo } from "./types/pay-period";
3
3
  import { TimeSheet } from "./types/time-keeper";
4
+ import { CustomerEwaStatusChangeLogs } from "./types/status-change";
4
5
  export declare function getAccessToken(): Promise<string>;
5
- export declare function findCustomerEWAByPhonenumber(phoneNumber: string): Promise<Gimo.CustomerEWA | null>;
6
+ export declare function findCustomerEWAByPhonenumber(phoneNumber: string, options?: {
7
+ accessToken?: string;
8
+ }): Promise<Gimo.CustomerEWA | null>;
6
9
  export declare function getPayPeriods(params: {
7
10
  orgId: number;
8
11
  parnterId: number;
12
+ }, options?: {
13
+ accessToken?: string;
9
14
  }): Promise<PayPeriod[]>;
10
15
  export declare function getTimeSheets(params: {
11
16
  payPeriodId: number;
12
17
  employeeId: number;
18
+ }, options?: {
19
+ accessToken?: string;
13
20
  }): Promise<TimeSheet[]>;
14
- export declare function getEmployeeByCustomerId(customerId: number): Promise<Gimo.EmployeeInfo>;
21
+ export declare function getEmployeeByCustomerId(customerId: number, options?: {
22
+ accessToken?: string;
23
+ }): Promise<Gimo.EmployeeInfo>;
15
24
  export declare function findCustomerEWAById(id: number): Promise<Gimo.CustomerEWA>;
25
+ export declare function getCustomerStatusChange(ewaCustomerId: number, options?: {
26
+ accessToken?: string;
27
+ }): Promise<CustomerEwaStatusChangeLogs[]>;
28
+ export declare function getCurrentPayperiodInfo(payPeriodId: number, options?: {
29
+ accessToken?: string;
30
+ }): Promise<PayperiodInfo>;
@@ -18,6 +18,8 @@ exports.getPayPeriods = getPayPeriods;
18
18
  exports.getTimeSheets = getTimeSheets;
19
19
  exports.getEmployeeByCustomerId = getEmployeeByCustomerId;
20
20
  exports.findCustomerEWAById = findCustomerEWAById;
21
+ exports.getCustomerStatusChange = getCustomerStatusChange;
22
+ exports.getCurrentPayperiodInfo = getCurrentPayperiodInfo;
21
23
  const axios_1 = __importDefault(require("axios"));
22
24
  const env_1 = require("../env");
23
25
  function getAccessToken() {
@@ -31,10 +33,15 @@ function getAccessToken() {
31
33
  .then((res) => res.data.access_token);
32
34
  });
33
35
  }
34
- function findCustomerEWAByPhonenumber(phoneNumber) {
36
+ function findCustomerEWAByPhonenumber(phoneNumber, options) {
35
37
  return __awaiter(this, void 0, void 0, function* () {
38
+ const { accessToken } = options || {};
39
+ let access_token = accessToken;
40
+ if (!access_token) {
41
+ access_token = yield getAccessToken();
42
+ }
36
43
  const customerApiUrl = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/customers/ewa/pagination`;
37
- const access_token = yield getAccessToken();
44
+ // const access_token = await getAccessToken();
38
45
  // Find inlist
39
46
  const customers = yield axios_1.default
40
47
  .get(customerApiUrl, {
@@ -53,11 +60,16 @@ function findCustomerEWAByPhonenumber(phoneNumber) {
53
60
  return findCustomerEWAById(foundedCustomer.customer_id);
54
61
  });
55
62
  }
56
- function getPayPeriods(params) {
63
+ function getPayPeriods(params, options) {
57
64
  return __awaiter(this, void 0, void 0, function* () {
58
65
  const { orgId, parnterId } = params;
66
+ const { accessToken } = options || {};
67
+ let access_token = accessToken;
68
+ if (!access_token) {
69
+ access_token = yield getAccessToken();
70
+ }
59
71
  const url = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/partners/${parnterId}/pay-periods`;
60
- const access_token = yield getAccessToken();
72
+ // const access_token = await getAccessToken();
61
73
  const customer = yield axios_1.default
62
74
  .get(url, {
63
75
  headers: {
@@ -73,11 +85,15 @@ function getPayPeriods(params) {
73
85
  return customer || null;
74
86
  });
75
87
  }
76
- function getTimeSheets(params) {
88
+ function getTimeSheets(params, options) {
77
89
  return __awaiter(this, void 0, void 0, function* () {
78
90
  const { payPeriodId, employeeId } = params;
91
+ const { accessToken } = options || {};
92
+ let access_token = accessToken;
93
+ if (!access_token) {
94
+ access_token = yield getAccessToken();
95
+ }
79
96
  const url = `${(0, env_1.getEnv)().DASH_URL}/api/v2/admin/time-sheets/by-period`;
80
- const access_token = yield getAccessToken();
81
97
  const customer = yield axios_1.default
82
98
  .get(url, {
83
99
  headers: {
@@ -93,10 +109,14 @@ function getTimeSheets(params) {
93
109
  return customer || null;
94
110
  });
95
111
  }
96
- function getEmployeeByCustomerId(customerId) {
112
+ function getEmployeeByCustomerId(customerId, options) {
97
113
  return __awaiter(this, void 0, void 0, function* () {
114
+ const { accessToken } = options || {};
115
+ let access_token = accessToken;
116
+ if (!access_token) {
117
+ access_token = yield getAccessToken();
118
+ }
98
119
  const url = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/customers/${customerId}/employee-info`;
99
- const access_token = yield getAccessToken();
100
120
  const customer = yield axios_1.default
101
121
  .get(url, {
102
122
  headers: {
@@ -124,3 +144,41 @@ function findCustomerEWAById(id) {
124
144
  return customer || null;
125
145
  });
126
146
  }
147
+ function getCustomerStatusChange(ewaCustomerId, options) {
148
+ return __awaiter(this, void 0, void 0, function* () {
149
+ const { accessToken } = options || {};
150
+ let access_token = accessToken;
151
+ if (!access_token) {
152
+ access_token = yield getAccessToken();
153
+ }
154
+ const url = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/customers/ewa/${ewaCustomerId}/status/changes`;
155
+ const res = yield axios_1.default
156
+ .get(url, {
157
+ headers: {
158
+ Authorization: "Bearer " + access_token,
159
+ },
160
+ })
161
+ .then((res) => res.data);
162
+ // Select first customer
163
+ return res;
164
+ });
165
+ }
166
+ function getCurrentPayperiodInfo(payPeriodId, options) {
167
+ return __awaiter(this, void 0, void 0, function* () {
168
+ const { accessToken } = options || {};
169
+ let access_token = accessToken;
170
+ if (!access_token) {
171
+ access_token = yield getAccessToken();
172
+ }
173
+ const url = `${(0, env_1.getEnv)().DASH_URL}/api/v1/admin/employees/${payPeriodId}/current-pay-period-info`;
174
+ const res = yield axios_1.default
175
+ .get(url, {
176
+ headers: {
177
+ Authorization: "Bearer " + access_token,
178
+ },
179
+ })
180
+ .then((res) => res.data);
181
+ // Select first customer
182
+ return res;
183
+ });
184
+ }
@@ -39,3 +39,14 @@ export interface Config {
39
39
  version_number: number;
40
40
  previous_config_id: any;
41
41
  }
42
+ export interface PayperiodInfo {
43
+ month: number;
44
+ year: number;
45
+ worked_days: number;
46
+ standard_work_days: number;
47
+ work_days: number;
48
+ earned_amount: number;
49
+ advanced_amount: number;
50
+ accessible_amount: number;
51
+ has_income_from_attendance: boolean;
52
+ }
@@ -0,0 +1,10 @@
1
+ export interface CustomerEwaStatusChangeLogs {
2
+ log_created_at: string;
3
+ log_description?: string;
4
+ log_ewa_status?: "DEACTIVATE" | "ACTIVE";
5
+ log_id: string;
6
+ log_type?: string;
7
+ log_user_id?: string;
8
+ log_username?: string;
9
+ [key: string]: any;
10
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types";
2
+ export declare const DEBT_COLLECTION_TYPE: {
3
+ readonly PARTNER_IN_CHARGE: "PARTNER_IN_CHARGE";
4
+ readonly DIRECT_FROM_CUSTOMER_ACCOUNT: "DIRECT_FROM_CUSTOMER_ACCOUNT";
5
+ };
6
+ export declare const EMPLOYEE_STATUS_MAPS: Record<string, any>;
7
+ export declare function elgibilityTool(phoneNumber: string): Promise<CallToolResult>;
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.EMPLOYEE_STATUS_MAPS = exports.DEBT_COLLECTION_TYPE = void 0;
13
+ exports.elgibilityTool = elgibilityTool;
14
+ const gimo_service_1 = require("../services/gimo.service");
15
+ const FIELD_LABELS = {
16
+ ewa_status: "Trạng thái EWA",
17
+ dda: "Trạng thái DDA",
18
+ seniority: "Thâm niên làm việc",
19
+ working_status: "Trạng thái làm việc",
20
+ longest_overdue_bill: "Số ngày quá hạn thanh toán dài nhất",
21
+ outstanding_balance: "Số dư nợ",
22
+ parnter_contract_expirity: "Hạn hợp đồng đối tác",
23
+ time_sheet: "Dữ liệu chấm công",
24
+ product_type: "Loại sản phẩm",
25
+ opreation_note: "Ghi chú vận hành",
26
+ };
27
+ const PRODUCT_TYPE = {
28
+ EWA_01: "EWA_01",
29
+ EWA_02: "EWA_02",
30
+ EWA_03: "EWA_03",
31
+ EWA_04: "EWA_04",
32
+ };
33
+ const PARTNER_ONBOARD_METHOD = {
34
+ /// truyen thong
35
+ TRADITIONAL: "TRADITIONAL",
36
+ /// cong doan
37
+ UNION: "UNION",
38
+ /// chung minh thu nhap
39
+ EARNING_PROVE: "EARNING_PROVE",
40
+ };
41
+ exports.DEBT_COLLECTION_TYPE = {
42
+ PARTNER_IN_CHARGE: "PARTNER_IN_CHARGE",
43
+ DIRECT_FROM_CUSTOMER_ACCOUNT: "DIRECT_FROM_CUSTOMER_ACCOUNT",
44
+ };
45
+ function getProductType(options) {
46
+ const { partner_onboard_method, debt_collection_type } = options;
47
+ if (debt_collection_type === exports.DEBT_COLLECTION_TYPE.PARTNER_IN_CHARGE) {
48
+ return PRODUCT_TYPE.EWA_01;
49
+ }
50
+ if (debt_collection_type === exports.DEBT_COLLECTION_TYPE.DIRECT_FROM_CUSTOMER_ACCOUNT) {
51
+ if (partner_onboard_method === PARTNER_ONBOARD_METHOD.EARNING_PROVE) {
52
+ return PRODUCT_TYPE.EWA_03;
53
+ }
54
+ if (partner_onboard_method === PARTNER_ONBOARD_METHOD.UNION) {
55
+ return PRODUCT_TYPE.EWA_02;
56
+ }
57
+ // if (partner_onboard_method === PARTNER_ONBOARD_METHOD.TRADITIONAL) {
58
+ // return PRODUCT_TYPE.EWA_02;
59
+ // }
60
+ }
61
+ return null;
62
+ }
63
+ exports.EMPLOYEE_STATUS_MAPS = {
64
+ ACTIVE: "Đang làm việc",
65
+ SUSPEND__WAITING_TO_APPROVE: "Chờ công đoàn phê duyệt",
66
+ SUSPEND__MATERNITY_LEAVE: "Nhân sự nghỉ thai sản",
67
+ SUSPEND__UNPAID_LEAVE: "Nhân sự nghỉ không lương",
68
+ SUSPEND__RE_UPLOAD_ACCOUNT_STATEMENT: "Chờ cập nhật chứng minh thu nhập",
69
+ SUSPEND__WAITING_APPRAISALS_ACCOUNT_STATEMENT: "Chờ phê duyệt chứng minh thu nhập",
70
+ SUSPEND__DEFAULT: "Tạm nghỉ",
71
+ INACTIVE: "Nghỉ việc",
72
+ };
73
+ const CUSTOMER_EWA_STATUSP_MAPS = {
74
+ ACTIVE: "Hoạt động",
75
+ DEACTIVATE: "Tạm ngưng",
76
+ };
77
+ const BASE_REQUIRED_CRITERIA = {
78
+ ewa_status: "ACTIVE",
79
+ seniority: ">= 0.3 year",
80
+ working_status: exports.EMPLOYEE_STATUS_MAPS.ACTIVE,
81
+ longest_overdue_bill: "<=10 days",
82
+ outstanding_balance: "0",
83
+ parnter_contract_expirity: "Not yet expired",
84
+ time_sheet: "The data exists",
85
+ available_balance: ">0",
86
+ };
87
+ const EWA_02_CRITERIA = Object.assign(Object.assign({}, BASE_REQUIRED_CRITERIA), { dda: "REGISTERED" });
88
+ const EWA_03_CRITERIA = Object.assign(Object.assign({}, BASE_REQUIRED_CRITERIA), { dda: "REGISTERED" });
89
+ const formatter = (record) => {
90
+ return Object.keys(record)
91
+ .map((key) => `${key}: ${record[key]}`)
92
+ .join(",");
93
+ };
94
+ function elgibilityTool(phoneNumber) {
95
+ return __awaiter(this, void 0, void 0, function* () {
96
+ var _a, _b;
97
+ try {
98
+ const accessToken = yield (0, gimo_service_1.getAccessToken)();
99
+ const customer = yield (0, gimo_service_1.findCustomerEWAByPhonenumber)(phoneNumber, { accessToken });
100
+ if (!customer) {
101
+ throw "Customer not found";
102
+ }
103
+ const { employee, partner } = yield (0, gimo_service_1.getEmployeeByCustomerId)(customer.customer_id, { accessToken });
104
+ let periods = [];
105
+ let timeSheets = [];
106
+ let ewaDeactiveReason = "";
107
+ let currentPayperiodInfo = null;
108
+ if (employee) {
109
+ const payPeriods = yield (0, gimo_service_1.getPayPeriods)({ orgId: employee === null || employee === void 0 ? void 0 : employee.organization_id, parnterId: employee.partner_id }, { accessToken });
110
+ if (payPeriods === null || payPeriods === void 0 ? void 0 : payPeriods.length) {
111
+ periods = payPeriods;
112
+ timeSheets = yield (0, gimo_service_1.getTimeSheets)({ payPeriodId: payPeriods[0].id, employeeId: employee.id }, { accessToken });
113
+ currentPayperiodInfo = yield (0, gimo_service_1.getCurrentPayperiodInfo)(payPeriods[0].id, { accessToken });
114
+ }
115
+ }
116
+ if (customer.ewa_status === "DEACTIVATE") {
117
+ ewaDeactiveReason =
118
+ ((_b = (_a = (yield (0, gimo_service_1.getCustomerStatusChange)(customer.customer_id, { accessToken }))) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.log_description) || "";
119
+ }
120
+ const { debt_collection, onboard_method } = partner || {};
121
+ const productType = getProductType({
122
+ debt_collection_type: debt_collection || "",
123
+ partner_onboard_method: onboard_method || "",
124
+ });
125
+ const currentInformation = {
126
+ ewa_status: customer === null || customer === void 0 ? void 0 : customer.ewa_status,
127
+ dda: customer === null || customer === void 0 ? void 0 : customer.dda_status,
128
+ seniority: employee === null || employee === void 0 ? void 0 : employee.seniority,
129
+ working_status: exports.EMPLOYEE_STATUS_MAPS[(employee === null || employee === void 0 ? void 0 : employee.status) || "ACTIVE"],
130
+ product_type: productType,
131
+ time_sheet: (timeSheets === null || timeSheets === void 0 ? void 0 : timeSheets.length) ? "The data exists" : "The data does't exists",
132
+ longest_overdue_bill: customer.ewa_longest_over_due_day,
133
+ opreation_note: employee === null || employee === void 0 ? void 0 : employee.reason,
134
+ available_balance: currentPayperiodInfo === null || currentPayperiodInfo === void 0 ? void 0 : currentPayperiodInfo.accessible_amount,
135
+ };
136
+ const getRequriedCriteria = (productType) => {
137
+ if (productType === PRODUCT_TYPE.EWA_01) {
138
+ return BASE_REQUIRED_CRITERIA;
139
+ }
140
+ if (productType === PRODUCT_TYPE.EWA_02) {
141
+ return EWA_02_CRITERIA;
142
+ }
143
+ if (productType === PRODUCT_TYPE.EWA_03) {
144
+ return EWA_03_CRITERIA;
145
+ }
146
+ return BASE_REQUIRED_CRITERIA;
147
+ };
148
+ const requiredCriteria = getRequriedCriteria(productType);
149
+ const reasons = [ewaDeactiveReason];
150
+ const result = `
151
+ Customer ${customer.customer_full_name}, partner name ${customer.partner_name} has these information: ${formatter(currentInformation)}
152
+ Eligibility Criteria for Salary Advance: ${formatter(requiredCriteria)}
153
+ Reasons: ${reasons.filter(Boolean).join("")}
154
+ `;
155
+ return { content: [{ type: "text", text: result }] };
156
+ }
157
+ catch (error) {
158
+ return {
159
+ content: [
160
+ {
161
+ type: "text",
162
+ text: "Oh no,có rồi, thử lại nhé " + error,
163
+ },
164
+ ],
165
+ };
166
+ }
167
+ });
168
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gm-mcp",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "Mcp server for Gm",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  import z from "zod";
14
14
  import { ensureEnvVariables, getEnv } from "./env";
15
15
  import { debtCollectionRateTool } from "./tools/lark-tool";
16
- import { accessibleTool } from "./tools/accessible-tools";
16
+ import { elgibilityTool } from "./tools/eligibility-tools";
17
17
 
18
18
  export const server = new McpServer(
19
19
  {
@@ -115,7 +115,7 @@ server.tool(
115
115
  },
116
116
  async (args) => {
117
117
  const { phone_number } = args;
118
- return accessibleTool(phone_number);
118
+ return elgibilityTool(phone_number);
119
119
  }
120
120
  );
121
121
 
@@ -1,8 +1,9 @@
1
1
  import axios from "axios";
2
2
  import { Gimo } from "./types";
3
3
  import { getEnv } from "../env";
4
- import { PayPeriod } from "./types/pay-period";
4
+ import { PayPeriod, PayperiodInfo } from "./types/pay-period";
5
5
  import { TimeSheet } from "./types/time-keeper";
6
+ import { CustomerEwaStatusChangeLogs } from "./types/status-change";
6
7
 
7
8
  export async function getAccessToken() {
8
9
  const url = `${getEnv().DASH_URL}/api/v1/auth/admin/login`;
@@ -14,9 +15,15 @@ export async function getAccessToken() {
14
15
  .then((res) => res.data.access_token);
15
16
  }
16
17
 
17
- export async function findCustomerEWAByPhonenumber(phoneNumber: string) {
18
+ export async function findCustomerEWAByPhonenumber(phoneNumber: string, options?: { accessToken?: string }) {
19
+ const { accessToken } = options || {};
20
+ let access_token = accessToken;
21
+ if (!access_token) {
22
+ access_token = await getAccessToken();
23
+ }
18
24
  const customerApiUrl = `${getEnv().DASH_URL}/api/v1/admin/customers/ewa/pagination`;
19
- const access_token = await getAccessToken();
25
+
26
+ // const access_token = await getAccessToken();
20
27
  // Find inlist
21
28
  const customers = await axios
22
29
  .get<{ content: Gimo.CustomerEWA[] }>(customerApiUrl, {
@@ -35,10 +42,15 @@ export async function findCustomerEWAByPhonenumber(phoneNumber: string) {
35
42
  return findCustomerEWAById(foundedCustomer.customer_id);
36
43
  }
37
44
 
38
- export async function getPayPeriods(params: { orgId: number; parnterId: number }) {
45
+ export async function getPayPeriods(params: { orgId: number; parnterId: number }, options?: { accessToken?: string }) {
39
46
  const { orgId, parnterId } = params;
47
+ const { accessToken } = options || {};
48
+ let access_token = accessToken;
49
+ if (!access_token) {
50
+ access_token = await getAccessToken();
51
+ }
40
52
  const url = `${getEnv().DASH_URL}/api/v1/admin/partners/${parnterId}/pay-periods`;
41
- const access_token = await getAccessToken();
53
+ // const access_token = await getAccessToken();
42
54
  const customer = await axios
43
55
  .get<PayPeriod[]>(url, {
44
56
  headers: {
@@ -54,10 +66,17 @@ export async function getPayPeriods(params: { orgId: number; parnterId: number }
54
66
  return customer || null;
55
67
  }
56
68
 
57
- export async function getTimeSheets(params: { payPeriodId: number; employeeId: number }) {
69
+ export async function getTimeSheets(
70
+ params: { payPeriodId: number; employeeId: number },
71
+ options?: { accessToken?: string },
72
+ ) {
58
73
  const { payPeriodId, employeeId } = params;
74
+ const { accessToken } = options || {};
75
+ let access_token = accessToken;
76
+ if (!access_token) {
77
+ access_token = await getAccessToken();
78
+ }
59
79
  const url = `${getEnv().DASH_URL}/api/v2/admin/time-sheets/by-period`;
60
- const access_token = await getAccessToken();
61
80
  const customer = await axios
62
81
  .get<TimeSheet[]>(url, {
63
82
  headers: {
@@ -73,9 +92,13 @@ export async function getTimeSheets(params: { payPeriodId: number; employeeId: n
73
92
  return customer || null;
74
93
  }
75
94
 
76
- export async function getEmployeeByCustomerId(customerId: number) {
95
+ export async function getEmployeeByCustomerId(customerId: number, options?: { accessToken?: string }) {
96
+ const { accessToken } = options || {};
97
+ let access_token = accessToken;
98
+ if (!access_token) {
99
+ access_token = await getAccessToken();
100
+ }
77
101
  const url = `${getEnv().DASH_URL}/api/v1/admin/customers/${customerId}/employee-info`;
78
- const access_token = await getAccessToken();
79
102
  const customer = await axios
80
103
  .get<Gimo.EmployeeInfo>(url, {
81
104
  headers: {
@@ -101,3 +124,39 @@ export async function findCustomerEWAById(id: number) {
101
124
  // Select first customer
102
125
  return customer || null;
103
126
  }
127
+
128
+ export async function getCustomerStatusChange(ewaCustomerId: number, options?: { accessToken?: string }) {
129
+ const { accessToken } = options || {};
130
+ let access_token = accessToken;
131
+ if (!access_token) {
132
+ access_token = await getAccessToken();
133
+ }
134
+ const url = `${getEnv().DASH_URL}/api/v1/admin/customers/ewa/${ewaCustomerId}/status/changes`;
135
+ const res = await axios
136
+ .get<CustomerEwaStatusChangeLogs[]>(url, {
137
+ headers: {
138
+ Authorization: "Bearer " + access_token,
139
+ },
140
+ })
141
+ .then((res) => res.data);
142
+ // Select first customer
143
+ return res;
144
+ }
145
+
146
+ export async function getCurrentPayperiodInfo(payPeriodId: number, options?: { accessToken?: string }) {
147
+ const { accessToken } = options || {};
148
+ let access_token = accessToken;
149
+ if (!access_token) {
150
+ access_token = await getAccessToken();
151
+ }
152
+ const url = `${getEnv().DASH_URL}/api/v1/admin/employees/${payPeriodId}/current-pay-period-info`;
153
+ const res = await axios
154
+ .get<PayperiodInfo>(url, {
155
+ headers: {
156
+ Authorization: "Bearer " + access_token,
157
+ },
158
+ })
159
+ .then((res) => res.data);
160
+ // Select first customer
161
+ return res;
162
+ }
@@ -40,3 +40,15 @@ export interface Config {
40
40
  version_number: number;
41
41
  previous_config_id: any;
42
42
  }
43
+
44
+ export interface PayperiodInfo {
45
+ month: number;
46
+ year: number;
47
+ worked_days: number;
48
+ standard_work_days: number;
49
+ work_days: number;
50
+ earned_amount: number;
51
+ advanced_amount: number;
52
+ accessible_amount: number;
53
+ has_income_from_attendance: boolean;
54
+ }
@@ -0,0 +1,11 @@
1
+ export interface CustomerEwaStatusChangeLogs {
2
+ log_created_at: string;
3
+ log_description?: string;
4
+ log_ewa_status?: "DEACTIVATE" | "ACTIVE";
5
+ log_id: string;
6
+ log_type?: string;
7
+ log_user_id?: string;
8
+ log_username?: string;
9
+
10
+ [key: string]: any;
11
+ }
@@ -1,13 +1,29 @@
1
1
  import { CallToolResult } from "@modelcontextprotocol/sdk/types";
2
2
  import {
3
3
  findCustomerEWAByPhonenumber,
4
+ getAccessToken,
5
+ getCurrentPayperiodInfo,
6
+ getCustomerStatusChange,
4
7
  getEmployeeByCustomerId,
5
8
  getPayPeriods,
6
9
  getTimeSheets,
7
10
  } from "../services/gimo.service";
8
- import { PayPeriod } from "../services/types/pay-period";
11
+ import { PayPeriod, PayperiodInfo } from "../services/types/pay-period";
9
12
  import { TimeSheet } from "../services/types/time-keeper";
10
13
 
14
+ const FIELD_LABELS: Record<string, string> = {
15
+ ewa_status: "Trạng thái EWA",
16
+ dda: "Trạng thái DDA",
17
+ seniority: "Thâm niên làm việc",
18
+ working_status: "Trạng thái làm việc",
19
+ longest_overdue_bill: "Số ngày quá hạn thanh toán dài nhất",
20
+ outstanding_balance: "Số dư nợ",
21
+ parnter_contract_expirity: "Hạn hợp đồng đối tác",
22
+ time_sheet: "Dữ liệu chấm công",
23
+ product_type: "Loại sản phẩm",
24
+ opreation_note: "Ghi chú vận hành",
25
+ };
26
+
11
27
  const PRODUCT_TYPE = {
12
28
  EWA_01: "EWA_01",
13
29
  EWA_02: "EWA_02",
@@ -59,6 +75,11 @@ export const EMPLOYEE_STATUS_MAPS: Record<string, any> = {
59
75
  INACTIVE: "Nghỉ việc",
60
76
  };
61
77
 
78
+ const CUSTOMER_EWA_STATUSP_MAPS = {
79
+ ACTIVE: "Hoạt động",
80
+ DEACTIVATE: "Tạm ngưng",
81
+ };
82
+
62
83
  const BASE_REQUIRED_CRITERIA = {
63
84
  ewa_status: "ACTIVE",
64
85
  seniority: ">= 0.3 year",
@@ -67,6 +88,7 @@ const BASE_REQUIRED_CRITERIA = {
67
88
  outstanding_balance: "0",
68
89
  parnter_contract_expirity: "Not yet expired",
69
90
  time_sheet: "The data exists",
91
+ available_balance: ">0",
70
92
  };
71
93
 
72
94
  const EWA_02_CRITERIA = {
@@ -79,26 +101,39 @@ const EWA_03_CRITERIA = {
79
101
  dda: "REGISTERED",
80
102
  };
81
103
 
82
- const formatter = (record:Record<string,any>) => {
83
- return Object.keys(record).map(key => `${key}: ${record[key]}`).join(',')
84
- }
104
+ const formatter = (record: Record<string, any>) => {
105
+ return Object.keys(record)
106
+ .map((key) => `${key}: ${record[key]}`)
107
+ .join(",");
108
+ };
85
109
 
86
- export async function accessibleTool(phoneNumber: string): Promise<CallToolResult> {
110
+ export async function elgibilityTool(phoneNumber: string): Promise<CallToolResult> {
87
111
  try {
88
- const customer = await findCustomerEWAByPhonenumber(phoneNumber);
112
+ const accessToken = await getAccessToken();
113
+ const customer = await findCustomerEWAByPhonenumber(phoneNumber, { accessToken });
89
114
  if (!customer) {
90
115
  throw "Customer not found";
91
116
  }
92
- const { employee, partner } = await getEmployeeByCustomerId(customer.customer_id);
117
+ const { employee, partner } = await getEmployeeByCustomerId(customer.customer_id, { accessToken });
93
118
  let periods: PayPeriod[] = [];
94
119
  let timeSheets: TimeSheet[] = [];
120
+ let ewaDeactiveReason = "";
121
+ let currentPayperiodInfo: PayperiodInfo | null = null;
95
122
  if (employee) {
96
- const payPeriods = await getPayPeriods({ orgId: employee?.organization_id, parnterId: employee.partner_id });
123
+ const payPeriods = await getPayPeriods(
124
+ { orgId: employee?.organization_id, parnterId: employee.partner_id },
125
+ { accessToken },
126
+ );
97
127
  if (payPeriods?.length) {
98
128
  periods = payPeriods;
99
- timeSheets = await getTimeSheets({ payPeriodId: payPeriods[0].id, employeeId: employee.id });
129
+ timeSheets = await getTimeSheets({ payPeriodId: payPeriods[0].id, employeeId: employee.id }, { accessToken });
130
+ currentPayperiodInfo = await getCurrentPayperiodInfo(payPeriods[0].id, { accessToken });
100
131
  }
101
132
  }
133
+ if (customer.ewa_status === "DEACTIVATE") {
134
+ ewaDeactiveReason =
135
+ (await getCustomerStatusChange(customer.customer_id, { accessToken }))?.[0]?.log_description || "";
136
+ }
102
137
  const { debt_collection, onboard_method } = partner || {};
103
138
 
104
139
  const productType = getProductType({
@@ -113,6 +148,9 @@ export async function accessibleTool(phoneNumber: string): Promise<CallToolResul
113
148
  working_status: EMPLOYEE_STATUS_MAPS[employee?.status || "ACTIVE"],
114
149
  product_type: productType,
115
150
  time_sheet: timeSheets?.length ? "The data exists" : "The data does't exists",
151
+ longest_overdue_bill: customer.ewa_longest_over_due_day,
152
+ opreation_note: employee?.reason,
153
+ available_balance: currentPayperiodInfo?.accessible_amount,
116
154
  };
117
155
 
118
156
  const getRequriedCriteria = (productType: keyof typeof PRODUCT_TYPE | null) => {
@@ -130,15 +168,13 @@ export async function accessibleTool(phoneNumber: string): Promise<CallToolResul
130
168
 
131
169
  const requiredCriteria: Record<string, any> = getRequriedCriteria(productType);
132
170
 
133
- const returnData = {
134
- current_information: currentInformation,
135
- valid_information: requiredCriteria,
136
- };
171
+ const reasons = [ewaDeactiveReason];
137
172
 
138
173
  const result = `
139
- Customer ${customer.customer_full_name}, partner name ${customer.partner_name} has these informations: ${formatter(currentInformation)}
140
- Eligibility Criteria for Salary Advances: ${formatter(requiredCriteria)}
141
- `
174
+ Customer ${customer.customer_full_name}, partner name ${customer.partner_name} has these information: ${formatter(currentInformation)}
175
+ Eligibility Criteria for Salary Advance: ${formatter(requiredCriteria)}
176
+ Reasons: ${reasons.filter(Boolean).join("")}
177
+ `;
142
178
 
143
179
  return { content: [{ type: "text", text: result }] };
144
180
  } catch (error) {