@rinse-dental/open-dental 3.2.2 → 3.3.1
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/api/payPlanCharges.d.ts +18 -0
- package/dist/api/payPlanCharges.d.ts.map +1 -0
- package/dist/api/payPlanCharges.js +34 -0
- package/dist/api/payPlans.d.ts +66 -0
- package/dist/api/payPlans.d.ts.map +1 -0
- package/dist/api/payPlans.js +189 -0
- package/dist/openDental.d.ts +10 -0
- package/dist/openDental.d.ts.map +1 -1
- package/dist/openDental.js +20 -0
- package/dist/types/payPlanChargeTypes.d.ts +57 -0
- package/dist/types/payPlanChargeTypes.d.ts.map +1 -0
- package/dist/types/payPlanChargeTypes.js +32 -0
- package/dist/types/payPlanTypes.d.ts +143 -0
- package/dist/types/payPlanTypes.d.ts.map +1 -0
- package/dist/types/payPlanTypes.js +35 -0
- package/package.json +1 -1
- package/release.sh +1 -1
- package/src/api/payPlanCharges.ts +49 -0
- package/src/api/payPlans.ts +274 -0
- package/src/openDental.ts +22 -0
- package/src/types/payPlanChargeTypes.ts +77 -0
- package/src/types/payPlanTypes.ts +171 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import HttpClient from "../utils/httpClient";
|
|
2
|
+
import { PayPlanCharge } from "../types/payPlanChargeTypes";
|
|
3
|
+
export default class PayPlanCharges {
|
|
4
|
+
private httpClient;
|
|
5
|
+
constructor(httpClient: HttpClient);
|
|
6
|
+
/**
|
|
7
|
+
* Fetch all payment plan charges for a specified payment plan.
|
|
8
|
+
* Mirrors GET /payplancharges
|
|
9
|
+
* Added in version 23.2.28
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.opendental.com/site/apipayplancharges.html
|
|
12
|
+
* @param params - Query parameters: { PayPlanNum: number } (required)
|
|
13
|
+
*/
|
|
14
|
+
getPayPlanCharges(params: {
|
|
15
|
+
PayPlanNum: number;
|
|
16
|
+
}): Promise<PayPlanCharge[]>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=payPlanCharges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payPlanCharges.d.ts","sourceRoot":"","sources":["../../src/api/payPlanCharges.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAS5D,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,UAAU,CAAa;gBAEnB,UAAU,EAAE,UAAU;IAIlC;;;;;;;OAOG;IACU,iBAAiB,CAC5B,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAC7B,OAAO,CAAC,aAAa,EAAE,CAAC;CAoB5B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/** Utility to remove undefined fields from objects (for API payloads) */
|
|
4
|
+
const clean = (obj) => {
|
|
5
|
+
return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== undefined));
|
|
6
|
+
};
|
|
7
|
+
class PayPlanCharges {
|
|
8
|
+
httpClient;
|
|
9
|
+
constructor(httpClient) {
|
|
10
|
+
this.httpClient = httpClient;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fetch all payment plan charges for a specified payment plan.
|
|
14
|
+
* Mirrors GET /payplancharges
|
|
15
|
+
* Added in version 23.2.28
|
|
16
|
+
*
|
|
17
|
+
* @see https://www.opendental.com/site/apipayplancharges.html
|
|
18
|
+
* @param params - Query parameters: { PayPlanNum: number } (required)
|
|
19
|
+
*/
|
|
20
|
+
async getPayPlanCharges(params) {
|
|
21
|
+
// Validate required parameter
|
|
22
|
+
if (!params || typeof params !== "object") {
|
|
23
|
+
throw new Error("Invalid parameters: getPayPlanCharges requires a params object.");
|
|
24
|
+
}
|
|
25
|
+
if (!params.PayPlanNum || typeof params.PayPlanNum !== "number") {
|
|
26
|
+
throw new Error("Invalid parameter: PayPlanNum is required and must be a number.");
|
|
27
|
+
}
|
|
28
|
+
const query = clean({
|
|
29
|
+
PayPlanNum: params.PayPlanNum,
|
|
30
|
+
});
|
|
31
|
+
return this.httpClient.get("/payplancharges", query);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.default = PayPlanCharges;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import HttpClient from "../utils/httpClient";
|
|
2
|
+
import { PayPlan, GetPayPlanByIdParams, CreateDynamicPayPlanParams, CreatePayPlanParams, ClosePayPlanParams, UpdateDynamicPayPlanParams } from "../types/payPlanTypes";
|
|
3
|
+
export default class PayPlans {
|
|
4
|
+
private httpClient;
|
|
5
|
+
constructor(httpClient: HttpClient);
|
|
6
|
+
/**
|
|
7
|
+
* Fetch multiple payment plans with filtering by PatNum or Guarantor.
|
|
8
|
+
* Mirrors GET /payplans
|
|
9
|
+
* @see https://www.opendental.com/site/apipayplans.html
|
|
10
|
+
* @param params - Query parameters: { PatNum: number } OR { Guarantor: number } (mutually exclusive, one required)
|
|
11
|
+
*/
|
|
12
|
+
getPayPlans(params: {
|
|
13
|
+
PatNum: number;
|
|
14
|
+
Guarantor?: never;
|
|
15
|
+
} | {
|
|
16
|
+
Guarantor: number;
|
|
17
|
+
PatNum?: never;
|
|
18
|
+
}): Promise<PayPlan[]>;
|
|
19
|
+
/**
|
|
20
|
+
* Fetch a single payment plan by PayPlanNum.
|
|
21
|
+
* Mirrors GET /payplans/{PayPlanNum}
|
|
22
|
+
* Added in version 24.4.30
|
|
23
|
+
*/
|
|
24
|
+
getPayPlan({ PayPlanNum, }: GetPayPlanByIdParams): Promise<PayPlan>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new dynamic payment plan.
|
|
27
|
+
* Mirrors POST /payplans/Dynamic
|
|
28
|
+
* Added in version 22.2.22
|
|
29
|
+
*
|
|
30
|
+
* Required:
|
|
31
|
+
* - PatNum
|
|
32
|
+
* - PayAmt OR NumberOfPayments
|
|
33
|
+
* - procNums and/or adjNums (at least one must have items)
|
|
34
|
+
*
|
|
35
|
+
* Note: If APR > 0, IsLocked may be required to be true (depending on preferences)
|
|
36
|
+
*/
|
|
37
|
+
createDynamicPayPlan(data: CreateDynamicPayPlanParams): Promise<PayPlan>;
|
|
38
|
+
/**
|
|
39
|
+
* Create a patient payment plan (DEPRECATED as of 23.3.1).
|
|
40
|
+
* Mirrors POST /payplans
|
|
41
|
+
* Added in version 22.4.39, deprecated in 23.3.1
|
|
42
|
+
*
|
|
43
|
+
* @deprecated Use createDynamicPayPlan instead. This endpoint returns 410 Gone in newer versions.
|
|
44
|
+
*
|
|
45
|
+
* Required:
|
|
46
|
+
* - PatNum
|
|
47
|
+
* - useEstBalance OR principalAmount
|
|
48
|
+
* - PayAmt OR NumberOfPayments
|
|
49
|
+
*/
|
|
50
|
+
createPayPlan(data: CreatePayPlanParams): Promise<PayPlan>;
|
|
51
|
+
/**
|
|
52
|
+
* Close a payment plan and charge any outstanding interest.
|
|
53
|
+
* Mirrors PUT /payplans/{PayPlanNum}/Close
|
|
54
|
+
* Added in version 22.4.39
|
|
55
|
+
*/
|
|
56
|
+
closePayPlan({ PayPlanNum, }: ClosePayPlanParams): Promise<PayPlan>;
|
|
57
|
+
/**
|
|
58
|
+
* Update an existing dynamic payment plan.
|
|
59
|
+
* Mirrors PUT /payplans/{PayPlanNum}/Dynamic
|
|
60
|
+
* Added in version 25.3.31
|
|
61
|
+
*
|
|
62
|
+
* All fields except PayPlanNum are optional; send only what you intend to change.
|
|
63
|
+
*/
|
|
64
|
+
updateDynamicPayPlan(data: UpdateDynamicPayPlanParams): Promise<PayPlan>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=payPlans.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payPlans.d.ts","sourceRoot":"","sources":["../../src/api/payPlans.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EACL,OAAO,EACP,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACnB,kBAAkB,EAClB,0BAA0B,EAC3B,MAAM,uBAAuB,CAAC;AAS/B,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,OAAO,CAAC,UAAU,CAAa;gBAEnB,UAAU,EAAE,UAAU;IAIlC;;;;;OAKG;IACU,WAAW,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAsBnI;;;;OAIG;IACU,UAAU,CAAC,EACtB,UAAU,GACX,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAO1C;;;;;;;;;;;OAWG;IACU,oBAAoB,CAC/B,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,OAAO,CAAC;IA4DnB;;;;;;;;;;;OAWG;IACU,aAAa,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IAuDvE;;;;OAIG;IACU,YAAY,CAAC,EACxB,UAAU,GACX,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC;IAaxC;;;;;;OAMG;IACU,oBAAoB,CAC/B,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,OAAO,CAAC;CAoCpB"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/** Utility to remove undefined fields from objects (for API payloads) */
|
|
4
|
+
const clean = (obj) => {
|
|
5
|
+
return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== undefined));
|
|
6
|
+
};
|
|
7
|
+
class PayPlans {
|
|
8
|
+
httpClient;
|
|
9
|
+
constructor(httpClient) {
|
|
10
|
+
this.httpClient = httpClient;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Fetch multiple payment plans with filtering by PatNum or Guarantor.
|
|
14
|
+
* Mirrors GET /payplans
|
|
15
|
+
* @see https://www.opendental.com/site/apipayplans.html
|
|
16
|
+
* @param params - Query parameters: { PatNum: number } OR { Guarantor: number } (mutually exclusive, one required)
|
|
17
|
+
*/
|
|
18
|
+
async getPayPlans(params) {
|
|
19
|
+
// API requires either PatNum OR Guarantor, not both
|
|
20
|
+
if ('PatNum' in params && 'Guarantor' in params && params.PatNum && params.Guarantor) {
|
|
21
|
+
throw new Error("Invalid parameters: PatNum and Guarantor are mutually exclusive. Provide only one.");
|
|
22
|
+
}
|
|
23
|
+
if (!('PatNum' in params) && !('Guarantor' in params)) {
|
|
24
|
+
throw new Error("Invalid parameters: Either PatNum or Guarantor is required.");
|
|
25
|
+
}
|
|
26
|
+
const query = clean({
|
|
27
|
+
PatNum: 'PatNum' in params ? params.PatNum : undefined,
|
|
28
|
+
Guarantor: 'Guarantor' in params ? params.Guarantor : undefined,
|
|
29
|
+
});
|
|
30
|
+
return this.httpClient.get("/payplans", query);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Fetch a single payment plan by PayPlanNum.
|
|
34
|
+
* Mirrors GET /payplans/{PayPlanNum}
|
|
35
|
+
* Added in version 24.4.30
|
|
36
|
+
*/
|
|
37
|
+
async getPayPlan({ PayPlanNum, }) {
|
|
38
|
+
if (!PayPlanNum || typeof PayPlanNum !== "number") {
|
|
39
|
+
throw new Error("Invalid parameter: PayPlanNum must be a valid number.");
|
|
40
|
+
}
|
|
41
|
+
return this.httpClient.get(`/payplans/${PayPlanNum}`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a new dynamic payment plan.
|
|
45
|
+
* Mirrors POST /payplans/Dynamic
|
|
46
|
+
* Added in version 22.2.22
|
|
47
|
+
*
|
|
48
|
+
* Required:
|
|
49
|
+
* - PatNum
|
|
50
|
+
* - PayAmt OR NumberOfPayments
|
|
51
|
+
* - procNums and/or adjNums (at least one must have items)
|
|
52
|
+
*
|
|
53
|
+
* Note: If APR > 0, IsLocked may be required to be true (depending on preferences)
|
|
54
|
+
*/
|
|
55
|
+
async createDynamicPayPlan(data) {
|
|
56
|
+
// Validate required fields
|
|
57
|
+
if (!data || typeof data !== "object") {
|
|
58
|
+
throw new Error("Invalid payload: createDynamicPayPlan requires a request body.");
|
|
59
|
+
}
|
|
60
|
+
if (!data.PatNum || typeof data.PatNum !== "number") {
|
|
61
|
+
throw new Error("Invalid payload: PatNum is required and must be a number.");
|
|
62
|
+
}
|
|
63
|
+
// Either PayAmt OR NumberOfPayments is required
|
|
64
|
+
if (!data.PayAmt && !data.NumberOfPayments) {
|
|
65
|
+
throw new Error("Invalid payload: Either PayAmt or NumberOfPayments is required.");
|
|
66
|
+
}
|
|
67
|
+
// At least one of procNums or adjNums must be provided and non-empty
|
|
68
|
+
const hasProcNums = Array.isArray(data.procNums) && data.procNums.length > 0;
|
|
69
|
+
const hasAdjNums = Array.isArray(data.adjNums) && data.adjNums.length > 0;
|
|
70
|
+
if (!hasProcNums && !hasAdjNums) {
|
|
71
|
+
throw new Error("Invalid payload: At least one of procNums or adjNums must be a non-empty array.");
|
|
72
|
+
}
|
|
73
|
+
// Validate APR and IsLocked relationship
|
|
74
|
+
if (data.APR && data.APR > 0 && data.IsLocked === false) {
|
|
75
|
+
console.warn("Warning: When APR > 0, IsLocked may need to be true depending on Open Dental preferences.");
|
|
76
|
+
}
|
|
77
|
+
const payload = clean({
|
|
78
|
+
PatNum: data.PatNum,
|
|
79
|
+
PayAmt: data.PayAmt,
|
|
80
|
+
NumberOfPayments: data.NumberOfPayments,
|
|
81
|
+
procNums: data.procNums,
|
|
82
|
+
adjNums: data.adjNums,
|
|
83
|
+
Guarantor: data.Guarantor,
|
|
84
|
+
PayPlanDate: data.PayPlanDate,
|
|
85
|
+
APR: data.APR,
|
|
86
|
+
DownPayment: data.DownPayment,
|
|
87
|
+
Note: data.Note,
|
|
88
|
+
PlanCategory: data.PlanCategory,
|
|
89
|
+
ChargeFrequency: data.ChargeFrequency,
|
|
90
|
+
DatePayPlanStart: data.DatePayPlanStart,
|
|
91
|
+
DateInterestStart: data.DateInterestStart,
|
|
92
|
+
IsLocked: data.IsLocked,
|
|
93
|
+
DynamicPayPlanTPOption: data.DynamicPayPlanTPOption,
|
|
94
|
+
});
|
|
95
|
+
return this.httpClient.post("/payplans/Dynamic", payload);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create a patient payment plan (DEPRECATED as of 23.3.1).
|
|
99
|
+
* Mirrors POST /payplans
|
|
100
|
+
* Added in version 22.4.39, deprecated in 23.3.1
|
|
101
|
+
*
|
|
102
|
+
* @deprecated Use createDynamicPayPlan instead. This endpoint returns 410 Gone in newer versions.
|
|
103
|
+
*
|
|
104
|
+
* Required:
|
|
105
|
+
* - PatNum
|
|
106
|
+
* - useEstBalance OR principalAmount
|
|
107
|
+
* - PayAmt OR NumberOfPayments
|
|
108
|
+
*/
|
|
109
|
+
async createPayPlan(data) {
|
|
110
|
+
console.warn("Warning: createPayPlan is deprecated as of version 23.3.1. Use createDynamicPayPlan instead.");
|
|
111
|
+
// Validate required fields
|
|
112
|
+
if (!data || typeof data !== "object") {
|
|
113
|
+
throw new Error("Invalid payload: createPayPlan requires a request body.");
|
|
114
|
+
}
|
|
115
|
+
if (!data.PatNum || typeof data.PatNum !== "number") {
|
|
116
|
+
throw new Error("Invalid payload: PatNum is required and must be a number.");
|
|
117
|
+
}
|
|
118
|
+
// Either useEstBalance OR principalAmount is required
|
|
119
|
+
if (data.useEstBalance === undefined &&
|
|
120
|
+
data.principalAmount === undefined) {
|
|
121
|
+
throw new Error("Invalid payload: Either useEstBalance or principalAmount is required.");
|
|
122
|
+
}
|
|
123
|
+
// Either PayAmt OR NumberOfPayments is required
|
|
124
|
+
if (!data.PayAmt && !data.NumberOfPayments) {
|
|
125
|
+
throw new Error("Invalid payload: Either PayAmt or NumberOfPayments is required.");
|
|
126
|
+
}
|
|
127
|
+
const payload = clean({
|
|
128
|
+
PatNum: data.PatNum,
|
|
129
|
+
useEstBalance: data.useEstBalance,
|
|
130
|
+
principalAmount: data.principalAmount,
|
|
131
|
+
PayAmt: data.PayAmt,
|
|
132
|
+
NumberOfPayments: data.NumberOfPayments,
|
|
133
|
+
Guarantor: data.Guarantor,
|
|
134
|
+
PayPlanDate: data.PayPlanDate,
|
|
135
|
+
APR: data.APR,
|
|
136
|
+
DownPayment: data.DownPayment,
|
|
137
|
+
Note: data.Note,
|
|
138
|
+
PlanCategory: data.PlanCategory,
|
|
139
|
+
ChargeFrequency: data.ChargeFrequency,
|
|
140
|
+
DatePayPlanStart: data.DatePayPlanStart,
|
|
141
|
+
DateInterestStart: data.DateInterestStart,
|
|
142
|
+
});
|
|
143
|
+
return this.httpClient.post("/payplans", payload);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Close a payment plan and charge any outstanding interest.
|
|
147
|
+
* Mirrors PUT /payplans/{PayPlanNum}/Close
|
|
148
|
+
* Added in version 22.4.39
|
|
149
|
+
*/
|
|
150
|
+
async closePayPlan({ PayPlanNum, }) {
|
|
151
|
+
if (!PayPlanNum || typeof PayPlanNum !== "number") {
|
|
152
|
+
throw new Error("Invalid parameter: PayPlanNum is required and must be a number.");
|
|
153
|
+
}
|
|
154
|
+
return this.httpClient.put(`/payplans/${PayPlanNum}/Close`, {});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Update an existing dynamic payment plan.
|
|
158
|
+
* Mirrors PUT /payplans/{PayPlanNum}/Dynamic
|
|
159
|
+
* Added in version 25.3.31
|
|
160
|
+
*
|
|
161
|
+
* All fields except PayPlanNum are optional; send only what you intend to change.
|
|
162
|
+
*/
|
|
163
|
+
async updateDynamicPayPlan(data) {
|
|
164
|
+
if (!data?.PayPlanNum || typeof data.PayPlanNum !== "number") {
|
|
165
|
+
throw new Error("Invalid payload: PayPlanNum is required and must be a number.");
|
|
166
|
+
}
|
|
167
|
+
// Validate APR and IsLocked relationship
|
|
168
|
+
if (data.APR && data.APR > 0 && data.IsLocked === false) {
|
|
169
|
+
console.warn("Warning: When APR > 0, IsLocked may need to be true depending on Open Dental preferences.");
|
|
170
|
+
}
|
|
171
|
+
const { PayPlanNum, ...updateFields } = data;
|
|
172
|
+
const payload = clean({
|
|
173
|
+
PayAmt: updateFields.PayAmt,
|
|
174
|
+
NumberOfPayments: updateFields.NumberOfPayments,
|
|
175
|
+
Guarantor: updateFields.Guarantor,
|
|
176
|
+
PayPlanDate: updateFields.PayPlanDate,
|
|
177
|
+
APR: updateFields.APR,
|
|
178
|
+
Note: updateFields.Note,
|
|
179
|
+
PlanCategory: updateFields.PlanCategory,
|
|
180
|
+
ChargeFrequency: updateFields.ChargeFrequency,
|
|
181
|
+
DatePayPlanStart: updateFields.DatePayPlanStart,
|
|
182
|
+
DateInterestStart: updateFields.DateInterestStart,
|
|
183
|
+
IsLocked: updateFields.IsLocked,
|
|
184
|
+
SheetDefNum: updateFields.SheetDefNum,
|
|
185
|
+
});
|
|
186
|
+
return this.httpClient.put(`/payplans/${PayPlanNum}/Dynamic`, payload);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
exports.default = PayPlans;
|
package/dist/openDental.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ import Providers from "./api/providers";
|
|
|
12
12
|
import Operatories from "./api/operatories";
|
|
13
13
|
import Payments from "./api/payments";
|
|
14
14
|
import PaySplits from "./api/paySplits";
|
|
15
|
+
import PayPlans from "./api/payPlans";
|
|
16
|
+
import PayPlanCharges from "./api/payPlanCharges";
|
|
15
17
|
import Definitions from "./api/definitions";
|
|
16
18
|
import DiscountPlans from "./api/discountPlans";
|
|
17
19
|
import DiscountPlanSubs from "./api/discountPlanSubs";
|
|
@@ -161,6 +163,14 @@ declare class OpenDental {
|
|
|
161
163
|
* Create a new instance of the PaySplits API.
|
|
162
164
|
*/
|
|
163
165
|
static PaySplits(): PaySplits;
|
|
166
|
+
/**
|
|
167
|
+
* Create a new instance of the PayPlans API.
|
|
168
|
+
*/
|
|
169
|
+
static PayPlans(): PayPlans;
|
|
170
|
+
/**
|
|
171
|
+
* Create a new instance of the PayPlanCharges API.
|
|
172
|
+
*/
|
|
173
|
+
static PayPlanCharges(): PayPlanCharges;
|
|
164
174
|
/**
|
|
165
175
|
* Create a new instance of the Fees API.
|
|
166
176
|
*/
|
package/dist/openDental.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openDental.d.ts","sourceRoot":"","sources":["../src/openDental.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"openDental.d.ts","sourceRoot":"","sources":["../src/openDental.ts"],"names":[],"mappings":"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"}
|
package/dist/openDental.js
CHANGED
|
@@ -52,6 +52,8 @@ const providers_1 = __importDefault(require("./api/providers"));
|
|
|
52
52
|
const operatories_1 = __importDefault(require("./api/operatories"));
|
|
53
53
|
const payments_1 = __importDefault(require("./api/payments"));
|
|
54
54
|
const paySplits_1 = __importDefault(require("./api/paySplits"));
|
|
55
|
+
const payPlans_1 = __importDefault(require("./api/payPlans"));
|
|
56
|
+
const payPlanCharges_1 = __importDefault(require("./api/payPlanCharges"));
|
|
55
57
|
const definitions_1 = __importDefault(require("./api/definitions"));
|
|
56
58
|
const discountPlans_1 = __importDefault(require("./api/discountPlans"));
|
|
57
59
|
const discountPlanSubs_1 = __importDefault(require("./api/discountPlanSubs"));
|
|
@@ -353,6 +355,24 @@ class OpenDental {
|
|
|
353
355
|
}
|
|
354
356
|
return new paySplits_1.default(this.httpClient);
|
|
355
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* Create a new instance of the PayPlans API.
|
|
360
|
+
*/
|
|
361
|
+
static PayPlans() {
|
|
362
|
+
if (!this.httpClient) {
|
|
363
|
+
throw new Error("OpenDental not initialized. Call OpenDental.initialize() first.");
|
|
364
|
+
}
|
|
365
|
+
return new payPlans_1.default(this.httpClient);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Create a new instance of the PayPlanCharges API.
|
|
369
|
+
*/
|
|
370
|
+
static PayPlanCharges() {
|
|
371
|
+
if (!this.httpClient) {
|
|
372
|
+
throw new Error("OpenDental not initialized. Call OpenDental.initialize() first.");
|
|
373
|
+
}
|
|
374
|
+
return new payPlanCharges_1.default(this.httpClient);
|
|
375
|
+
}
|
|
356
376
|
/**
|
|
357
377
|
* Create a new instance of the Fees API.
|
|
358
378
|
*/
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPlanCharge types for Open Dental REST API
|
|
3
|
+
* Spec refs:
|
|
4
|
+
* - https://www.opendental.com/site/apipayplancharges.html
|
|
5
|
+
*
|
|
6
|
+
* Notes:
|
|
7
|
+
* - Dates are strings from the API (yyyy-MM-dd or yyyy-MM-dd HH:mm:ss).
|
|
8
|
+
* - PayPlanCharges represent individual charges within a payment plan
|
|
9
|
+
* - Each charge can be a debit (payment due) or credit (payment received)
|
|
10
|
+
* @see https://www.opendental.com/site/apipayplancharges.html
|
|
11
|
+
*/
|
|
12
|
+
/** Charge type for payment plan charges */
|
|
13
|
+
export type ChargeType = "Debit" | "Credit";
|
|
14
|
+
/** Link type for payment plan charges */
|
|
15
|
+
export type LinkType = "Procedure" | "Adjustment" | "Payment" | "None" | string;
|
|
16
|
+
/**
|
|
17
|
+
* Represents a PayPlanCharge returned by the Open Dental API.
|
|
18
|
+
* Mirrors the response payload of GET endpoints.
|
|
19
|
+
*/
|
|
20
|
+
export interface PayPlanCharge {
|
|
21
|
+
PayPlanChargeNum: number;
|
|
22
|
+
PayPlanNum: number;
|
|
23
|
+
Guarantor: number;
|
|
24
|
+
PatNum: number;
|
|
25
|
+
ChargeDate: string;
|
|
26
|
+
Principal: number;
|
|
27
|
+
Interest: number;
|
|
28
|
+
Note: string;
|
|
29
|
+
ProvNum: number;
|
|
30
|
+
ClinicNum: number;
|
|
31
|
+
ChargeType: ChargeType;
|
|
32
|
+
ProcNum: number;
|
|
33
|
+
SecDateTEntry: string;
|
|
34
|
+
SecDateTEdit: string;
|
|
35
|
+
StatementNum: number;
|
|
36
|
+
FKey: number;
|
|
37
|
+
LinkType: LinkType;
|
|
38
|
+
IsOffset: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** GET /payplancharges query params */
|
|
41
|
+
export interface GetPayPlanChargesParams {
|
|
42
|
+
/** Payment plan number - Required */
|
|
43
|
+
PayPlanNum: number;
|
|
44
|
+
}
|
|
45
|
+
/** Minimal helper to detect "zero" dates in responses */
|
|
46
|
+
export declare const isZeroDate: (d?: string | null) => boolean;
|
|
47
|
+
/** Narrow helper for timestamps that can be zeroed by the API */
|
|
48
|
+
export declare const isZeroDateTime: (d?: string | null) => boolean;
|
|
49
|
+
/** Runtime guard for ChargeType values */
|
|
50
|
+
export declare const isChargeType: (s: string) => s is ChargeType;
|
|
51
|
+
/** Helper to determine if a charge is a debit (payment due) */
|
|
52
|
+
export declare const isDebitCharge: (charge: PayPlanCharge) => boolean;
|
|
53
|
+
/** Helper to determine if a charge is a credit (payment received) */
|
|
54
|
+
export declare const isCreditCharge: (charge: PayPlanCharge) => boolean;
|
|
55
|
+
/** Helper to calculate total charge amount (principal + interest) */
|
|
56
|
+
export declare const getTotalChargeAmount: (charge: PayPlanCharge) => number;
|
|
57
|
+
//# sourceMappingURL=payPlanChargeTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payPlanChargeTypes.d.ts","sourceRoot":"","sources":["../../src/types/payPlanChargeTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,2CAA2C;AAC3C,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,yCAAyC;AACzC,MAAM,MAAM,QAAQ,GAChB,WAAW,GACX,YAAY,GACZ,SAAS,GACT,MAAM,GACN,MAAM,CAAC;AAEX;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,uCAAuC;AACvC,MAAM,WAAW,uBAAuB;IACtC,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,yDAAyD;AACzD,eAAO,MAAM,UAAU,GAAI,IAAI,MAAM,GAAG,IAAI,KAAG,OACrB,CAAC;AAE3B,iEAAiE;AACjE,eAAO,MAAM,cAAc,GAAI,IAAI,MAAM,GAAG,IAAI,KAAG,OACjB,CAAC;AAEnC,0CAA0C;AAC1C,eAAO,MAAM,YAAY,GAAI,GAAG,MAAM,KAAG,CAAC,IAAI,UACb,CAAC;AAElC,+DAA+D;AAC/D,eAAO,MAAM,aAAa,GAAI,QAAQ,aAAa,KAAG,OACvB,CAAC;AAEhC,qEAAqE;AACrE,eAAO,MAAM,cAAc,GAAI,QAAQ,aAAa,KAAG,OACvB,CAAC;AAEjC,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,GAAI,QAAQ,aAAa,KAAG,MACzB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PayPlanCharge types for Open Dental REST API
|
|
4
|
+
* Spec refs:
|
|
5
|
+
* - https://www.opendental.com/site/apipayplancharges.html
|
|
6
|
+
*
|
|
7
|
+
* Notes:
|
|
8
|
+
* - Dates are strings from the API (yyyy-MM-dd or yyyy-MM-dd HH:mm:ss).
|
|
9
|
+
* - PayPlanCharges represent individual charges within a payment plan
|
|
10
|
+
* - Each charge can be a debit (payment due) or credit (payment received)
|
|
11
|
+
* @see https://www.opendental.com/site/apipayplancharges.html
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.getTotalChargeAmount = exports.isCreditCharge = exports.isDebitCharge = exports.isChargeType = exports.isZeroDateTime = exports.isZeroDate = void 0;
|
|
15
|
+
/** Minimal helper to detect "zero" dates in responses */
|
|
16
|
+
const isZeroDate = (d) => !d || d === "0001-01-01";
|
|
17
|
+
exports.isZeroDate = isZeroDate;
|
|
18
|
+
/** Narrow helper for timestamps that can be zeroed by the API */
|
|
19
|
+
const isZeroDateTime = (d) => !d || d.startsWith("0001-01-01");
|
|
20
|
+
exports.isZeroDateTime = isZeroDateTime;
|
|
21
|
+
/** Runtime guard for ChargeType values */
|
|
22
|
+
const isChargeType = (s) => ["Debit", "Credit"].includes(s);
|
|
23
|
+
exports.isChargeType = isChargeType;
|
|
24
|
+
/** Helper to determine if a charge is a debit (payment due) */
|
|
25
|
+
const isDebitCharge = (charge) => charge.ChargeType === "Debit";
|
|
26
|
+
exports.isDebitCharge = isDebitCharge;
|
|
27
|
+
/** Helper to determine if a charge is a credit (payment received) */
|
|
28
|
+
const isCreditCharge = (charge) => charge.ChargeType === "Credit";
|
|
29
|
+
exports.isCreditCharge = isCreditCharge;
|
|
30
|
+
/** Helper to calculate total charge amount (principal + interest) */
|
|
31
|
+
const getTotalChargeAmount = (charge) => charge.Principal + charge.Interest;
|
|
32
|
+
exports.getTotalChargeAmount = getTotalChargeAmount;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPlan types for Open Dental REST API
|
|
3
|
+
* Spec refs:
|
|
4
|
+
* - https://www.opendental.com/site/apipayplans.html
|
|
5
|
+
*
|
|
6
|
+
* Notes:
|
|
7
|
+
* - Dates are strings from the API (yyyy-MM-dd or yyyy-MM-dd HH:mm:ss).
|
|
8
|
+
* - Prior to 23.3.1, Open Dental users had the ability to create both Patient Payment Plans and Dynamic Payment Plans.
|
|
9
|
+
* - In version 23.3.1, Open Dental deprecated Patient Payment Plans, renaming them to Old Payment Plans in the UI.
|
|
10
|
+
* - The PayPlans POST (create) method was also deprecated at that time.
|
|
11
|
+
* - Dynamic Payment Plans are now referred to simply as Payment Plans in Open Dental.
|
|
12
|
+
* - Insurance payment plans have PlanNum and InsSubNum values greater than zero
|
|
13
|
+
* @see https://www.opendental.com/site/apipayplans.html
|
|
14
|
+
*/
|
|
15
|
+
/** Charge frequency for payment plans */
|
|
16
|
+
export type ChargeFrequency = "Weekly" | "EveryOtherWeek" | "Monthly" | "Quarterly" | "OrdinalWeekday";
|
|
17
|
+
/** Dynamic payment plan treatment plan option */
|
|
18
|
+
export type DynamicPayPlanTPOption = "AwaitComplete" | "TreatAsComplete" | "None";
|
|
19
|
+
/**
|
|
20
|
+
* Represents a PayPlan returned by the Open Dental API.
|
|
21
|
+
* Mirrors the response payload of GET/POST/PUT endpoints.
|
|
22
|
+
*/
|
|
23
|
+
export interface PayPlan {
|
|
24
|
+
PayPlanNum: number;
|
|
25
|
+
PatNum: number;
|
|
26
|
+
Guarantor: number;
|
|
27
|
+
PayPlanDate: string;
|
|
28
|
+
APR: number;
|
|
29
|
+
Note: string;
|
|
30
|
+
PlanNum: number;
|
|
31
|
+
CompletedAmt: number;
|
|
32
|
+
InsSubNum: number;
|
|
33
|
+
PaySchedule: number;
|
|
34
|
+
NumberOfPayments: number;
|
|
35
|
+
PayAmt: number;
|
|
36
|
+
DownPayment: number;
|
|
37
|
+
IsClosed: boolean;
|
|
38
|
+
Signature: string;
|
|
39
|
+
SigIsTopaz: boolean;
|
|
40
|
+
PlanCategory: number;
|
|
41
|
+
IsDynamic: boolean;
|
|
42
|
+
ChargeFrequency: ChargeFrequency;
|
|
43
|
+
DatePayPlanStart: string;
|
|
44
|
+
DynamicPayPlanTPOption: DynamicPayPlanTPOption;
|
|
45
|
+
DateInterestStart: string;
|
|
46
|
+
IsLocked: boolean;
|
|
47
|
+
SheetDefNum: number;
|
|
48
|
+
}
|
|
49
|
+
/** GET /payplans (multiple) query params */
|
|
50
|
+
export interface GetPayPlansParams {
|
|
51
|
+
/** Patient number - mutually exclusive with Guarantor */
|
|
52
|
+
PatNum?: number;
|
|
53
|
+
/** Guarantor number - mutually exclusive with PatNum */
|
|
54
|
+
Guarantor?: number;
|
|
55
|
+
}
|
|
56
|
+
/** GET /payplans/{PayPlanNum} - path parameter only */
|
|
57
|
+
export interface GetPayPlanByIdParams {
|
|
58
|
+
PayPlanNum: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* POST /payplans/Dynamic body
|
|
62
|
+
* Creates a dynamic payment plan
|
|
63
|
+
* Required: PatNum, (PayAmt OR NumberOfPayments), (procNums OR adjNums)
|
|
64
|
+
*/
|
|
65
|
+
export interface CreateDynamicPayPlanParams {
|
|
66
|
+
PatNum: number;
|
|
67
|
+
PayAmt?: number;
|
|
68
|
+
NumberOfPayments?: number;
|
|
69
|
+
procNums?: number[];
|
|
70
|
+
adjNums?: number[];
|
|
71
|
+
Guarantor?: number;
|
|
72
|
+
PayPlanDate?: string;
|
|
73
|
+
APR?: number;
|
|
74
|
+
DownPayment?: number;
|
|
75
|
+
Note?: string;
|
|
76
|
+
PlanCategory?: number;
|
|
77
|
+
ChargeFrequency?: ChargeFrequency;
|
|
78
|
+
DatePayPlanStart?: string;
|
|
79
|
+
DateInterestStart?: string;
|
|
80
|
+
IsLocked?: boolean;
|
|
81
|
+
DynamicPayPlanTPOption?: DynamicPayPlanTPOption;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* POST /payplans body (DEPRECATED as of 23.3.1)
|
|
85
|
+
* Use CreateDynamicPayPlanParams instead
|
|
86
|
+
* Creates an old-style patient payment plan
|
|
87
|
+
*/
|
|
88
|
+
export interface CreatePayPlanParams {
|
|
89
|
+
PatNum: number;
|
|
90
|
+
useEstBalance?: boolean;
|
|
91
|
+
principalAmount?: number;
|
|
92
|
+
PayAmt?: number;
|
|
93
|
+
NumberOfPayments?: number;
|
|
94
|
+
Guarantor?: number;
|
|
95
|
+
PayPlanDate?: string;
|
|
96
|
+
APR?: number;
|
|
97
|
+
DownPayment?: number;
|
|
98
|
+
Note?: string;
|
|
99
|
+
PlanCategory?: number;
|
|
100
|
+
ChargeFrequency?: ChargeFrequency;
|
|
101
|
+
DatePayPlanStart?: string;
|
|
102
|
+
DateInterestStart?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* PUT /payplans/{PayPlanNum}/Close
|
|
106
|
+
* Closes a payment plan and charges outstanding interest
|
|
107
|
+
*/
|
|
108
|
+
export interface ClosePayPlanParams {
|
|
109
|
+
PayPlanNum: number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* PUT /payplans/{PayPlanNum}/Dynamic
|
|
113
|
+
* Updates a dynamic payment plan
|
|
114
|
+
* All fields optional except PayPlanNum
|
|
115
|
+
*/
|
|
116
|
+
export interface UpdateDynamicPayPlanParams {
|
|
117
|
+
PayPlanNum: number;
|
|
118
|
+
PayAmt?: number;
|
|
119
|
+
NumberOfPayments?: number;
|
|
120
|
+
Guarantor?: number;
|
|
121
|
+
PayPlanDate?: string;
|
|
122
|
+
APR?: number;
|
|
123
|
+
Note?: string;
|
|
124
|
+
PlanCategory?: number;
|
|
125
|
+
ChargeFrequency?: ChargeFrequency;
|
|
126
|
+
DatePayPlanStart?: string;
|
|
127
|
+
DateInterestStart?: string;
|
|
128
|
+
IsLocked?: boolean;
|
|
129
|
+
SheetDefNum?: number;
|
|
130
|
+
}
|
|
131
|
+
/** Minimal helper to detect "zero" dates in responses */
|
|
132
|
+
export declare const isZeroDate: (d?: string | null) => boolean;
|
|
133
|
+
/** Narrow helper for timestamps that can be zeroed by the API */
|
|
134
|
+
export declare const isZeroDateTime: (d?: string | null) => boolean;
|
|
135
|
+
/** Runtime guard for ChargeFrequency values */
|
|
136
|
+
export declare const isChargeFrequency: (s: string) => s is ChargeFrequency;
|
|
137
|
+
/** Runtime guard for DynamicPayPlanTPOption values */
|
|
138
|
+
export declare const isDynamicPayPlanTPOption: (t: string) => t is DynamicPayPlanTPOption;
|
|
139
|
+
/** Helper to determine if a PayPlan is an insurance payment plan */
|
|
140
|
+
export declare const isInsurancePayPlan: (payPlan: PayPlan) => boolean;
|
|
141
|
+
/** Helper to determine if a PayPlan is a patient payment plan */
|
|
142
|
+
export declare const isPatientPayPlan: (payPlan: PayPlan) => boolean;
|
|
143
|
+
//# sourceMappingURL=payPlanTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payPlanTypes.d.ts","sourceRoot":"","sources":["../../src/types/payPlanTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PayPlan types for Open Dental REST API
|
|
4
|
+
* Spec refs:
|
|
5
|
+
* - https://www.opendental.com/site/apipayplans.html
|
|
6
|
+
*
|
|
7
|
+
* Notes:
|
|
8
|
+
* - Dates are strings from the API (yyyy-MM-dd or yyyy-MM-dd HH:mm:ss).
|
|
9
|
+
* - Prior to 23.3.1, Open Dental users had the ability to create both Patient Payment Plans and Dynamic Payment Plans.
|
|
10
|
+
* - In version 23.3.1, Open Dental deprecated Patient Payment Plans, renaming them to Old Payment Plans in the UI.
|
|
11
|
+
* - The PayPlans POST (create) method was also deprecated at that time.
|
|
12
|
+
* - Dynamic Payment Plans are now referred to simply as Payment Plans in Open Dental.
|
|
13
|
+
* - Insurance payment plans have PlanNum and InsSubNum values greater than zero
|
|
14
|
+
* @see https://www.opendental.com/site/apipayplans.html
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.isPatientPayPlan = exports.isInsurancePayPlan = exports.isDynamicPayPlanTPOption = exports.isChargeFrequency = exports.isZeroDateTime = exports.isZeroDate = void 0;
|
|
18
|
+
/** Minimal helper to detect "zero" dates in responses */
|
|
19
|
+
const isZeroDate = (d) => !d || d === "0001-01-01";
|
|
20
|
+
exports.isZeroDate = isZeroDate;
|
|
21
|
+
/** Narrow helper for timestamps that can be zeroed by the API */
|
|
22
|
+
const isZeroDateTime = (d) => !d || d.startsWith("0001-01-01");
|
|
23
|
+
exports.isZeroDateTime = isZeroDateTime;
|
|
24
|
+
/** Runtime guard for ChargeFrequency values */
|
|
25
|
+
const isChargeFrequency = (s) => ["Weekly", "EveryOtherWeek", "Monthly", "Quarterly", "OrdinalWeekday"].includes(s);
|
|
26
|
+
exports.isChargeFrequency = isChargeFrequency;
|
|
27
|
+
/** Runtime guard for DynamicPayPlanTPOption values */
|
|
28
|
+
const isDynamicPayPlanTPOption = (t) => ["AwaitComplete", "TreatAsComplete", "None"].includes(t);
|
|
29
|
+
exports.isDynamicPayPlanTPOption = isDynamicPayPlanTPOption;
|
|
30
|
+
/** Helper to determine if a PayPlan is an insurance payment plan */
|
|
31
|
+
const isInsurancePayPlan = (payPlan) => payPlan.PlanNum > 0 && payPlan.InsSubNum > 0;
|
|
32
|
+
exports.isInsurancePayPlan = isInsurancePayPlan;
|
|
33
|
+
/** Helper to determine if a PayPlan is a patient payment plan */
|
|
34
|
+
const isPatientPayPlan = (payPlan) => payPlan.PlanNum === 0 && payPlan.InsSubNum === 0;
|
|
35
|
+
exports.isPatientPayPlan = isPatientPayPlan;
|
package/package.json
CHANGED
package/release.sh
CHANGED
|
@@ -41,7 +41,7 @@ gh release create "$NEW_TAG" --title "Release $NEW_TAG" --notes "$COMMIT_MSG"
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
#example ./release.sh "updated axios error return" patch
|
|
44
|
-
#example ./release.sh "Added
|
|
44
|
+
#example ./release.sh "Added Claims api" minor
|
|
45
45
|
#example ./release.sh "Some commit message" major
|
|
46
46
|
|
|
47
47
|
#./release.sh "Added readme" patch
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// src/api/payPlanCharges.ts
|
|
2
|
+
import HttpClient from "../utils/httpClient";
|
|
3
|
+
import { PayPlanCharge } from "../types/payPlanChargeTypes";
|
|
4
|
+
|
|
5
|
+
/** Utility to remove undefined fields from objects (for API payloads) */
|
|
6
|
+
const clean = (obj: Record<string, any>): Record<string, any> => {
|
|
7
|
+
return Object.fromEntries(
|
|
8
|
+
Object.entries(obj).filter(([_, v]) => v !== undefined)
|
|
9
|
+
);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default class PayPlanCharges {
|
|
13
|
+
private httpClient: HttpClient;
|
|
14
|
+
|
|
15
|
+
constructor(httpClient: HttpClient) {
|
|
16
|
+
this.httpClient = httpClient;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Fetch all payment plan charges for a specified payment plan.
|
|
21
|
+
* Mirrors GET /payplancharges
|
|
22
|
+
* Added in version 23.2.28
|
|
23
|
+
*
|
|
24
|
+
* @see https://www.opendental.com/site/apipayplancharges.html
|
|
25
|
+
* @param params - Query parameters: { PayPlanNum: number } (required)
|
|
26
|
+
*/
|
|
27
|
+
public async getPayPlanCharges(
|
|
28
|
+
params: { PayPlanNum: number }
|
|
29
|
+
): Promise<PayPlanCharge[]> {
|
|
30
|
+
// Validate required parameter
|
|
31
|
+
if (!params || typeof params !== "object") {
|
|
32
|
+
throw new Error(
|
|
33
|
+
"Invalid parameters: getPayPlanCharges requires a params object."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!params.PayPlanNum || typeof params.PayPlanNum !== "number") {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"Invalid parameter: PayPlanNum is required and must be a number."
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const query = clean({
|
|
44
|
+
PayPlanNum: params.PayPlanNum,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return this.httpClient.get<PayPlanCharge[]>("/payplancharges", query);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// src/api/payPlans.ts
|
|
2
|
+
import HttpClient from "../utils/httpClient";
|
|
3
|
+
import {
|
|
4
|
+
PayPlan,
|
|
5
|
+
GetPayPlanByIdParams,
|
|
6
|
+
CreateDynamicPayPlanParams,
|
|
7
|
+
CreatePayPlanParams,
|
|
8
|
+
ClosePayPlanParams,
|
|
9
|
+
UpdateDynamicPayPlanParams,
|
|
10
|
+
} from "../types/payPlanTypes";
|
|
11
|
+
|
|
12
|
+
/** Utility to remove undefined fields from objects (for API payloads) */
|
|
13
|
+
const clean = (obj: Record<string, any>): Record<string, any> => {
|
|
14
|
+
return Object.fromEntries(
|
|
15
|
+
Object.entries(obj).filter(([_, v]) => v !== undefined)
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default class PayPlans {
|
|
20
|
+
private httpClient: HttpClient;
|
|
21
|
+
|
|
22
|
+
constructor(httpClient: HttpClient) {
|
|
23
|
+
this.httpClient = httpClient;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Fetch multiple payment plans with filtering by PatNum or Guarantor.
|
|
28
|
+
* Mirrors GET /payplans
|
|
29
|
+
* @see https://www.opendental.com/site/apipayplans.html
|
|
30
|
+
* @param params - Query parameters: { PatNum: number } OR { Guarantor: number } (mutually exclusive, one required)
|
|
31
|
+
*/
|
|
32
|
+
public async getPayPlans(params: { PatNum: number; Guarantor?: never } | { Guarantor: number; PatNum?: never }): Promise<PayPlan[]> {
|
|
33
|
+
// API requires either PatNum OR Guarantor, not both
|
|
34
|
+
if ('PatNum' in params && 'Guarantor' in params && params.PatNum && params.Guarantor) {
|
|
35
|
+
throw new Error(
|
|
36
|
+
"Invalid parameters: PatNum and Guarantor are mutually exclusive. Provide only one."
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (!('PatNum' in params) && !('Guarantor' in params)) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
"Invalid parameters: Either PatNum or Guarantor is required."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const query = clean({
|
|
47
|
+
PatNum: 'PatNum' in params ? params.PatNum : undefined,
|
|
48
|
+
Guarantor: 'Guarantor' in params ? params.Guarantor : undefined,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return this.httpClient.get<PayPlan[]>("/payplans", query);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Fetch a single payment plan by PayPlanNum.
|
|
56
|
+
* Mirrors GET /payplans/{PayPlanNum}
|
|
57
|
+
* Added in version 24.4.30
|
|
58
|
+
*/
|
|
59
|
+
public async getPayPlan({
|
|
60
|
+
PayPlanNum,
|
|
61
|
+
}: GetPayPlanByIdParams): Promise<PayPlan> {
|
|
62
|
+
if (!PayPlanNum || typeof PayPlanNum !== "number") {
|
|
63
|
+
throw new Error("Invalid parameter: PayPlanNum must be a valid number.");
|
|
64
|
+
}
|
|
65
|
+
return this.httpClient.get<PayPlan>(`/payplans/${PayPlanNum}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Create a new dynamic payment plan.
|
|
70
|
+
* Mirrors POST /payplans/Dynamic
|
|
71
|
+
* Added in version 22.2.22
|
|
72
|
+
*
|
|
73
|
+
* Required:
|
|
74
|
+
* - PatNum
|
|
75
|
+
* - PayAmt OR NumberOfPayments
|
|
76
|
+
* - procNums and/or adjNums (at least one must have items)
|
|
77
|
+
*
|
|
78
|
+
* Note: If APR > 0, IsLocked may be required to be true (depending on preferences)
|
|
79
|
+
*/
|
|
80
|
+
public async createDynamicPayPlan(
|
|
81
|
+
data: CreateDynamicPayPlanParams
|
|
82
|
+
): Promise<PayPlan> {
|
|
83
|
+
// Validate required fields
|
|
84
|
+
if (!data || typeof data !== "object") {
|
|
85
|
+
throw new Error(
|
|
86
|
+
"Invalid payload: createDynamicPayPlan requires a request body."
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!data.PatNum || typeof data.PatNum !== "number") {
|
|
91
|
+
throw new Error(
|
|
92
|
+
"Invalid payload: PatNum is required and must be a number."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Either PayAmt OR NumberOfPayments is required
|
|
97
|
+
if (!data.PayAmt && !data.NumberOfPayments) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
"Invalid payload: Either PayAmt or NumberOfPayments is required."
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// At least one of procNums or adjNums must be provided and non-empty
|
|
104
|
+
const hasProcNums = Array.isArray(data.procNums) && data.procNums.length > 0;
|
|
105
|
+
const hasAdjNums = Array.isArray(data.adjNums) && data.adjNums.length > 0;
|
|
106
|
+
|
|
107
|
+
if (!hasProcNums && !hasAdjNums) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
"Invalid payload: At least one of procNums or adjNums must be a non-empty array."
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Validate APR and IsLocked relationship
|
|
114
|
+
if (data.APR && data.APR > 0 && data.IsLocked === false) {
|
|
115
|
+
console.warn(
|
|
116
|
+
"Warning: When APR > 0, IsLocked may need to be true depending on Open Dental preferences."
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const payload = clean({
|
|
121
|
+
PatNum: data.PatNum,
|
|
122
|
+
PayAmt: data.PayAmt,
|
|
123
|
+
NumberOfPayments: data.NumberOfPayments,
|
|
124
|
+
procNums: data.procNums,
|
|
125
|
+
adjNums: data.adjNums,
|
|
126
|
+
Guarantor: data.Guarantor,
|
|
127
|
+
PayPlanDate: data.PayPlanDate,
|
|
128
|
+
APR: data.APR,
|
|
129
|
+
DownPayment: data.DownPayment,
|
|
130
|
+
Note: data.Note,
|
|
131
|
+
PlanCategory: data.PlanCategory,
|
|
132
|
+
ChargeFrequency: data.ChargeFrequency,
|
|
133
|
+
DatePayPlanStart: data.DatePayPlanStart,
|
|
134
|
+
DateInterestStart: data.DateInterestStart,
|
|
135
|
+
IsLocked: data.IsLocked,
|
|
136
|
+
DynamicPayPlanTPOption: data.DynamicPayPlanTPOption,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return this.httpClient.post<PayPlan>("/payplans/Dynamic", payload);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Create a patient payment plan (DEPRECATED as of 23.3.1).
|
|
144
|
+
* Mirrors POST /payplans
|
|
145
|
+
* Added in version 22.4.39, deprecated in 23.3.1
|
|
146
|
+
*
|
|
147
|
+
* @deprecated Use createDynamicPayPlan instead. This endpoint returns 410 Gone in newer versions.
|
|
148
|
+
*
|
|
149
|
+
* Required:
|
|
150
|
+
* - PatNum
|
|
151
|
+
* - useEstBalance OR principalAmount
|
|
152
|
+
* - PayAmt OR NumberOfPayments
|
|
153
|
+
*/
|
|
154
|
+
public async createPayPlan(data: CreatePayPlanParams): Promise<PayPlan> {
|
|
155
|
+
console.warn(
|
|
156
|
+
"Warning: createPayPlan is deprecated as of version 23.3.1. Use createDynamicPayPlan instead."
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Validate required fields
|
|
160
|
+
if (!data || typeof data !== "object") {
|
|
161
|
+
throw new Error(
|
|
162
|
+
"Invalid payload: createPayPlan requires a request body."
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (!data.PatNum || typeof data.PatNum !== "number") {
|
|
167
|
+
throw new Error(
|
|
168
|
+
"Invalid payload: PatNum is required and must be a number."
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Either useEstBalance OR principalAmount is required
|
|
173
|
+
if (
|
|
174
|
+
data.useEstBalance === undefined &&
|
|
175
|
+
data.principalAmount === undefined
|
|
176
|
+
) {
|
|
177
|
+
throw new Error(
|
|
178
|
+
"Invalid payload: Either useEstBalance or principalAmount is required."
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Either PayAmt OR NumberOfPayments is required
|
|
183
|
+
if (!data.PayAmt && !data.NumberOfPayments) {
|
|
184
|
+
throw new Error(
|
|
185
|
+
"Invalid payload: Either PayAmt or NumberOfPayments is required."
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const payload = clean({
|
|
190
|
+
PatNum: data.PatNum,
|
|
191
|
+
useEstBalance: data.useEstBalance,
|
|
192
|
+
principalAmount: data.principalAmount,
|
|
193
|
+
PayAmt: data.PayAmt,
|
|
194
|
+
NumberOfPayments: data.NumberOfPayments,
|
|
195
|
+
Guarantor: data.Guarantor,
|
|
196
|
+
PayPlanDate: data.PayPlanDate,
|
|
197
|
+
APR: data.APR,
|
|
198
|
+
DownPayment: data.DownPayment,
|
|
199
|
+
Note: data.Note,
|
|
200
|
+
PlanCategory: data.PlanCategory,
|
|
201
|
+
ChargeFrequency: data.ChargeFrequency,
|
|
202
|
+
DatePayPlanStart: data.DatePayPlanStart,
|
|
203
|
+
DateInterestStart: data.DateInterestStart,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return this.httpClient.post<PayPlan>("/payplans", payload);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Close a payment plan and charge any outstanding interest.
|
|
211
|
+
* Mirrors PUT /payplans/{PayPlanNum}/Close
|
|
212
|
+
* Added in version 22.4.39
|
|
213
|
+
*/
|
|
214
|
+
public async closePayPlan({
|
|
215
|
+
PayPlanNum,
|
|
216
|
+
}: ClosePayPlanParams): Promise<PayPlan> {
|
|
217
|
+
if (!PayPlanNum || typeof PayPlanNum !== "number") {
|
|
218
|
+
throw new Error(
|
|
219
|
+
"Invalid parameter: PayPlanNum is required and must be a number."
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return this.httpClient.put<PayPlan>(
|
|
224
|
+
`/payplans/${PayPlanNum}/Close`,
|
|
225
|
+
{}
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Update an existing dynamic payment plan.
|
|
231
|
+
* Mirrors PUT /payplans/{PayPlanNum}/Dynamic
|
|
232
|
+
* Added in version 25.3.31
|
|
233
|
+
*
|
|
234
|
+
* All fields except PayPlanNum are optional; send only what you intend to change.
|
|
235
|
+
*/
|
|
236
|
+
public async updateDynamicPayPlan(
|
|
237
|
+
data: UpdateDynamicPayPlanParams
|
|
238
|
+
): Promise<PayPlan> {
|
|
239
|
+
if (!data?.PayPlanNum || typeof data.PayPlanNum !== "number") {
|
|
240
|
+
throw new Error(
|
|
241
|
+
"Invalid payload: PayPlanNum is required and must be a number."
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Validate APR and IsLocked relationship
|
|
246
|
+
if (data.APR && data.APR > 0 && data.IsLocked === false) {
|
|
247
|
+
console.warn(
|
|
248
|
+
"Warning: When APR > 0, IsLocked may need to be true depending on Open Dental preferences."
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const { PayPlanNum, ...updateFields } = data;
|
|
253
|
+
|
|
254
|
+
const payload = clean({
|
|
255
|
+
PayAmt: updateFields.PayAmt,
|
|
256
|
+
NumberOfPayments: updateFields.NumberOfPayments,
|
|
257
|
+
Guarantor: updateFields.Guarantor,
|
|
258
|
+
PayPlanDate: updateFields.PayPlanDate,
|
|
259
|
+
APR: updateFields.APR,
|
|
260
|
+
Note: updateFields.Note,
|
|
261
|
+
PlanCategory: updateFields.PlanCategory,
|
|
262
|
+
ChargeFrequency: updateFields.ChargeFrequency,
|
|
263
|
+
DatePayPlanStart: updateFields.DatePayPlanStart,
|
|
264
|
+
DateInterestStart: updateFields.DateInterestStart,
|
|
265
|
+
IsLocked: updateFields.IsLocked,
|
|
266
|
+
SheetDefNum: updateFields.SheetDefNum,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
return this.httpClient.put<PayPlan>(
|
|
270
|
+
`/payplans/${PayPlanNum}/Dynamic`,
|
|
271
|
+
payload
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
}
|
package/src/openDental.ts
CHANGED
|
@@ -13,6 +13,8 @@ import Providers from "./api/providers";
|
|
|
13
13
|
import Operatories from "./api/operatories";
|
|
14
14
|
import Payments from "./api/payments";
|
|
15
15
|
import PaySplits from "./api/paySplits";
|
|
16
|
+
import PayPlans from "./api/payPlans";
|
|
17
|
+
import PayPlanCharges from "./api/payPlanCharges";
|
|
16
18
|
import Definitions from "./api/definitions";
|
|
17
19
|
import DiscountPlans from "./api/discountPlans";
|
|
18
20
|
import DiscountPlanSubs from "./api/discountPlanSubs";
|
|
@@ -350,6 +352,26 @@ class OpenDental {
|
|
|
350
352
|
return new PaySplits(this.httpClient);
|
|
351
353
|
}
|
|
352
354
|
|
|
355
|
+
/**
|
|
356
|
+
* Create a new instance of the PayPlans API.
|
|
357
|
+
*/
|
|
358
|
+
public static PayPlans() {
|
|
359
|
+
if (!this.httpClient) {
|
|
360
|
+
throw new Error("OpenDental not initialized. Call OpenDental.initialize() first.");
|
|
361
|
+
}
|
|
362
|
+
return new PayPlans(this.httpClient);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Create a new instance of the PayPlanCharges API.
|
|
367
|
+
*/
|
|
368
|
+
public static PayPlanCharges() {
|
|
369
|
+
if (!this.httpClient) {
|
|
370
|
+
throw new Error("OpenDental not initialized. Call OpenDental.initialize() first.");
|
|
371
|
+
}
|
|
372
|
+
return new PayPlanCharges(this.httpClient);
|
|
373
|
+
}
|
|
374
|
+
|
|
353
375
|
/**
|
|
354
376
|
* Create a new instance of the Fees API.
|
|
355
377
|
*/
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPlanCharge types for Open Dental REST API
|
|
3
|
+
* Spec refs:
|
|
4
|
+
* - https://www.opendental.com/site/apipayplancharges.html
|
|
5
|
+
*
|
|
6
|
+
* Notes:
|
|
7
|
+
* - Dates are strings from the API (yyyy-MM-dd or yyyy-MM-dd HH:mm:ss).
|
|
8
|
+
* - PayPlanCharges represent individual charges within a payment plan
|
|
9
|
+
* - Each charge can be a debit (payment due) or credit (payment received)
|
|
10
|
+
* @see https://www.opendental.com/site/apipayplancharges.html
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Charge type for payment plan charges */
|
|
14
|
+
export type ChargeType = "Debit" | "Credit";
|
|
15
|
+
|
|
16
|
+
/** Link type for payment plan charges */
|
|
17
|
+
export type LinkType =
|
|
18
|
+
| "Procedure"
|
|
19
|
+
| "Adjustment"
|
|
20
|
+
| "Payment"
|
|
21
|
+
| "None"
|
|
22
|
+
| string; // Open to allow for other types
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Represents a PayPlanCharge returned by the Open Dental API.
|
|
26
|
+
* Mirrors the response payload of GET endpoints.
|
|
27
|
+
*/
|
|
28
|
+
export interface PayPlanCharge {
|
|
29
|
+
PayPlanChargeNum: number; // PK - Unique charge identifier
|
|
30
|
+
PayPlanNum: number; // FK to payplan.PayPlanNum
|
|
31
|
+
Guarantor: number; // FK to patient.PatNum (guarantor)
|
|
32
|
+
PatNum: number; // FK to patient.PatNum
|
|
33
|
+
ChargeDate: string; // "yyyy-MM-dd" - Date of charge
|
|
34
|
+
Principal: number; // Principal amount (decimal)
|
|
35
|
+
Interest: number; // Interest amount (decimal)
|
|
36
|
+
Note: string; // Optional note for the charge
|
|
37
|
+
ProvNum: number; // FK to provider.ProvNum
|
|
38
|
+
ClinicNum: number; // FK to clinic.ClinicNum
|
|
39
|
+
ChargeType: ChargeType; // Type of charge ("Debit" | "Credit")
|
|
40
|
+
ProcNum: number; // FK to procedurelog.ProcNum
|
|
41
|
+
SecDateTEntry: string; // "yyyy-MM-dd HH:mm:ss" - Entry timestamp
|
|
42
|
+
SecDateTEdit: string; // "yyyy-MM-dd HH:mm:ss" - Last edit timestamp
|
|
43
|
+
StatementNum: number; // FK to statement.StatementNum
|
|
44
|
+
FKey: number; // Foreign key reference (context-dependent)
|
|
45
|
+
LinkType: LinkType; // Link type (e.g., "Procedure", "Adjustment")
|
|
46
|
+
IsOffset: boolean; // Whether this is an offset charge
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** GET /payplancharges query params */
|
|
50
|
+
export interface GetPayPlanChargesParams {
|
|
51
|
+
/** Payment plan number - Required */
|
|
52
|
+
PayPlanNum: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Minimal helper to detect "zero" dates in responses */
|
|
56
|
+
export const isZeroDate = (d?: string | null): boolean =>
|
|
57
|
+
!d || d === "0001-01-01";
|
|
58
|
+
|
|
59
|
+
/** Narrow helper for timestamps that can be zeroed by the API */
|
|
60
|
+
export const isZeroDateTime = (d?: string | null): boolean =>
|
|
61
|
+
!d || d.startsWith("0001-01-01");
|
|
62
|
+
|
|
63
|
+
/** Runtime guard for ChargeType values */
|
|
64
|
+
export const isChargeType = (s: string): s is ChargeType =>
|
|
65
|
+
["Debit", "Credit"].includes(s);
|
|
66
|
+
|
|
67
|
+
/** Helper to determine if a charge is a debit (payment due) */
|
|
68
|
+
export const isDebitCharge = (charge: PayPlanCharge): boolean =>
|
|
69
|
+
charge.ChargeType === "Debit";
|
|
70
|
+
|
|
71
|
+
/** Helper to determine if a charge is a credit (payment received) */
|
|
72
|
+
export const isCreditCharge = (charge: PayPlanCharge): boolean =>
|
|
73
|
+
charge.ChargeType === "Credit";
|
|
74
|
+
|
|
75
|
+
/** Helper to calculate total charge amount (principal + interest) */
|
|
76
|
+
export const getTotalChargeAmount = (charge: PayPlanCharge): number =>
|
|
77
|
+
charge.Principal + charge.Interest;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPlan types for Open Dental REST API
|
|
3
|
+
* Spec refs:
|
|
4
|
+
* - https://www.opendental.com/site/apipayplans.html
|
|
5
|
+
*
|
|
6
|
+
* Notes:
|
|
7
|
+
* - Dates are strings from the API (yyyy-MM-dd or yyyy-MM-dd HH:mm:ss).
|
|
8
|
+
* - Prior to 23.3.1, Open Dental users had the ability to create both Patient Payment Plans and Dynamic Payment Plans.
|
|
9
|
+
* - In version 23.3.1, Open Dental deprecated Patient Payment Plans, renaming them to Old Payment Plans in the UI.
|
|
10
|
+
* - The PayPlans POST (create) method was also deprecated at that time.
|
|
11
|
+
* - Dynamic Payment Plans are now referred to simply as Payment Plans in Open Dental.
|
|
12
|
+
* - Insurance payment plans have PlanNum and InsSubNum values greater than zero
|
|
13
|
+
* @see https://www.opendental.com/site/apipayplans.html
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** Charge frequency for payment plans */
|
|
17
|
+
export type ChargeFrequency =
|
|
18
|
+
| "Weekly"
|
|
19
|
+
| "EveryOtherWeek"
|
|
20
|
+
| "Monthly"
|
|
21
|
+
| "Quarterly"
|
|
22
|
+
| "OrdinalWeekday";
|
|
23
|
+
|
|
24
|
+
/** Dynamic payment plan treatment plan option */
|
|
25
|
+
export type DynamicPayPlanTPOption =
|
|
26
|
+
| "AwaitComplete"
|
|
27
|
+
| "TreatAsComplete"
|
|
28
|
+
| "None";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Represents a PayPlan returned by the Open Dental API.
|
|
32
|
+
* Mirrors the response payload of GET/POST/PUT endpoints.
|
|
33
|
+
*/
|
|
34
|
+
export interface PayPlan {
|
|
35
|
+
PayPlanNum: number; // PK
|
|
36
|
+
PatNum: number; // FK to patient.PatNum
|
|
37
|
+
Guarantor: number; // FK to patient.PatNum (guarantor)
|
|
38
|
+
PayPlanDate: string; // "yyyy-MM-dd" - Date of agreement
|
|
39
|
+
APR: number; // Annual percentage rate (decimal)
|
|
40
|
+
Note: string; // Payment plan note
|
|
41
|
+
PlanNum: number; // FK to insplan.PlanNum (0 for patient plans)
|
|
42
|
+
CompletedAmt: number; // Amount completed
|
|
43
|
+
InsSubNum: number; // FK to inssub.InsSubNum (0 for patient plans)
|
|
44
|
+
PaySchedule: number; // FK to schedule (if applicable)
|
|
45
|
+
NumberOfPayments: number; // Total number of payments
|
|
46
|
+
PayAmt: number; // Amount per payment
|
|
47
|
+
DownPayment: number; // Down payment amount
|
|
48
|
+
IsClosed: boolean; // Whether plan is closed
|
|
49
|
+
Signature: string; // Digital signature data
|
|
50
|
+
SigIsTopaz: boolean; // Whether signature is Topaz format
|
|
51
|
+
PlanCategory: number; // DefNum for plan category
|
|
52
|
+
IsDynamic: boolean; // Whether this is a dynamic payment plan
|
|
53
|
+
ChargeFrequency: ChargeFrequency; // Payment frequency
|
|
54
|
+
DatePayPlanStart: string; // "yyyy-MM-dd" - First payment due date
|
|
55
|
+
DynamicPayPlanTPOption: DynamicPayPlanTPOption; // TP option for dynamic plans
|
|
56
|
+
DateInterestStart: string; // "yyyy-MM-dd" - When interest starts accruing
|
|
57
|
+
IsLocked: boolean; // Lock status (required true if APR > 0)
|
|
58
|
+
SheetDefNum: number; // FK to sheetdef.SheetDefNum (custom sheet)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** GET /payplans (multiple) query params */
|
|
62
|
+
export interface GetPayPlansParams {
|
|
63
|
+
/** Patient number - mutually exclusive with Guarantor */
|
|
64
|
+
PatNum?: number;
|
|
65
|
+
/** Guarantor number - mutually exclusive with PatNum */
|
|
66
|
+
Guarantor?: number;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** GET /payplans/{PayPlanNum} - path parameter only */
|
|
70
|
+
export interface GetPayPlanByIdParams {
|
|
71
|
+
PayPlanNum: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* POST /payplans/Dynamic body
|
|
76
|
+
* Creates a dynamic payment plan
|
|
77
|
+
* Required: PatNum, (PayAmt OR NumberOfPayments), (procNums OR adjNums)
|
|
78
|
+
*/
|
|
79
|
+
export interface CreateDynamicPayPlanParams {
|
|
80
|
+
PatNum: number; // Required
|
|
81
|
+
PayAmt?: number; // Required if NumberOfPayments not provided
|
|
82
|
+
NumberOfPayments?: number; // Required if PayAmt not provided
|
|
83
|
+
procNums?: number[]; // Array of procedure numbers
|
|
84
|
+
adjNums?: number[]; // Array of adjustment numbers
|
|
85
|
+
Guarantor?: number; // FK to patient.PatNum
|
|
86
|
+
PayPlanDate?: string; // "yyyy-MM-dd" - defaults to today
|
|
87
|
+
APR?: number; // Annual percentage rate
|
|
88
|
+
DownPayment?: number; // Down payment amount
|
|
89
|
+
Note?: string; // Payment plan note
|
|
90
|
+
PlanCategory?: number; // DefNum for plan category
|
|
91
|
+
ChargeFrequency?: ChargeFrequency; // Payment frequency
|
|
92
|
+
DatePayPlanStart?: string; // "yyyy-MM-dd" - first payment due date
|
|
93
|
+
DateInterestStart?: string; // "yyyy-MM-dd" - when interest starts
|
|
94
|
+
IsLocked?: boolean; // Lock status (required true if APR > 0)
|
|
95
|
+
DynamicPayPlanTPOption?: DynamicPayPlanTPOption; // TP option
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* POST /payplans body (DEPRECATED as of 23.3.1)
|
|
100
|
+
* Use CreateDynamicPayPlanParams instead
|
|
101
|
+
* Creates an old-style patient payment plan
|
|
102
|
+
*/
|
|
103
|
+
export interface CreatePayPlanParams {
|
|
104
|
+
PatNum: number; // Required
|
|
105
|
+
useEstBalance?: boolean; // Use estimated balance
|
|
106
|
+
principalAmount?: number; // Principal amount
|
|
107
|
+
PayAmt?: number; // Required if NumberOfPayments not provided
|
|
108
|
+
NumberOfPayments?: number; // Required if PayAmt not provided
|
|
109
|
+
Guarantor?: number; // FK to patient.PatNum
|
|
110
|
+
PayPlanDate?: string; // "yyyy-MM-dd"
|
|
111
|
+
APR?: number; // Annual percentage rate
|
|
112
|
+
DownPayment?: number; // Down payment amount
|
|
113
|
+
Note?: string; // Payment plan note
|
|
114
|
+
PlanCategory?: number; // DefNum for plan category
|
|
115
|
+
ChargeFrequency?: ChargeFrequency; // Payment frequency
|
|
116
|
+
DatePayPlanStart?: string; // "yyyy-MM-dd"
|
|
117
|
+
DateInterestStart?: string; // "yyyy-MM-dd"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* PUT /payplans/{PayPlanNum}/Close
|
|
122
|
+
* Closes a payment plan and charges outstanding interest
|
|
123
|
+
*/
|
|
124
|
+
export interface ClosePayPlanParams {
|
|
125
|
+
PayPlanNum: number; // in URL
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* PUT /payplans/{PayPlanNum}/Dynamic
|
|
130
|
+
* Updates a dynamic payment plan
|
|
131
|
+
* All fields optional except PayPlanNum
|
|
132
|
+
*/
|
|
133
|
+
export interface UpdateDynamicPayPlanParams {
|
|
134
|
+
PayPlanNum: number; // Required (in URL)
|
|
135
|
+
PayAmt?: number; // Amount per payment
|
|
136
|
+
NumberOfPayments?: number; // Total number of payments
|
|
137
|
+
Guarantor?: number; // FK to patient.PatNum
|
|
138
|
+
PayPlanDate?: string; // "yyyy-MM-dd"
|
|
139
|
+
APR?: number; // Annual percentage rate
|
|
140
|
+
Note?: string; // Payment plan note
|
|
141
|
+
PlanCategory?: number; // DefNum for plan category
|
|
142
|
+
ChargeFrequency?: ChargeFrequency; // Payment frequency
|
|
143
|
+
DatePayPlanStart?: string; // "yyyy-MM-dd"
|
|
144
|
+
DateInterestStart?: string; // "yyyy-MM-dd"
|
|
145
|
+
IsLocked?: boolean; // Lock status
|
|
146
|
+
SheetDefNum?: number; // FK to sheetdef.SheetDefNum
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** Minimal helper to detect "zero" dates in responses */
|
|
150
|
+
export const isZeroDate = (d?: string | null): boolean =>
|
|
151
|
+
!d || d === "0001-01-01";
|
|
152
|
+
|
|
153
|
+
/** Narrow helper for timestamps that can be zeroed by the API */
|
|
154
|
+
export const isZeroDateTime = (d?: string | null): boolean =>
|
|
155
|
+
!d || d.startsWith("0001-01-01");
|
|
156
|
+
|
|
157
|
+
/** Runtime guard for ChargeFrequency values */
|
|
158
|
+
export const isChargeFrequency = (s: string): s is ChargeFrequency =>
|
|
159
|
+
["Weekly", "EveryOtherWeek", "Monthly", "Quarterly", "OrdinalWeekday"].includes(s);
|
|
160
|
+
|
|
161
|
+
/** Runtime guard for DynamicPayPlanTPOption values */
|
|
162
|
+
export const isDynamicPayPlanTPOption = (t: string): t is DynamicPayPlanTPOption =>
|
|
163
|
+
["AwaitComplete", "TreatAsComplete", "None"].includes(t);
|
|
164
|
+
|
|
165
|
+
/** Helper to determine if a PayPlan is an insurance payment plan */
|
|
166
|
+
export const isInsurancePayPlan = (payPlan: PayPlan): boolean =>
|
|
167
|
+
payPlan.PlanNum > 0 && payPlan.InsSubNum > 0;
|
|
168
|
+
|
|
169
|
+
/** Helper to determine if a PayPlan is a patient payment plan */
|
|
170
|
+
export const isPatientPayPlan = (payPlan: PayPlan): boolean =>
|
|
171
|
+
payPlan.PlanNum === 0 && payPlan.InsSubNum === 0;
|