@openmrs/esm-billing-app 1.1.2-pre.8 → 1.2.0

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.
Files changed (390) hide show
  1. package/.turbo/cache/31f1dfc7f71601df-meta.json +1 -0
  2. package/.turbo/cache/31f1dfc7f71601df.tar.zst +0 -0
  3. package/.turbo/turbo-build.log +13 -42
  4. package/__mocks__/bills.mock.ts +3 -2
  5. package/dist/1480.js +1 -0
  6. package/dist/1480.js.map +1 -0
  7. package/dist/1564.js +1 -0
  8. package/dist/1564.js.map +1 -0
  9. package/dist/1578.js +1 -0
  10. package/dist/1578.js.map +1 -0
  11. package/dist/1646.js +1 -0
  12. package/dist/1646.js.map +1 -0
  13. package/dist/1869.js +1 -0
  14. package/dist/1869.js.map +1 -0
  15. package/dist/1877.js +1 -0
  16. package/dist/1877.js.map +1 -0
  17. package/dist/1899.js +1 -0
  18. package/dist/1899.js.map +1 -0
  19. package/dist/196.js +2 -0
  20. package/dist/196.js.map +1 -0
  21. package/dist/2250.js +43 -0
  22. package/dist/2250.js.map +1 -0
  23. package/dist/2269.js +1 -0
  24. package/dist/2269.js.map +1 -0
  25. package/dist/2317.js +1 -0
  26. package/dist/2317.js.map +1 -0
  27. package/dist/2416.js +1 -0
  28. package/dist/2416.js.map +1 -0
  29. package/dist/2489.js +1 -0
  30. package/dist/2489.js.map +1 -0
  31. package/dist/282.js +1 -0
  32. package/dist/282.js.map +1 -0
  33. package/dist/2881.js +1 -0
  34. package/dist/2881.js.map +1 -0
  35. package/dist/2997.js +1 -0
  36. package/dist/2997.js.map +1 -0
  37. package/dist/3378.js +1 -0
  38. package/dist/3378.js.map +1 -0
  39. package/dist/3379.js +1 -0
  40. package/dist/3379.js.map +1 -0
  41. package/dist/3784.js +1 -0
  42. package/dist/3784.js.map +1 -0
  43. package/dist/3963.js +1 -0
  44. package/dist/3963.js.map +1 -0
  45. package/dist/4106.js +1 -0
  46. package/dist/4106.js.map +1 -0
  47. package/dist/4111.js +1 -0
  48. package/dist/4111.js.map +1 -0
  49. package/dist/434.js +1 -0
  50. package/dist/434.js.map +1 -0
  51. package/dist/4348.js +1 -0
  52. package/dist/4348.js.map +1 -0
  53. package/dist/4383.js +1 -0
  54. package/dist/4383.js.map +1 -0
  55. package/dist/4658.js +1 -0
  56. package/dist/4658.js.map +1 -0
  57. package/dist/4870.js +1 -0
  58. package/dist/4870.js.map +1 -0
  59. package/dist/4928.js +1 -0
  60. package/dist/4928.js.map +1 -0
  61. package/dist/5098.js +1 -0
  62. package/dist/5098.js.map +1 -0
  63. package/dist/5117.js +1 -0
  64. package/dist/5117.js.map +1 -0
  65. package/dist/5132.js +1 -0
  66. package/dist/5132.js.map +1 -0
  67. package/dist/5145.js +1 -0
  68. package/dist/5145.js.map +1 -0
  69. package/dist/5390.js +1 -0
  70. package/dist/5390.js.map +1 -0
  71. package/dist/5503.js +1 -0
  72. package/dist/5503.js.map +1 -0
  73. package/dist/556.js +1 -0
  74. package/dist/556.js.map +1 -0
  75. package/dist/5644.js +1 -0
  76. package/dist/5644.js.map +1 -0
  77. package/dist/5898.js +1 -0
  78. package/dist/5898.js.map +1 -0
  79. package/dist/5940.js +1 -0
  80. package/dist/5940.js.map +1 -0
  81. package/dist/6047.js +1 -0
  82. package/dist/6047.js.map +1 -0
  83. package/dist/6237.js +1 -0
  84. package/dist/6237.js.map +1 -0
  85. package/dist/6362.js +1 -0
  86. package/dist/6362.js.map +1 -0
  87. package/dist/6371.js +1 -0
  88. package/dist/6371.js.map +1 -0
  89. package/dist/6377.js +1 -0
  90. package/dist/6377.js.map +1 -0
  91. package/dist/6444.js +1 -0
  92. package/dist/6444.js.map +1 -0
  93. package/dist/6508.js +1 -0
  94. package/dist/6508.js.map +1 -0
  95. package/dist/6594.js +1 -0
  96. package/dist/6594.js.map +1 -0
  97. package/dist/6724.js +1 -0
  98. package/dist/6724.js.map +1 -0
  99. package/dist/6904.js +1 -0
  100. package/dist/6904.js.map +1 -0
  101. package/dist/7045.js +1 -0
  102. package/dist/7045.js.map +1 -0
  103. package/dist/7175.js +1 -0
  104. package/dist/7175.js.map +1 -0
  105. package/dist/7182.js +1 -0
  106. package/dist/7182.js.map +1 -0
  107. package/dist/7247.js +1 -0
  108. package/dist/7247.js.map +1 -0
  109. package/dist/7742.js +1 -0
  110. package/dist/7742.js.map +1 -0
  111. package/dist/7912.js +1 -0
  112. package/dist/7912.js.map +1 -0
  113. package/dist/8358.js +1 -0
  114. package/dist/8358.js.map +1 -0
  115. package/dist/8359.js +1 -0
  116. package/dist/8359.js.map +1 -0
  117. package/dist/8695.js +1 -0
  118. package/dist/8695.js.map +1 -0
  119. package/dist/903.js +1 -0
  120. package/dist/903.js.map +1 -0
  121. package/dist/9072.js +1 -0
  122. package/dist/9072.js.map +1 -0
  123. package/dist/9414.js +1 -0
  124. package/dist/9414.js.map +1 -0
  125. package/dist/9655.js +11 -0
  126. package/dist/9655.js.map +1 -0
  127. package/dist/9806.js +1 -0
  128. package/dist/9806.js.map +1 -0
  129. package/dist/990.js +1 -0
  130. package/dist/990.js.map +1 -0
  131. package/dist/main.js +17 -2
  132. package/dist/main.js.map +1 -1
  133. package/dist/openmrs-esm-billing-app.js +6 -1
  134. package/dist/openmrs-esm-billing-app.js.buildmanifest.json +643 -436
  135. package/dist/openmrs-esm-billing-app.js.map +1 -1
  136. package/dist/routes.json +1 -1
  137. package/e2e/commands/billing-operations.ts +21 -0
  138. package/e2e/commands/types.ts +9 -1
  139. package/e2e/pages/discounts-page.ts +75 -0
  140. package/e2e/pages/index.ts +1 -0
  141. package/e2e/pages/invoice-page.ts +7 -7
  142. package/e2e/specs/bill-discounts.spec.ts +255 -0
  143. package/e2e/specs/billing-dashboard.spec.ts +3 -3
  144. package/e2e/specs/billing-patient-chart.spec.ts +2 -2
  145. package/package.json +13 -22
  146. package/rspack.config.js +1 -0
  147. package/src/bill-history/bill-action-menu.component.tsx +20 -2
  148. package/src/bill-history/bill-history.test.tsx +23 -22
  149. package/src/bill-item-actions/edit-bill-item.modal.tsx +1 -1
  150. package/src/bill-item-actions/edit-bill-item.test.tsx +29 -27
  151. package/src/billable-services/billable-service-form/billable-service-form.test.tsx +74 -73
  152. package/src/billable-services/billable-services-home.component.tsx +4 -2
  153. package/src/billable-services/billable-services.test.tsx +8 -7
  154. package/src/billable-services/dashboard/dashboard.test.tsx +3 -2
  155. package/src/billable-services-admin-card-link.test.tsx +2 -1
  156. package/src/billing-dashboard/billing-dashboard.test.tsx +19 -3
  157. package/src/billing-form/billing-checkin-form.component.tsx +7 -3
  158. package/src/billing-form/billing-checkin-form.test.tsx +22 -21
  159. package/src/billing-form/billing-form.resource.test.ts +7 -6
  160. package/src/billing-form/billing-form.test.tsx +77 -40
  161. package/src/billing-form/billing-form.workspace.tsx +25 -6
  162. package/src/billing-form/visit-attributes/visit-attributes-form.component.tsx +6 -2
  163. package/src/billing.resource.test.ts +43 -41
  164. package/src/billing.resource.ts +65 -16
  165. package/src/bills-table/bills-table.component.tsx +15 -4
  166. package/src/bills-table/bills-table.test.tsx +72 -71
  167. package/src/config-schema.ts +0 -7
  168. package/src/discounts/admin/discount-requests-left-panel-link.component.tsx +43 -0
  169. package/src/discounts/admin/discount-requests.component.tsx +316 -0
  170. package/src/discounts/admin/discount-requests.scss +133 -0
  171. package/src/discounts/admin/discount-requests.test.tsx +104 -0
  172. package/src/discounts/admin/review-bill-discounts/bill-line-items-table/bill-line-items-table.component.tsx +42 -0
  173. package/src/discounts/admin/review-bill-discounts/bill-line-items-table/bill-line-items-table.scss +76 -0
  174. package/src/discounts/admin/review-bill-discounts/bill-payments-table/bill-payments-table.component.tsx +50 -0
  175. package/src/discounts/admin/review-bill-discounts/bill-payments-table/bill-payments-table.scss +63 -0
  176. package/src/discounts/admin/review-bill-discounts/bill-receipt-rail/bill-receipt-rail.component.tsx +73 -0
  177. package/src/discounts/admin/review-bill-discounts/bill-receipt-rail/bill-receipt-rail.scss +54 -0
  178. package/src/discounts/admin/review-bill-discounts/bill-totals-summary/bill-totals-summary.component.tsx +95 -0
  179. package/src/discounts/admin/review-bill-discounts/bill-totals-summary/bill-totals-summary.scss +128 -0
  180. package/src/discounts/admin/review-bill-discounts/discount-card/discount-card.component.tsx +158 -0
  181. package/src/discounts/admin/review-bill-discounts/discount-card/discount-card.scss +164 -0
  182. package/src/discounts/admin/review-bill-discounts/discount-review-stack/discount-review-stack.component.tsx +86 -0
  183. package/src/discounts/admin/review-bill-discounts/discount-review-stack/discount-review-stack.scss +40 -0
  184. package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.scss +14 -0
  185. package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.test.tsx +153 -0
  186. package/src/discounts/admin/review-bill-discounts/review-bill-discounts.modal.tsx +167 -0
  187. package/src/discounts/admin/review-bill-discounts/review-bill-discounts.utils.ts +42 -0
  188. package/src/discounts/discounts-table.component.tsx +109 -0
  189. package/src/discounts/discounts-table.scss +37 -0
  190. package/src/discounts/discounts-table.test.tsx +67 -0
  191. package/src/discounts/discounts.resource.ts +71 -0
  192. package/src/discounts/request-discount.modal.scss +88 -0
  193. package/src/discounts/request-discount.modal.test.tsx +161 -0
  194. package/src/discounts/request-discount.modal.tsx +253 -0
  195. package/src/index.ts +52 -21
  196. package/src/invoice/invoice-table.component.tsx +116 -18
  197. package/src/invoice/invoice-table.test.tsx +165 -13
  198. package/src/invoice/invoice.component.tsx +111 -7
  199. package/src/invoice/invoice.test.tsx +366 -66
  200. package/src/invoice/line-item-action-menu.component.tsx +31 -1
  201. package/src/invoice/payments/payment-form/payment-form.test.tsx +20 -19
  202. package/src/invoice/payments/payment-history/payment-history.test.tsx +13 -10
  203. package/src/invoice/payments/payments.component.tsx +20 -6
  204. package/src/invoice/payments/payments.test.tsx +88 -23
  205. package/src/invoice/printable-invoice/print-receipt.test.tsx +10 -28
  206. package/src/invoice/printable-invoice/printable-footer.test.tsx +5 -4
  207. package/src/invoice/printable-invoice/printable-invoice-header.component.tsx +3 -3
  208. package/src/invoice/printable-invoice/printable-invoice-header.test.tsx +26 -11
  209. package/src/invoice/printable-invoice/printable-invoice.component.tsx +38 -15
  210. package/src/left-panel-link.test.tsx +3 -3
  211. package/src/metrics-cards/metrics-cards.test.tsx +11 -10
  212. package/src/modal/delete-bill-confirmation.modal.test.tsx +134 -0
  213. package/src/modal/delete-bill-confirmation.modal.tsx +98 -0
  214. package/src/modal/delete-line-item-confirmation.modal.test.tsx +11 -9
  215. package/src/modal/finalize-bill-confirmation.modal.test.tsx +10 -8
  216. package/src/modal/require-payment-modal.test.tsx +12 -11
  217. package/src/payment-status-tag/payment-status-tag.component.tsx +50 -0
  218. package/src/payment-status-tag/payment-status-tag.scss +6 -0
  219. package/src/payment-status-tag/payment-status-tag.test.tsx +113 -0
  220. package/src/refunds/admin/refund-requests-left-panel-link.component.tsx +43 -0
  221. package/src/refunds/admin/refund-requests.component.tsx +324 -0
  222. package/src/refunds/admin/refund-requests.scss +133 -0
  223. package/src/refunds/admin/refund-requests.test.tsx +99 -0
  224. package/src/refunds/admin/review-bill-refunds/bill-line-items-table/bill-line-items-table.component.tsx +42 -0
  225. package/src/refunds/admin/review-bill-refunds/bill-line-items-table/bill-line-items-table.scss +76 -0
  226. package/src/refunds/admin/review-bill-refunds/bill-payments-table/bill-payments-table.component.tsx +50 -0
  227. package/src/refunds/admin/review-bill-refunds/bill-payments-table/bill-payments-table.scss +63 -0
  228. package/src/refunds/admin/review-bill-refunds/bill-receipt-rail/bill-receipt-rail.component.tsx +84 -0
  229. package/src/refunds/admin/review-bill-refunds/bill-receipt-rail/bill-receipt-rail.scss +54 -0
  230. package/src/refunds/admin/review-bill-refunds/bill-totals-summary/bill-totals-summary.component.tsx +83 -0
  231. package/src/refunds/admin/review-bill-refunds/bill-totals-summary/bill-totals-summary.scss +65 -0
  232. package/src/refunds/admin/review-bill-refunds/refund-card/refund-card.component.tsx +170 -0
  233. package/src/refunds/admin/review-bill-refunds/refund-card/refund-card.scss +155 -0
  234. package/src/refunds/admin/review-bill-refunds/refund-review-stack/refund-review-stack.component.tsx +86 -0
  235. package/src/refunds/admin/review-bill-refunds/refund-review-stack/refund-review-stack.scss +40 -0
  236. package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.scss +14 -0
  237. package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.test.tsx +313 -0
  238. package/src/refunds/admin/review-bill-refunds/review-bill-refunds.modal.tsx +188 -0
  239. package/src/refunds/admin/review-bill-refunds/review-bill-refunds.utils.ts +66 -0
  240. package/src/refunds/refunds-table.component.tsx +137 -0
  241. package/src/refunds/refunds-table.scss +37 -0
  242. package/src/refunds/refunds-table.test.tsx +105 -0
  243. package/src/refunds/refunds.resource.test.ts +44 -0
  244. package/src/refunds/refunds.resource.ts +42 -0
  245. package/src/refunds/refunds.types.test.ts +15 -0
  246. package/src/refunds/request-refund.modal.scss +84 -0
  247. package/src/refunds/request-refund.modal.test.tsx +204 -0
  248. package/src/refunds/request-refund.modal.tsx +218 -0
  249. package/src/routes.json +36 -2
  250. package/src/types/index.ts +116 -1
  251. package/src/visit-bills/visit-bills-panel.component.tsx +151 -0
  252. package/src/visit-bills/visit-bills-panel.scss +31 -0
  253. package/src/visit-bills/visit-bills-panel.test.tsx +113 -0
  254. package/tools/empty-module.ts +1 -0
  255. package/tools/setup-tests.ts +9 -9
  256. package/translations/am.json +154 -16
  257. package/translations/ar.json +154 -16
  258. package/translations/ar_SY.json +154 -16
  259. package/translations/bn.json +154 -16
  260. package/translations/cs.json +154 -16
  261. package/translations/de.json +154 -16
  262. package/translations/en.json +154 -16
  263. package/translations/en_US.json +154 -16
  264. package/translations/es.json +154 -16
  265. package/translations/es_MX.json +154 -16
  266. package/translations/fr.json +154 -16
  267. package/translations/he.json +154 -16
  268. package/translations/hi.json +154 -16
  269. package/translations/hi_IN.json +154 -16
  270. package/translations/id.json +154 -16
  271. package/translations/it.json +154 -16
  272. package/translations/ka.json +154 -16
  273. package/translations/km.json +154 -16
  274. package/translations/ku.json +154 -16
  275. package/translations/ky.json +154 -16
  276. package/translations/lg.json +154 -16
  277. package/translations/ne.json +154 -16
  278. package/translations/pl.json +154 -16
  279. package/translations/pt.json +154 -16
  280. package/translations/pt_BR.json +154 -16
  281. package/translations/qu.json +154 -16
  282. package/translations/ro_RO.json +154 -16
  283. package/translations/ru_RU.json +154 -16
  284. package/translations/si.json +154 -16
  285. package/translations/sq.json +154 -16
  286. package/translations/sw.json +154 -16
  287. package/translations/sw_KE.json +154 -16
  288. package/translations/tr.json +154 -16
  289. package/translations/tr_TR.json +154 -16
  290. package/translations/uk.json +154 -16
  291. package/translations/uz.json +154 -16
  292. package/translations/uz@Latn.json +154 -16
  293. package/translations/uz_UZ.json +154 -16
  294. package/translations/vi.json +154 -16
  295. package/translations/zh.json +154 -16
  296. package/translations/zh_CN.json +179 -41
  297. package/translations/zh_TW.json +154 -16
  298. package/tsconfig.json +3 -3
  299. package/vitest.config.js +28 -0
  300. package/.turbo/cache/6c998b0f30a031ab-meta.json +0 -1
  301. package/.turbo/cache/6c998b0f30a031ab.tar.zst +0 -0
  302. package/dist/1119.js +0 -1
  303. package/dist/1197.js +0 -1
  304. package/dist/1435.js +0 -1
  305. package/dist/1435.js.map +0 -1
  306. package/dist/1807.js +0 -1
  307. package/dist/1807.js.map +0 -1
  308. package/dist/2146.js +0 -1
  309. package/dist/2177.js +0 -2
  310. package/dist/2177.js.LICENSE.txt +0 -9
  311. package/dist/2177.js.map +0 -1
  312. package/dist/2690.js +0 -1
  313. package/dist/2704.js +0 -1
  314. package/dist/2704.js.map +0 -1
  315. package/dist/3002.js +0 -1
  316. package/dist/3002.js.map +0 -1
  317. package/dist/3041.js +0 -1
  318. package/dist/3041.js.map +0 -1
  319. package/dist/3099.js +0 -1
  320. package/dist/3184.js +0 -2
  321. package/dist/3184.js.LICENSE.txt +0 -14
  322. package/dist/3184.js.map +0 -1
  323. package/dist/3584.js +0 -1
  324. package/dist/4055.js +0 -1
  325. package/dist/4132.js +0 -1
  326. package/dist/4225.js +0 -1
  327. package/dist/4225.js.map +0 -1
  328. package/dist/4300.js +0 -1
  329. package/dist/4335.js +0 -1
  330. package/dist/439.js +0 -1
  331. package/dist/4618.js +0 -1
  332. package/dist/4652.js +0 -1
  333. package/dist/4944.js +0 -1
  334. package/dist/5173.js +0 -1
  335. package/dist/5241.js +0 -1
  336. package/dist/5422.js +0 -1
  337. package/dist/5422.js.map +0 -1
  338. package/dist/5442.js +0 -1
  339. package/dist/5661.js +0 -1
  340. package/dist/6022.js +0 -1
  341. package/dist/6404.js +0 -1
  342. package/dist/6404.js.map +0 -1
  343. package/dist/6468.js +0 -1
  344. package/dist/6540.js +0 -2
  345. package/dist/6540.js.LICENSE.txt +0 -9
  346. package/dist/6540.js.map +0 -1
  347. package/dist/6589.js +0 -1
  348. package/dist/6606.js +0 -1
  349. package/dist/6606.js.map +0 -1
  350. package/dist/6679.js +0 -1
  351. package/dist/6792.js +0 -1
  352. package/dist/6792.js.map +0 -1
  353. package/dist/6840.js +0 -1
  354. package/dist/6859.js +0 -1
  355. package/dist/7097.js +0 -1
  356. package/dist/7159.js +0 -1
  357. package/dist/723.js +0 -1
  358. package/dist/7255.js +0 -1
  359. package/dist/7255.js.map +0 -1
  360. package/dist/7617.js +0 -1
  361. package/dist/795.js +0 -1
  362. package/dist/8163.js +0 -1
  363. package/dist/8341.js +0 -2
  364. package/dist/8341.js.LICENSE.txt +0 -52
  365. package/dist/8341.js.map +0 -1
  366. package/dist/8349.js +0 -1
  367. package/dist/8371.js +0 -1
  368. package/dist/8421.js +0 -1
  369. package/dist/8421.js.map +0 -1
  370. package/dist/8618.js +0 -1
  371. package/dist/890.js +0 -1
  372. package/dist/9214.js +0 -1
  373. package/dist/9538.js +0 -1
  374. package/dist/9569.js +0 -1
  375. package/dist/961.js +0 -2
  376. package/dist/961.js.LICENSE.txt +0 -19
  377. package/dist/961.js.map +0 -1
  378. package/dist/986.js +0 -1
  379. package/dist/9879.js +0 -1
  380. package/dist/9895.js +0 -1
  381. package/dist/9900.js +0 -1
  382. package/dist/9913.js +0 -1
  383. package/dist/main.js.LICENSE.txt +0 -62
  384. package/src/billable-services/bill-waiver/bill-selection.component.tsx +0 -76
  385. package/src/billable-services/bill-waiver/bill-waiver-form.component.tsx +0 -107
  386. package/src/billable-services/bill-waiver/bill-waiver-form.scss +0 -34
  387. package/src/billable-services/bill-waiver/bill-waiver.component.tsx +0 -34
  388. package/src/billable-services/bill-waiver/bill-waiver.scss +0 -10
  389. package/src/billable-services/bill-waiver/patient-bills.component.tsx +0 -134
  390. package/webpack.config.js +0 -1
@@ -1,21 +1,22 @@
1
1
  import React from 'react';
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
3
  import userEvent from '@testing-library/user-event';
3
4
  import { render, screen, waitFor } from '@testing-library/react';
4
5
  import { usePaginatedBills } from '../billing.resource';
5
- import { BillStatus } from '../types';
6
+ import { BillLineItemStatus, BillStatus, type MappedBill } from '../types';
6
7
  import BillsTable from './bills-table.component';
7
8
 
8
- jest.mock('../billing.resource', () => ({
9
- usePaginatedBills: jest.fn(() => ({
9
+ vi.mock('../billing.resource', () => ({
10
+ usePaginatedBills: vi.fn(() => ({
10
11
  bills: mockBillsData,
11
12
  isLoading: false,
12
13
  isValidating: false,
13
14
  error: null,
14
- mutate: jest.fn(),
15
+ mutate: vi.fn(),
15
16
  })),
16
17
  }));
17
18
 
18
- const mockBills = jest.mocked(usePaginatedBills);
19
+ const mockBills = vi.mocked(usePaginatedBills);
19
20
 
20
21
  const mockBillsData = [
21
22
  {
@@ -23,7 +24,6 @@ const mockBillsData = [
23
24
  id: 1,
24
25
  patientName: 'John Doe',
25
26
  identifier: '12345678',
26
- visitType: 'Checkup',
27
27
  patientUuid: 'uuid1',
28
28
  dateCreated: '2024-01-01',
29
29
  lineItems: [
@@ -40,7 +40,7 @@ const mockBillsData = [
40
40
  priceUuid: 'price-1',
41
41
  lineItemOrder: 1,
42
42
  resourceVersion: '1.0',
43
- paymentStatus: 'PENDING',
43
+ status: BillLineItemStatus.PENDING,
44
44
  },
45
45
  ],
46
46
  status: BillStatus.PENDING,
@@ -52,6 +52,7 @@ const mockBillsData = [
52
52
  billingService: 'Service 1',
53
53
  payments: [],
54
54
  totalAmount: 100,
55
+ netAmount: 100,
55
56
  tenderedAmount: 0,
56
57
  },
57
58
  {
@@ -59,7 +60,6 @@ const mockBillsData = [
59
60
  id: 2,
60
61
  patientName: 'Mary Smith',
61
62
  identifier: '98765432',
62
- visitType: 'Wake up',
63
63
  patientUuid: 'uuid2',
64
64
  dateCreated: '2024-01-02',
65
65
  lineItems: [
@@ -76,7 +76,7 @@ const mockBillsData = [
76
76
  priceUuid: 'price-1',
77
77
  lineItemOrder: 1,
78
78
  resourceVersion: '1.0',
79
- paymentStatus: 'PENDING',
79
+ status: BillLineItemStatus.PENDING,
80
80
  },
81
81
  ],
82
82
  status: BillStatus.PENDING,
@@ -88,9 +88,10 @@ const mockBillsData = [
88
88
  billingService: 'Service 2',
89
89
  payments: [],
90
90
  totalAmount: 200,
91
+ netAmount: 200,
91
92
  tenderedAmount: 200,
92
93
  },
93
- ];
94
+ ] satisfies MappedBill[];
94
95
 
95
96
  describe('BillsTable', () => {
96
97
  beforeEach(() => {
@@ -99,14 +100,14 @@ describe('BillsTable', () => {
99
100
  isLoading: false,
100
101
  isValidating: false,
101
102
  error: null,
102
- mutate: jest.fn(),
103
+ mutate: vi.fn(),
103
104
  currentPage: 1,
104
105
  totalCount: 10,
105
- goTo: jest.fn(),
106
+ goTo: vi.fn(),
106
107
  }));
107
108
  });
108
109
 
109
- test('renders data table with pending bills', () => {
110
+ it('renders data table with pending bills', () => {
110
111
  render(<BillsTable />);
111
112
 
112
113
  expect(screen.getByText(/bill date/i)).toBeInTheDocument();
@@ -116,16 +117,16 @@ describe('BillsTable', () => {
116
117
  expect(screen.getByText(/12345678/i)).toBeInTheDocument();
117
118
  });
118
119
 
119
- test('displays empty state when there are no bills with default filter', () => {
120
+ it('displays empty state when there are no bills with default filter', () => {
120
121
  mockBills.mockImplementationOnce(() => ({
121
122
  bills: [],
122
123
  isLoading: false,
123
124
  isValidating: false,
124
125
  error: null,
125
- mutate: jest.fn(),
126
+ mutate: vi.fn(),
126
127
  currentPage: 1,
127
128
  totalCount: 0,
128
- goTo: jest.fn(),
129
+ goTo: vi.fn(),
129
130
  }));
130
131
 
131
132
  render(<BillsTable />);
@@ -136,35 +137,35 @@ describe('BillsTable', () => {
136
137
  expect(screen.getByRole('searchbox')).toBeInTheDocument();
137
138
  });
138
139
 
139
- test('should show the loading spinner while retrieving data', () => {
140
+ it('should show the loading spinner while retrieving data', () => {
140
141
  mockBills.mockImplementationOnce(() => ({
141
142
  bills: undefined,
142
143
  isLoading: true,
143
144
  isValidating: false,
144
145
  error: null,
145
- mutate: jest.fn(),
146
+ mutate: vi.fn(),
146
147
  currentPage: 1,
147
148
  totalCount: 0,
148
- goTo: jest.fn(),
149
+ goTo: vi.fn(),
149
150
  }));
150
151
 
151
152
  render(<BillsTable />);
152
153
 
153
- expect(screen.getByRole('progressbar')).toBeInTheDocument();
154
+ expect(screen.getByTestId('bills-table-skeleton')).toBeInTheDocument();
154
155
  expect(screen.getByText(/filter by/i)).toBeInTheDocument();
155
- expect(screen.getByText(/pending payment/i)).toBeInTheDocument();
156
+ expect(screen.getByText(/pending confirmation/i)).toBeInTheDocument();
156
157
  });
157
158
 
158
- test('should display an error state if there is a problem loading bill data', () => {
159
+ it('should display an error state if there is a problem loading bill data', () => {
159
160
  mockBills.mockImplementationOnce(() => ({
160
161
  bills: undefined,
161
162
  isLoading: false,
162
163
  isValidating: false,
163
164
  error: new Error('Error in fetching data'),
164
- mutate: jest.fn(),
165
+ mutate: vi.fn(),
165
166
  currentPage: 1,
166
167
  totalCount: 0,
167
- goTo: jest.fn(),
168
+ goTo: vi.fn(),
168
169
  }));
169
170
 
170
171
  render(<BillsTable />);
@@ -172,19 +173,19 @@ describe('BillsTable', () => {
172
173
  expect(screen.getByText(/error state/i)).toBeInTheDocument();
173
174
  expect(screen.queryByRole('table')).not.toBeInTheDocument();
174
175
  expect(screen.getByText(/filter by/i)).toBeInTheDocument();
175
- expect(screen.getByText(/pending payment/i)).toBeInTheDocument();
176
+ expect(screen.getByText(/pending confirmation/i)).toBeInTheDocument();
176
177
  });
177
178
 
178
- test('should pass search term to backend API', async () => {
179
+ it('should pass search term to backend API', async () => {
179
180
  const user = userEvent.setup();
180
- const mockGoTo = jest.fn();
181
+ const mockGoTo = vi.fn();
181
182
 
182
183
  mockBills.mockImplementation((_pageSize, _status, patientName) => ({
183
184
  bills: patientName === 'John' ? [mockBillsData[0]] : mockBillsData,
184
185
  isLoading: false,
185
186
  isValidating: false,
186
187
  error: null,
187
- mutate: jest.fn(),
188
+ mutate: vi.fn(),
188
189
  currentPage: 1,
189
190
  totalCount: patientName === 'John' ? 1 : 2,
190
191
  goTo: mockGoTo,
@@ -201,13 +202,13 @@ describe('BillsTable', () => {
201
202
  await user.type(searchInput, 'John');
202
203
 
203
204
  await waitFor(() => {
204
- expect(mockBills).toHaveBeenCalledWith(10, 'POSTED', 'John');
205
+ expect(mockBills).toHaveBeenCalledWith(10, 'PENDING', 'John');
205
206
  });
206
207
 
207
208
  expect(mockGoTo).toHaveBeenCalledWith(1);
208
209
  });
209
210
 
210
- test('should render invoice number as a link to the invoice page', () => {
211
+ it('should render invoice number as a link to the invoice page', () => {
211
212
  render(<BillsTable />);
212
213
 
213
214
  const invoiceNumberLink = screen.getByRole('link', { name: 'RCP-001' });
@@ -216,7 +217,7 @@ describe('BillsTable', () => {
216
217
  expect(invoiceNumberLink).toHaveAttribute('href', '/openmrs/spa/home/billing/patient/uuid1/1');
217
218
  });
218
219
 
219
- test('should filter bills by payment status', async () => {
220
+ it('should filter bills by payment status', async () => {
220
221
  const user = userEvent.setup();
221
222
 
222
223
  // First call: initial render with PENDING filter (default)
@@ -225,10 +226,10 @@ describe('BillsTable', () => {
225
226
  isLoading: false,
226
227
  isValidating: false,
227
228
  error: null,
228
- mutate: jest.fn(),
229
+ mutate: vi.fn(),
229
230
  currentPage: 1,
230
231
  totalCount: 2,
231
- goTo: jest.fn(),
232
+ goTo: vi.fn(),
232
233
  }));
233
234
 
234
235
  // Second call: after filter changes to PAID, return empty bills
@@ -237,15 +238,15 @@ describe('BillsTable', () => {
237
238
  isLoading: false,
238
239
  isValidating: false,
239
240
  error: null,
240
- mutate: jest.fn(),
241
+ mutate: vi.fn(),
241
242
  currentPage: 1,
242
243
  totalCount: 0,
243
- goTo: jest.fn(),
244
+ goTo: vi.fn(),
244
245
  }));
245
246
 
246
247
  render(<BillsTable />);
247
248
 
248
- const filterDropdown = screen.getByText('Pending payment');
249
+ const filterDropdown = screen.getByText('Pending confirmation');
249
250
  await user.click(filterDropdown);
250
251
 
251
252
  const paidBillsOption = screen.getAllByText('Paid bills')[0];
@@ -258,16 +259,16 @@ describe('BillsTable', () => {
258
259
  expect(screen.getByText(/check the filters above/i)).toBeInTheDocument();
259
260
  });
260
261
 
261
- test('should show loading state during background updates', () => {
262
+ it('should show loading state during background updates', () => {
262
263
  mockBills.mockImplementationOnce(() => ({
263
264
  bills: mockBillsData,
264
265
  isLoading: false,
265
266
  isValidating: true,
266
267
  error: null,
267
- mutate: jest.fn(),
268
+ mutate: vi.fn(),
268
269
  currentPage: 1,
269
270
  totalCount: 0,
270
- goTo: jest.fn(),
271
+ goTo: vi.fn(),
271
272
  }));
272
273
 
273
274
  render(<BillsTable />);
@@ -276,16 +277,16 @@ describe('BillsTable', () => {
276
277
  expect(loadingIndicator).toBeInTheDocument();
277
278
  });
278
279
 
279
- test('should show search box and empty state message when search returns no results', () => {
280
+ it('should show search box and empty state message when search returns no results', () => {
280
281
  mockBills.mockImplementationOnce(() => ({
281
282
  bills: [],
282
283
  isLoading: false,
283
284
  isValidating: false,
284
285
  error: null,
285
- mutate: jest.fn(),
286
+ mutate: vi.fn(),
286
287
  currentPage: 1,
287
288
  totalCount: 0,
288
- goTo: jest.fn(),
289
+ goTo: vi.fn(),
289
290
  }));
290
291
 
291
292
  render(<BillsTable />);
@@ -297,16 +298,16 @@ describe('BillsTable', () => {
297
298
  expect(screen.queryByText(/next page/i)).not.toBeInTheDocument();
298
299
  });
299
300
 
300
- test('should reset to page 1 when page size changes', async () => {
301
+ it('should reset to page 1 when page size changes', async () => {
301
302
  const user = userEvent.setup();
302
- const mockGoTo = jest.fn();
303
+ const mockGoTo = vi.fn();
303
304
 
304
305
  mockBills.mockImplementation(() => ({
305
306
  bills: mockBillsData,
306
307
  isLoading: false,
307
308
  isValidating: false,
308
309
  error: null,
309
- mutate: jest.fn(),
310
+ mutate: vi.fn(),
310
311
  currentPage: 3,
311
312
  totalCount: 100,
312
313
  goTo: mockGoTo,
@@ -326,60 +327,60 @@ describe('BillsTable', () => {
326
327
  });
327
328
  });
328
329
 
329
- test('should default to "Pending payment" filter showing POSTED bills', () => {
330
+ it('should default to "Pending confirmation" filter showing PENDING bills', () => {
330
331
  render(<BillsTable />);
331
332
 
332
- expect(screen.getByText('Pending payment')).toBeInTheDocument();
333
- expect(mockBills).toHaveBeenCalledWith(expect.any(Number), 'POSTED', undefined);
333
+ expect(screen.getByText('Pending confirmation')).toBeInTheDocument();
334
+ expect(mockBills).toHaveBeenCalledWith(expect.any(Number), 'PENDING', undefined);
334
335
  });
335
336
 
336
- test('should show "Pending confirmation" option in filter dropdown', async () => {
337
+ it('should show "Pending payment" option in filter dropdown', async () => {
337
338
  const user = userEvent.setup();
338
339
  render(<BillsTable />);
339
340
 
340
- const filterDropdown = screen.getByText('Pending payment');
341
+ const filterDropdown = screen.getByText('Pending confirmation');
341
342
  await user.click(filterDropdown);
342
343
 
343
- expect(screen.getByRole('option', { name: /pending confirmation/i })).toBeInTheDocument();
344
+ expect(screen.getByRole('option', { name: /pending payment/i })).toBeInTheDocument();
344
345
  });
345
346
 
346
- test('should filter by PENDING status when "Pending confirmation" is selected', async () => {
347
+ it('should filter by POSTED status when "Pending payment" is selected', async () => {
347
348
  const user = userEvent.setup();
348
- const mockGoTo = jest.fn();
349
+ const mockGoTo = vi.fn();
349
350
 
350
351
  mockBills.mockImplementation((_pageSize, status) => ({
351
- bills: status === 'PENDING' ? [mockBillsData[0]] : mockBillsData,
352
+ bills: status === 'POSTED' ? [mockBillsData[1]] : mockBillsData,
352
353
  isLoading: false,
353
354
  isValidating: false,
354
355
  error: null,
355
- mutate: jest.fn(),
356
+ mutate: vi.fn(),
356
357
  currentPage: 1,
357
- totalCount: status === 'PENDING' ? 1 : 2,
358
+ totalCount: status === 'POSTED' ? 1 : 2,
358
359
  goTo: mockGoTo,
359
360
  }));
360
361
 
361
362
  render(<BillsTable />);
362
363
 
363
- const filterDropdown = screen.getByText('Pending payment');
364
+ const filterDropdown = screen.getByText('Pending confirmation');
364
365
  await user.click(filterDropdown);
365
366
 
366
- await user.click(screen.getByRole('option', { name: /pending confirmation/i }));
367
+ await user.click(screen.getByRole('option', { name: /pending payment/i }));
367
368
 
368
369
  await waitFor(() => {
369
- expect(mockBills).toHaveBeenCalledWith(expect.any(Number), 'PENDING', undefined);
370
+ expect(mockBills).toHaveBeenCalledWith(expect.any(Number), 'POSTED', undefined);
370
371
  });
371
372
  });
372
373
 
373
- test('should filter by POSTED status when "Pending payment" is selected', async () => {
374
+ it('should filter by PENDING status when "Pending confirmation" is selected', async () => {
374
375
  const user = userEvent.setup();
375
- const mockGoTo = jest.fn();
376
+ const mockGoTo = vi.fn();
376
377
 
377
378
  mockBills.mockImplementation((_pageSize, status) => ({
378
- bills: status === 'POSTED' ? [mockBillsData[1]] : mockBillsData,
379
+ bills: status === 'PENDING' ? [mockBillsData[0]] : mockBillsData,
379
380
  isLoading: false,
380
381
  isValidating: false,
381
382
  error: null,
382
- mutate: jest.fn(),
383
+ mutate: vi.fn(),
383
384
  currentPage: 1,
384
385
  totalCount: 1,
385
386
  goTo: mockGoTo,
@@ -387,31 +388,31 @@ describe('BillsTable', () => {
387
388
 
388
389
  render(<BillsTable />);
389
390
 
390
- // Navigate away from the default POSTED filter first, then select it again
391
- const filterDropdown = screen.getByText('Pending payment');
391
+ // Navigate away from the default PENDING filter first, then select it again
392
+ const filterDropdown = screen.getByText('Pending confirmation');
392
393
  await user.click(filterDropdown);
393
394
  await user.click(screen.getByRole('option', { name: /all bills/i }));
394
395
 
395
396
  mockBills.mockClear();
396
397
 
397
398
  await user.click(screen.getByText('All bills'));
398
- await user.click(screen.getByRole('option', { name: /pending payment/i }));
399
+ await user.click(screen.getByRole('option', { name: /pending confirmation/i }));
399
400
 
400
401
  await waitFor(() => {
401
- expect(mockBills).toHaveBeenCalledWith(expect.any(Number), 'POSTED', undefined);
402
+ expect(mockBills).toHaveBeenCalledWith(expect.any(Number), 'PENDING', undefined);
402
403
  });
403
404
  });
404
405
 
405
- test('should keep data visible during subsequent loads', () => {
406
+ it('should keep data visible during subsequent loads', () => {
406
407
  mockBills.mockImplementationOnce(() => ({
407
408
  bills: mockBillsData,
408
409
  isLoading: true,
409
410
  isValidating: true,
410
411
  error: null,
411
- mutate: jest.fn(),
412
+ mutate: vi.fn(),
412
413
  currentPage: 2,
413
414
  totalCount: 50,
414
- goTo: jest.fn(),
415
+ goTo: vi.fn(),
415
416
  }));
416
417
 
417
418
  render(<BillsTable />);
@@ -424,6 +425,6 @@ describe('BillsTable', () => {
424
425
  expect(screen.getByTitle('loading')).toBeInTheDocument();
425
426
 
426
427
  // Should NOT show skeleton
427
- expect(screen.queryByRole('progressbar')).not.toBeInTheDocument();
428
+ expect(screen.queryByTestId('bills-table-skeleton')).not.toBeInTheDocument();
428
429
  });
429
430
  });
@@ -95,12 +95,6 @@ export const configSchema = {
95
95
  _description: 'The default page size',
96
96
  _default: 10,
97
97
  },
98
- waiverPaymentModeUuid: {
99
- _type: Type.String,
100
- _description:
101
- 'Payment Mode UUID used for bill waivers. This UUID identifies the payment mode (e.g. waiver) used when posting a waiver payment to a bill.',
102
- _default: 'eb6173cb-9678-4614-bbe1-0ccf7ed9d1d4',
103
- },
104
98
  };
105
99
 
106
100
  /**
@@ -141,5 +135,4 @@ export interface BillingConfig {
141
135
  };
142
136
  defaultCurrency: string;
143
137
  pageSize: number;
144
- waiverPaymentModeUuid: string;
145
138
  }
@@ -0,0 +1,43 @@
1
+ import React, { useMemo } from 'react';
2
+ import { BrowserRouter, useLocation } from 'react-router-dom';
3
+ import { useTranslation } from 'react-i18next';
4
+ import { SideNavLink } from '@carbon/react';
5
+ import { navigate } from '@openmrs/esm-framework';
6
+
7
+ export interface LinkConfig {
8
+ name: string;
9
+ title: string;
10
+ path: string;
11
+ icon?: React.ComponentType;
12
+ }
13
+
14
+ function DiscountRequestsLinkExtension({ config }: { config: LinkConfig }) {
15
+ const { title, path, icon: Icon } = config;
16
+ const { t } = useTranslation();
17
+ const location = useLocation();
18
+ const spaBasePath = `${window.spaBase}/billable-services`;
19
+
20
+ const isActive = useMemo(() => {
21
+ const currentPath = location.pathname.replace(spaBasePath, '');
22
+ if (path === '' || path === '/') {
23
+ return currentPath === '' || currentPath === '/';
24
+ }
25
+ return currentPath.startsWith(`/${path}`);
26
+ }, [location.pathname, path, spaBasePath]);
27
+
28
+ const handleNavigation = () => {
29
+ navigate({ to: `${spaBasePath}/${path}` });
30
+ };
31
+
32
+ return (
33
+ <SideNavLink onClick={handleNavigation} renderIcon={Icon} isActive={isActive}>
34
+ {t(title)}
35
+ </SideNavLink>
36
+ );
37
+ }
38
+
39
+ export const createDiscountRequestsLeftPanelLink = (config: LinkConfig) => () => (
40
+ <BrowserRouter>
41
+ <DiscountRequestsLinkExtension config={config} />
42
+ </BrowserRouter>
43
+ );