@ngockhoale/ukit 1.1.6

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 (344) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/LICENSE +21 -0
  3. package/README.md +189 -0
  4. package/bin/ukit +30 -0
  5. package/manifests/platform.full.yaml +1194 -0
  6. package/package.json +71 -0
  7. package/scripts/bug/triage.mjs +37 -0
  8. package/scripts/index/build-index.mjs +35 -0
  9. package/scripts/index/query-index.mjs +92 -0
  10. package/scripts/index/refresh-index.mjs +85 -0
  11. package/scripts/release/verify-release.mjs +56 -0
  12. package/src/bug/triageBug.js +123 -0
  13. package/src/cli/adapters.js +148 -0
  14. package/src/cli/commands/diff.js +51 -0
  15. package/src/cli/commands/doctor.js +125 -0
  16. package/src/cli/commands/indexArgs.js +73 -0
  17. package/src/cli/commands/indexTools.js +509 -0
  18. package/src/cli/commands/install.js +293 -0
  19. package/src/cli/commands/memory.js +126 -0
  20. package/src/cli/commands/status.js +8 -0
  21. package/src/cli/commands/uninstall.js +51 -0
  22. package/src/cli/index.js +109 -0
  23. package/src/context/detectProjectContext.js +49 -0
  24. package/src/context/detectProviders.js +12 -0
  25. package/src/core/applyPlan.js +89 -0
  26. package/src/core/buildPlan.js +228 -0
  27. package/src/core/compact/index.js +294 -0
  28. package/src/core/compact/threshold.js +936 -0
  29. package/src/core/diffPlan.js +73 -0
  30. package/src/core/ensureGitignore.js +117 -0
  31. package/src/core/fileOps.js +188 -0
  32. package/src/core/memory/hygiene.js +160 -0
  33. package/src/core/memory/index.js +2 -0
  34. package/src/core/memory/retrieval.js +476 -0
  35. package/src/core/memory/store.js +202 -0
  36. package/src/core/metadata.js +132 -0
  37. package/src/core/migrateLegacy.js +139 -0
  38. package/src/core/output/index.js +1309 -0
  39. package/src/core/paths.js +13 -0
  40. package/src/core/report.js +17 -0
  41. package/src/core/router/advisor.js +42 -0
  42. package/src/core/router/index.js +2 -0
  43. package/src/core/router/router.js +164 -0
  44. package/src/core/runInstallPipeline.js +365 -0
  45. package/src/core/runtimeConfig.js +190 -0
  46. package/src/core/runtimePaths.js +24 -0
  47. package/src/core/status.js +186 -0
  48. package/src/core/token/index.js +328 -0
  49. package/src/core/uninstall.js +246 -0
  50. package/src/core/validation/confidence.js +89 -0
  51. package/src/core/validation/index.js +2 -0
  52. package/src/core/validation/validator.js +165 -0
  53. package/src/index/buildIndex.js +1392 -0
  54. package/src/index/gitHooks.js +109 -0
  55. package/src/index/importResolution.js +377 -0
  56. package/src/index/languageTools.js +127 -0
  57. package/src/index/paths.js +27 -0
  58. package/src/index/queryIndex.js +637 -0
  59. package/src/index/relatedTests.js +237 -0
  60. package/src/index/resolveContext.js +345 -0
  61. package/src/index/routeCatalog.js +258 -0
  62. package/src/index/taskRouting.js +677 -0
  63. package/src/index/verificationPlan.js +437 -0
  64. package/src/manifest/loadManifest.js +22 -0
  65. package/src/manifest/selectItems.js +78 -0
  66. package/src/manifest/validateManifest.js +115 -0
  67. package/src/render/buildVariables.js +39 -0
  68. package/src/render/renderTemplate.js +44 -0
  69. package/src/stack/detectStack.js +213 -0
  70. package/templates/.claude/agents/bug-debugger.md +57 -0
  71. package/templates/.claude/agents/feature-implementer.md +55 -0
  72. package/templates/.claude/config/providers.md +25 -0
  73. package/templates/.claude/hooks/auto-allow-bash.sh +155 -0
  74. package/templates/.claude/hooks/auto-prune-bash.sh +75 -0
  75. package/templates/.claude/hooks/block-dangerous.sh +54 -0
  76. package/templates/.claude/hooks/compress-output.sh +17 -0
  77. package/templates/.claude/hooks/protect-files.sh +37 -0
  78. package/templates/.claude/hooks/reinject-context.sh +28 -0
  79. package/templates/.claude/hooks/session-start.md +13 -0
  80. package/templates/.claude/hooks/skill-router.sh +1681 -0
  81. package/templates/.claude/hooks/verification-guard.sh +271 -0
  82. package/templates/.claude/settings.json +144 -0
  83. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  84. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  85. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  86. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  87. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  88. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  89. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  90. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  91. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  92. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  93. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  94. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  95. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  96. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  97. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  98. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  99. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  100. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  101. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  102. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  103. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  104. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  105. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  106. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  107. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  108. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  109. package/templates/.claude/skills/_shared/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  110. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  111. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  112. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  113. package/templates/.claude/skills/_shared/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  114. package/templates/.claude/skills/_shared/ooxml/schemas/mce/mc.xsd +75 -0
  115. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  116. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  117. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  118. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  119. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  120. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  121. package/templates/.claude/skills/_shared/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  122. package/templates/.claude/skills/_shared/ooxml/scripts/pack.py +159 -0
  123. package/templates/.claude/skills/_shared/ooxml/scripts/unpack.py +29 -0
  124. package/templates/.claude/skills/_shared/ooxml/scripts/validate.py +69 -0
  125. package/templates/.claude/skills/_shared/ooxml/scripts/validation/__init__.py +15 -0
  126. package/templates/.claude/skills/_shared/ooxml/scripts/validation/base.py +951 -0
  127. package/templates/.claude/skills/_shared/ooxml/scripts/validation/docx.py +274 -0
  128. package/templates/.claude/skills/_shared/ooxml/scripts/validation/pptx.py +315 -0
  129. package/templates/.claude/skills/_shared/ooxml/scripts/validation/redlining.py +279 -0
  130. package/templates/.claude/skills/backend-api/SKILL.md +26 -0
  131. package/templates/.claude/skills/canvas-design/LICENSE.txt +202 -0
  132. package/templates/.claude/skills/canvas-design/SKILL.md +130 -0
  133. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  134. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  135. package/templates/.claude/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  136. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  137. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  138. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  139. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  140. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  141. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  142. package/templates/.claude/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  143. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  144. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  145. package/templates/.claude/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  146. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  147. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  148. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  149. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  150. package/templates/.claude/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  151. package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  152. package/templates/.claude/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  153. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  154. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  155. package/templates/.claude/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  156. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  157. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  158. package/templates/.claude/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  159. package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  160. package/templates/.claude/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  161. package/templates/.claude/skills/code-review/SKILL.md +97 -0
  162. package/templates/.claude/skills/debugging-toolkit/SKILL.md +156 -0
  163. package/templates/.claude/skills/delivery/SKILL.md +92 -0
  164. package/templates/.claude/skills/discover-security/SKILL.md +86 -0
  165. package/templates/.claude/skills/docker-packaging/SKILL.md +60 -0
  166. package/templates/.claude/skills/docs-manager/SKILL.md +465 -0
  167. package/templates/.claude/skills/docs-manager/init-project-docs.sh +70 -0
  168. package/templates/.claude/skills/docs-manager/templates/README.md.template +50 -0
  169. package/templates/.claude/skills/docs-manager/templates/agent-roles.md.template +24 -0
  170. package/templates/.claude/skills/docs-manager/templates/coding-conventions.md.template +28 -0
  171. package/templates/.claude/skills/docs-manager/templates/memory.md.template +30 -0
  172. package/templates/.claude/skills/docs-manager/templates/onboarding.md.template +20 -0
  173. package/templates/.claude/skills/docs-manager/templates/project.md.template +26 -0
  174. package/templates/.claude/skills/docs-quality/SKILL.md +148 -0
  175. package/templates/.claude/skills/docx/LICENSE.txt +30 -0
  176. package/templates/.claude/skills/docx/SKILL.md +197 -0
  177. package/templates/.claude/skills/docx/docx-js.md +350 -0
  178. package/templates/.claude/skills/docx/ooxml.md +610 -0
  179. package/templates/.claude/skills/docx/scripts/__init__.py +1 -0
  180. package/templates/.claude/skills/docx/scripts/document.py +1276 -0
  181. package/templates/.claude/skills/docx/scripts/templates/comments.xml +3 -0
  182. package/templates/.claude/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  183. package/templates/.claude/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  184. package/templates/.claude/skills/docx/scripts/templates/commentsIds.xml +3 -0
  185. package/templates/.claude/skills/docx/scripts/templates/people.xml +3 -0
  186. package/templates/.claude/skills/docx/scripts/utilities.py +374 -0
  187. package/templates/.claude/skills/duraone/SKILL.md +204 -0
  188. package/templates/.claude/skills/duraone/references/backend.md +636 -0
  189. package/templates/.claude/skills/duraone/references/frontend.md +1506 -0
  190. package/templates/.claude/skills/duraone/references/sql.md +631 -0
  191. package/templates/.claude/skills/duraone/references/workflow.md +520 -0
  192. package/templates/.claude/skills/executing-plans/SKILL.md +76 -0
  193. package/templates/.claude/skills/file-organizer/SKILL.md +433 -0
  194. package/templates/.claude/skills/frontend/SKILL.md +26 -0
  195. package/templates/.claude/skills/frontend-design/LICENSE.txt +177 -0
  196. package/templates/.claude/skills/frontend-design/SKILL.md +42 -0
  197. package/templates/.claude/skills/frontend-vue/SKILL.md +127 -0
  198. package/templates/.claude/skills/frontend-vue/components/Control/Box.vue +137 -0
  199. package/templates/.claude/skills/frontend-vue/components/Control/Button.vue +93 -0
  200. package/templates/.claude/skills/frontend-vue/components/Control/ButtonBar.vue +29 -0
  201. package/templates/.claude/skills/frontend-vue/components/Control/ButtonFloat.vue +62 -0
  202. package/templates/.claude/skills/frontend-vue/components/Control/CheckButton.vue +75 -0
  203. package/templates/.claude/skills/frontend-vue/components/Control/Checkbox.vue +58 -0
  204. package/templates/.claude/skills/frontend-vue/components/Control/Datetime.vue +148 -0
  205. package/templates/.claude/skills/frontend-vue/components/Control/Dropdownlist.vue +156 -0
  206. package/templates/.claude/skills/frontend-vue/components/Control/Input.vue +106 -0
  207. package/templates/.claude/skills/frontend-vue/components/Control/Label.vue +38 -0
  208. package/templates/.claude/skills/frontend-vue/components/Control/Master/BoxColumn.vue +24 -0
  209. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Confirm.vue +33 -0
  210. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Info.vue +32 -0
  211. package/templates/.claude/skills/frontend-vue/components/Control/Popup/ModalInfo.vue +39 -0
  212. package/templates/.claude/skills/frontend-vue/components/Control/Popup/Reject.vue +64 -0
  213. package/templates/.claude/skills/frontend-vue/components/Control/Tag.vue +82 -0
  214. package/templates/.claude/skills/frontend-vue/components/Control/Upload.vue +61 -0
  215. package/templates/.claude/skills/frontend-vue/components/ControlMobile/Dropdownlist.vue +103 -0
  216. package/templates/.claude/skills/frontend-vue/components/ControlMobile/PagingBar.vue +108 -0
  217. package/templates/.claude/skills/frontend-vue/components/ControlMobile/UploadImage.vue +137 -0
  218. package/templates/.claude/skills/frontend-vue/components/Grid/AG.vue +806 -0
  219. package/templates/.claude/skills/frontend-vue/components/Grid/AntTable.vue +253 -0
  220. package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditor.vue +43 -0
  221. package/templates/.claude/skills/frontend-vue/components/Grid/CustomDropdownEditorEnable.vue +55 -0
  222. package/templates/.claude/skills/frontend-vue/components/Grid/HtmlTable.vue +40 -0
  223. package/templates/.claude/skills/frontend-vue/components/PDFViewer.vue +25 -0
  224. package/templates/.claude/skills/frontend-vue/components/Panel/FormView.vue +309 -0
  225. package/templates/.claude/skills/frontend-vue/components/Partial/Footer.vue +23 -0
  226. package/templates/.claude/skills/frontend-vue/components/Partial/Header.vue +265 -0
  227. package/templates/.claude/skills/frontend-vue/components/Partial/Sidebar.vue +122 -0
  228. package/templates/.claude/skills/frontend-vue/components/Template.vue +16 -0
  229. package/templates/.claude/skills/frontend-vue/components/View/Form.vue +89 -0
  230. package/templates/.claude/skills/frontend-vue/composables/indexDBStore.js +140 -0
  231. package/templates/.claude/skills/frontend-vue/composables/masterApi.js +362 -0
  232. package/templates/.claude/skills/frontend-vue/composables/state.js +578 -0
  233. package/templates/.claude/skills/frontend-vue/composables/useRequest.js +221 -0
  234. package/templates/.claude/skills/frontend-vue/composables/useSession.js +179 -0
  235. package/templates/.claude/skills/frontend-vue/composables/useTranslation.js +54 -0
  236. package/templates/.claude/skills/frontend-vue/composables/useWebSocket.js +257 -0
  237. package/templates/.claude/skills/frontend-vue/composables/userObj.js +111 -0
  238. package/templates/.claude/skills/frontend-vue/composables/utils.js +322 -0
  239. package/templates/.claude/skills/frontend-vue/reference/composables-example.vue +320 -0
  240. package/templates/.claude/skills/frontend-vue/reference/form-example.vue +183 -0
  241. package/templates/.claude/skills/frontend-vue/reference/grid-example.vue +147 -0
  242. package/templates/.claude/skills/frontend-vue/reference/masterdata-example/[id].vue +106 -0
  243. package/templates/.claude/skills/frontend-vue/reference/masterdata-example/index.vue +58 -0
  244. package/templates/.claude/skills/frontend-vue/reference/popup-example.vue +159 -0
  245. package/templates/.claude/skills/pdf/LICENSE.txt +30 -0
  246. package/templates/.claude/skills/pdf/SKILL.md +294 -0
  247. package/templates/.claude/skills/pdf/forms.md +205 -0
  248. package/templates/.claude/skills/pdf/reference.md +612 -0
  249. package/templates/.claude/skills/pdf/scripts/check_bounding_boxes.py +70 -0
  250. package/templates/.claude/skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  251. package/templates/.claude/skills/pdf/scripts/check_fillable_fields.py +12 -0
  252. package/templates/.claude/skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  253. package/templates/.claude/skills/pdf/scripts/create_validation_image.py +41 -0
  254. package/templates/.claude/skills/pdf/scripts/extract_form_field_info.py +152 -0
  255. package/templates/.claude/skills/pdf/scripts/fill_fillable_fields.py +114 -0
  256. package/templates/.claude/skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  257. package/templates/.claude/skills/pdf-processing/SKILL.md +107 -0
  258. package/templates/.claude/skills/pdf-processing-pro/FORMS.md +610 -0
  259. package/templates/.claude/skills/pdf-processing-pro/OCR.md +137 -0
  260. package/templates/.claude/skills/pdf-processing-pro/SKILL.md +296 -0
  261. package/templates/.claude/skills/pdf-processing-pro/TABLES.md +626 -0
  262. package/templates/.claude/skills/pdf-processing-pro/scripts/analyze_form.py +307 -0
  263. package/templates/.claude/skills/postgres/SKILL.md +69 -0
  264. package/templates/.claude/skills/postgres/reference/fn_get_examples.sql +208 -0
  265. package/templates/.claude/skills/postgres/reference/fn_rpt_examples.sql +239 -0
  266. package/templates/.claude/skills/postgres/reference/utility_functions.sql +94 -0
  267. package/templates/.claude/skills/pptx/LICENSE.txt +30 -0
  268. package/templates/.claude/skills/pptx/SKILL.md +484 -0
  269. package/templates/.claude/skills/pptx/html2pptx.md +625 -0
  270. package/templates/.claude/skills/pptx/ooxml.md +427 -0
  271. package/templates/.claude/skills/pptx/scripts/html2pptx.js +979 -0
  272. package/templates/.claude/skills/pptx/scripts/inventory.py +1020 -0
  273. package/templates/.claude/skills/pptx/scripts/rearrange.py +231 -0
  274. package/templates/.claude/skills/pptx/scripts/replace.py +385 -0
  275. package/templates/.claude/skills/pptx/scripts/thumbnail.py +450 -0
  276. package/templates/.claude/skills/repo-maintenance/SKILL.md +97 -0
  277. package/templates/.claude/skills/research/EXAMPLES.md +434 -0
  278. package/templates/.claude/skills/research/REFERENCE.md +399 -0
  279. package/templates/.claude/skills/research/SKILL.md +136 -0
  280. package/templates/.claude/skills/root-cause-tracing/SKILL.md +174 -0
  281. package/templates/.claude/skills/root-cause-tracing/find-polluter.sh +63 -0
  282. package/templates/.claude/skills/sharing-skills/SKILL.md +194 -0
  283. package/templates/.claude/skills/sql-optimization-patterns/SKILL.md +493 -0
  284. package/templates/.claude/skills/subagent-driven-development/SKILL.md +189 -0
  285. package/templates/.claude/skills/systematic-debugging/CREATION-LOG.md +119 -0
  286. package/templates/.claude/skills/systematic-debugging/SKILL.md +295 -0
  287. package/templates/.claude/skills/systematic-debugging/test-academic.md +14 -0
  288. package/templates/.claude/skills/systematic-debugging/test-pressure-1.md +58 -0
  289. package/templates/.claude/skills/systematic-debugging/test-pressure-2.md +68 -0
  290. package/templates/.claude/skills/systematic-debugging/test-pressure-3.md +69 -0
  291. package/templates/.claude/skills/test-driven-development/SKILL.md +364 -0
  292. package/templates/.claude/skills/testing-anti-patterns/SKILL.md +302 -0
  293. package/templates/.claude/skills/testing-quality/SKILL.md +97 -0
  294. package/templates/.claude/skills/verification-before-completion/SKILL.md +139 -0
  295. package/templates/.claude/skills/webapp-testing/LICENSE.txt +202 -0
  296. package/templates/.claude/skills/webapp-testing/SKILL.md +96 -0
  297. package/templates/.claude/skills/webapp-testing/examples/console_logging.py +35 -0
  298. package/templates/.claude/skills/webapp-testing/examples/element_discovery.py +40 -0
  299. package/templates/.claude/skills/webapp-testing/examples/static_html_automation.py +33 -0
  300. package/templates/.claude/skills/webapp-testing/scripts/with_server.py +106 -0
  301. package/templates/.claude/ukit/index/build-index.mjs +28 -0
  302. package/templates/.claude/ukit/index/cache-utils.mjs +140 -0
  303. package/templates/.claude/ukit/index/lib/index-core.mjs +2800 -0
  304. package/templates/.claude/ukit/index/query-index.mjs +150 -0
  305. package/templates/.claude/ukit/index/refresh-index.mjs +57 -0
  306. package/templates/.claude/ukit/index/reset-auto-permissions.mjs +76 -0
  307. package/templates/.claude/ukit/index/resolve-context.mjs +279 -0
  308. package/templates/.claude/ukit/index/route-catalog.mjs +258 -0
  309. package/templates/.claude/ukit/index/route-task.mjs +1994 -0
  310. package/templates/.claude/ukit/index/triage.mjs +133 -0
  311. package/templates/.claude/ukit/index/verify-context.mjs +689 -0
  312. package/templates/.claude/ukit/runtime/compact-threshold.mjs +1013 -0
  313. package/templates/.claude/ukit/runtime/output-compression.mjs +1340 -0
  314. package/templates/.claude/ukit/runtime/reinject-context.mjs +874 -0
  315. package/templates/.claude/ukit/runtime/token-utils.mjs +500 -0
  316. package/templates/.codex/README.md +83 -0
  317. package/templates/.codex/settings.json +187 -0
  318. package/templates/.gitignore +75 -0
  319. package/templates/AGENTS.md +116 -0
  320. package/templates/CLAUDE.md +93 -0
  321. package/templates/adapter-presets/antigravity/README.md +22 -0
  322. package/templates/adapter-presets/antigravity/rules.md +49 -0
  323. package/templates/adapter-presets/claude/settings.local.json +42 -0
  324. package/templates/adapter-presets/codex/settings.local.json +6 -0
  325. package/templates/adapter-presets/opencode/opencode.template.json +1 -0
  326. package/templates/docs/BUGFIX.md +20 -0
  327. package/templates/docs/BUG_INDEX.md +12 -0
  328. package/templates/docs/BUG_METRICS.md +7 -0
  329. package/templates/docs/BUG_TEMPLATE.md +13 -0
  330. package/templates/docs/CODE_MAP.md +35 -0
  331. package/templates/docs/INSTALL.md +113 -0
  332. package/templates/docs/MEMORY.md +49 -0
  333. package/templates/docs/PROJECT.md +50 -0
  334. package/templates/docs/UKIT_USAGE_GUIDE.md +147 -0
  335. package/templates/docs/WORKLOG.md +10 -0
  336. package/templates/ukit/README.md +14 -0
  337. package/templates/ukit/storage/cache/compact-history.json +3 -0
  338. package/templates/ukit/storage/cache/compact-pressure.json +1 -0
  339. package/templates/ukit/storage/cache/output-history.json +3 -0
  340. package/templates/ukit/storage/cache/prompt-cache.json +3 -0
  341. package/templates/ukit/storage/config.json +37 -0
  342. package/templates/ukit/storage/memory/projects/.gitkeep +2 -0
  343. package/templates/ukit/storage/memory/sessions/.gitkeep +0 -0
  344. package/templates/ukit/storage/memory/user.json +5 -0
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Analyze PDF form fields and structure.
4
+
5
+ Usage:
6
+ python analyze_form.py input.pdf [--output fields.json] [--verbose]
7
+
8
+ Returns:
9
+ JSON with all form fields, types, positions, and metadata
10
+
11
+ Exit codes:
12
+ 0 - Success
13
+ 1 - File not found
14
+ 2 - Invalid PDF
15
+ 3 - Processing error
16
+ """
17
+
18
+ import sys
19
+ import json
20
+ import logging
21
+ import argparse
22
+ from pathlib import Path
23
+ from typing import Dict, List, Optional, Any
24
+
25
+ try:
26
+ from pypdf import PdfReader
27
+ except ImportError:
28
+ print("Error: pypdf not installed. Run: pip install pypdf", file=sys.stderr)
29
+ sys.exit(3)
30
+
31
+ # Configure logging
32
+ logging.basicConfig(
33
+ level=logging.INFO,
34
+ format='%(asctime)s - %(levelname)s - %(message)s'
35
+ )
36
+ logger = logging.getLogger(__name__)
37
+
38
+
39
+ class FormField:
40
+ """Represents a PDF form field."""
41
+
42
+ def __init__(self, name: str, field_dict: Dict[str, Any]):
43
+ self.name = name
44
+ self.raw_data = field_dict
45
+
46
+ @property
47
+ def field_type(self) -> str:
48
+ """Get field type."""
49
+ ft = self.raw_data.get('/FT', '')
50
+ type_map = {
51
+ '/Tx': 'text',
52
+ '/Btn': 'button', # checkbox or radio
53
+ '/Ch': 'choice', # dropdown or list
54
+ '/Sig': 'signature'
55
+ }
56
+ return type_map.get(ft, 'unknown')
57
+
58
+ @property
59
+ def value(self) -> Optional[str]:
60
+ """Get current field value."""
61
+ val = self.raw_data.get('/V')
62
+ return str(val) if val else None
63
+
64
+ @property
65
+ def default_value(self) -> Optional[str]:
66
+ """Get default field value."""
67
+ dv = self.raw_data.get('/DV')
68
+ return str(dv) if dv else None
69
+
70
+ @property
71
+ def is_required(self) -> bool:
72
+ """Check if field is required."""
73
+ flags = self.raw_data.get('/Ff', 0)
74
+ # Bit 2 indicates required
75
+ return bool(flags & 2)
76
+
77
+ @property
78
+ def is_readonly(self) -> bool:
79
+ """Check if field is read-only."""
80
+ flags = self.raw_data.get('/Ff', 0)
81
+ # Bit 1 indicates read-only
82
+ return bool(flags & 1)
83
+
84
+ @property
85
+ def options(self) -> List[str]:
86
+ """Get options for choice fields."""
87
+ if self.field_type != 'choice':
88
+ return []
89
+
90
+ opts = self.raw_data.get('/Opt', [])
91
+ if isinstance(opts, list):
92
+ return [str(opt) for opt in opts]
93
+ return []
94
+
95
+ @property
96
+ def max_length(self) -> Optional[int]:
97
+ """Get max length for text fields."""
98
+ if self.field_type == 'text':
99
+ return self.raw_data.get('/MaxLen')
100
+ return None
101
+
102
+ @property
103
+ def rect(self) -> Optional[List[float]]:
104
+ """Get field position and size [x0, y0, x1, y1]."""
105
+ return self.raw_data.get('/Rect')
106
+
107
+ def to_dict(self) -> Dict[str, Any]:
108
+ """Convert to dictionary."""
109
+ result = {
110
+ 'name': self.name,
111
+ 'type': self.field_type,
112
+ 'required': self.is_required,
113
+ 'readonly': self.is_readonly
114
+ }
115
+
116
+ if self.value is not None:
117
+ result['value'] = self.value
118
+
119
+ if self.default_value is not None:
120
+ result['default_value'] = self.default_value
121
+
122
+ if self.options:
123
+ result['options'] = self.options
124
+
125
+ if self.max_length is not None:
126
+ result['max_length'] = self.max_length
127
+
128
+ if self.rect:
129
+ result['position'] = {
130
+ 'x0': float(self.rect[0]),
131
+ 'y0': float(self.rect[1]),
132
+ 'x1': float(self.rect[2]),
133
+ 'y1': float(self.rect[3]),
134
+ 'width': float(self.rect[2] - self.rect[0]),
135
+ 'height': float(self.rect[3] - self.rect[1])
136
+ }
137
+
138
+ return result
139
+
140
+
141
+ class PDFFormAnalyzer:
142
+ """Analyzes PDF forms and extracts field information."""
143
+
144
+ def __init__(self, pdf_path: str):
145
+ self.pdf_path = Path(pdf_path)
146
+ self.reader: Optional[PdfReader] = None
147
+ self._validate_file()
148
+
149
+ def _validate_file(self) -> None:
150
+ """Validate PDF file exists and is readable."""
151
+ if not self.pdf_path.exists():
152
+ logger.error(f"PDF not found: {self.pdf_path}")
153
+ raise FileNotFoundError(f"PDF not found: {self.pdf_path}")
154
+
155
+ if not self.pdf_path.is_file():
156
+ logger.error(f"Not a file: {self.pdf_path}")
157
+ raise ValueError(f"Not a file: {self.pdf_path}")
158
+
159
+ if self.pdf_path.suffix.lower() != '.pdf':
160
+ logger.error(f"Not a PDF file: {self.pdf_path}")
161
+ raise ValueError(f"Not a PDF file: {self.pdf_path}")
162
+
163
+ def analyze(self) -> Dict[str, Dict[str, Any]]:
164
+ """
165
+ Analyze PDF and extract all form fields.
166
+
167
+ Returns:
168
+ Dictionary mapping field names to field information
169
+ """
170
+ try:
171
+ self.reader = PdfReader(str(self.pdf_path))
172
+
173
+ if not self.reader.pages:
174
+ logger.warning("PDF has no pages")
175
+ return {}
176
+
177
+ logger.info(f"Analyzing PDF with {len(self.reader.pages)} pages")
178
+
179
+ # Get form fields
180
+ raw_fields = self.reader.get_fields()
181
+
182
+ if not raw_fields:
183
+ logger.warning("PDF has no form fields")
184
+ return {}
185
+
186
+ logger.info(f"Found {len(raw_fields)} form fields")
187
+
188
+ # Process fields
189
+ fields = {}
190
+ for field_name, field_dict in raw_fields.items():
191
+ try:
192
+ field = FormField(field_name, field_dict)
193
+ fields[field_name] = field.to_dict()
194
+ except Exception as e:
195
+ logger.warning(f"Error processing field {field_name}: {e}")
196
+ continue
197
+
198
+ return fields
199
+
200
+ except Exception as e:
201
+ logger.error(f"Error analyzing PDF: {e}")
202
+ raise
203
+
204
+ def get_summary(self) -> Dict[str, Any]:
205
+ """Get summary statistics."""
206
+ fields = self.analyze()
207
+
208
+ summary = {
209
+ 'total_fields': len(fields),
210
+ 'field_types': {},
211
+ 'required_fields': [],
212
+ 'readonly_fields': [],
213
+ 'fields_with_values': []
214
+ }
215
+
216
+ for field_name, field_data in fields.items():
217
+ # Count by type
218
+ field_type = field_data['type']
219
+ summary['field_types'][field_type] = summary['field_types'].get(field_type, 0) + 1
220
+
221
+ # Required fields
222
+ if field_data.get('required'):
223
+ summary['required_fields'].append(field_name)
224
+
225
+ # Read-only fields
226
+ if field_data.get('readonly'):
227
+ summary['readonly_fields'].append(field_name)
228
+
229
+ # Fields with values
230
+ if field_data.get('value'):
231
+ summary['fields_with_values'].append(field_name)
232
+
233
+ return summary
234
+
235
+
236
+ def main():
237
+ """Main entry point."""
238
+ parser = argparse.ArgumentParser(
239
+ description='Analyze PDF form fields',
240
+ formatter_class=argparse.RawDescriptionHelpFormatter,
241
+ epilog='''
242
+ Examples:
243
+ %(prog)s form.pdf
244
+ %(prog)s form.pdf --output fields.json
245
+ %(prog)s form.pdf --output fields.json --verbose
246
+ %(prog)s form.pdf --summary
247
+
248
+ Exit codes:
249
+ 0 - Success
250
+ 1 - File not found
251
+ 2 - Invalid PDF
252
+ 3 - Processing error
253
+ '''
254
+ )
255
+
256
+ parser.add_argument('input', help='Input PDF file')
257
+ parser.add_argument('--output', '-o', help='Output JSON file (default: stdout)')
258
+ parser.add_argument('--summary', '-s', action='store_true', help='Show summary only')
259
+ parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
260
+
261
+ args = parser.parse_args()
262
+
263
+ # Set log level
264
+ if args.verbose:
265
+ logger.setLevel(logging.DEBUG)
266
+ else:
267
+ logger.setLevel(logging.WARNING)
268
+
269
+ try:
270
+ # Analyze form
271
+ analyzer = PDFFormAnalyzer(args.input)
272
+
273
+ if args.summary:
274
+ result = analyzer.get_summary()
275
+ else:
276
+ result = analyzer.analyze()
277
+
278
+ # Output
279
+ json_output = json.dumps(result, indent=2)
280
+
281
+ if args.output:
282
+ with open(args.output, 'w', encoding='utf-8') as f:
283
+ f.write(json_output)
284
+ logger.info(f"Saved to {args.output}")
285
+ else:
286
+ print(json_output)
287
+
288
+ return 0
289
+
290
+ except FileNotFoundError:
291
+ logger.error(f"File not found: {args.input}")
292
+ return 1
293
+
294
+ except ValueError as e:
295
+ logger.error(f"Invalid input: {e}")
296
+ return 2
297
+
298
+ except Exception as e:
299
+ logger.error(f"Error: {e}")
300
+ if args.verbose:
301
+ import traceback
302
+ traceback.print_exc()
303
+ return 3
304
+
305
+
306
+ if __name__ == '__main__':
307
+ sys.exit(main())
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: postgres
3
+ description: PostgreSQL conventions and patterns for UKit SQL work.
4
+ enabledByDefault: false
5
+ ---
6
+
7
+ # PostgreSQL Skill Pack
8
+
9
+ Enabled: false
10
+
11
+ AI suggests SQL only. User runs via psql. Read reference files for full examples:
12
+ - `reference/fn_rpt_examples.sql` - Report function patterns
13
+ - `reference/fn_get_examples.sql` - Get functions with permissions
14
+ - `reference/utility_functions.sql` - Utility functions & table templates
15
+
16
+ ## Data Types (ONLY 3)
17
+
18
+ | Type | Use for |
19
+ |------|---------|
20
+ | `VARCHAR` | Text, dates, timestamps, JSON, UUIDs |
21
+ | `NUMERIC` | Numbers (`NUMERIC(16,2)` for money) |
22
+ | `BOOLEAN` | True/false |
23
+
24
+ **NEVER use:** DATE, TIMESTAMP, INTEGER, BIGINT, JSON, JSONB, UUID, TEXT
25
+
26
+ ## Naming
27
+
28
+ | Object | Pattern | Example |
29
+ |--------|---------|---------|
30
+ | Table | `snake_case` | `users` |
31
+ | PK | `id_<table>` | `id_users` |
32
+ | View | `v_<name>` | `v_billing` |
33
+ | Function | `fn_<name>` | `fn_get_users` |
34
+ | Report fn | `fn_rpt_<name>` | `fn_rpt_billing` |
35
+ | Index | `idx_{table}_{cols}` | `idx_orders_user_id` |
36
+
37
+ ## Mandatory Workflow
38
+
39
+ 1. **Query structure first** (`\d schema.table` or `information_schema`)
40
+ 2. **Check if view exists** (`\dv schema.*`)
41
+ 3. View exists → `CREATE FUNCTION RETURNS SETOF view_name`
42
+ 4. View missing → Create view first, then function
43
+
44
+ **NEVER:** Use `RETURNS TABLE`, create views inside functions, skip `DROP FUNCTION IF EXISTS`
45
+
46
+ ## Function Pattern (Preferred)
47
+
48
+ ```sql
49
+ DROP FUNCTION IF EXISTS schema.fn_rpt_name;
50
+ CREATE OR REPLACE FUNCTION schema.fn_rpt_name()
51
+ RETURNS SETOF schema.v_report_name
52
+ AS $$
53
+ BEGIN
54
+ RETURN QUERY SELECT * FROM schema.v_report_name ORDER BY created_on DESC;
55
+ END;
56
+ $$ LANGUAGE plpgsql;
57
+
58
+ SELECT * FROM schema.fn_rpt_name();
59
+ ```
60
+
61
+ ## Key Rules
62
+
63
+ - `DROP` before `CREATE`. Explicit casts (`::VARCHAR`, `::NUMERIC(16,2)`)
64
+ - Declare + initialize variables. NULL checks for flags.
65
+ - `ORDER BY` in RETURN QUERY. Alias all tables. Test query after function.
66
+ - `CASE WHEN`: `(CASE WHEN cond THEN TRUE ELSE FALSE END) AS col`
67
+ - JSONB: `jsonb_array_elements_text(col::jsonb)`, `(t.detail::jsonb -> 0 ->>'key')::VARCHAR`
68
+ - Indexes for WHERE/JOIN/ORDER columns. `EXPLAIN ANALYZE` on large tables.
69
+ - Parameterized queries only. No `SELECT *` in app code.
@@ -0,0 +1,208 @@
1
+ -- =============================================
2
+ -- GET FUNCTION EXAMPLES
3
+ -- Pattern: fn_get_<name> - Returns SETOF view
4
+ -- With user permissions and computed columns
5
+ -- =============================================
6
+
7
+
8
+ -- =============================================
9
+ -- Example 1: Get with Role-based Permissions
10
+ -- Pattern: Single role check + permission table lookup
11
+ -- =============================================
12
+
13
+ DROP FUNCTION IF EXISTS qas.fn_get_collect_point;
14
+ CREATE OR REPLACE FUNCTION qas.fn_get_collect_point(_username VARCHAR)
15
+ RETURNS SETOF qas.v_collect_point
16
+ AS
17
+ $$
18
+ DECLARE
19
+ v_role VARCHAR;
20
+ v_is_admin1 BOOLEAN := FALSE;
21
+ v_is_admin2 BOOLEAN := FALSE;
22
+ t_can_edit_after_approved BOOLEAN := FALSE;
23
+ BEGIN
24
+ -- Get user role
25
+ SELECT usergroup INTO v_role FROM qas.user WHERE username = _username;
26
+
27
+ -- Check admin roles
28
+ IF v_role LIKE '%Collect Point Admin 1%' THEN
29
+ v_is_admin1 = TRUE;
30
+ END IF;
31
+
32
+ IF v_role LIKE '%Collect Point Admin 2%' THEN
33
+ v_is_admin2 = TRUE;
34
+ END IF;
35
+
36
+ -- Get permission from permission table
37
+ SELECT can_edit_after_approved INTO t_can_edit_after_approved
38
+ FROM qas.permission
39
+ WHERE usergroup IN (SELECT jsonb_array_elements_text(v_role::jsonb))
40
+ AND menu = 'Collect Point'
41
+ AND can_edit_after_approved IS TRUE;
42
+
43
+ -- NULL check
44
+ IF t_can_edit_after_approved IS NULL THEN
45
+ t_can_edit_after_approved = FALSE;
46
+ END IF;
47
+
48
+ RETURN QUERY
49
+ SELECT c.id_collect_point,
50
+ c.running_no,
51
+ c.receipt_no,
52
+ c.date_receipt,
53
+ c.date_of_upload,
54
+ c.stamp_product,
55
+ c.status,
56
+ c.history,
57
+ c.created_on,
58
+ c.username,
59
+ c.remark,
60
+ c.remark_admin2,
61
+ c.attach_file,
62
+ c.attach_image,
63
+ c.id_sub_dealer,
64
+ c.name_of_store,
65
+ c.crm_user_id,
66
+ c.sub_dealer_province,
67
+ c.store_region,
68
+ c.id_dealer,
69
+ c.name_of_seller,
70
+ c.region1_salesrep,
71
+ c.region3_division,
72
+ c.customer_code,
73
+ c.total_point,
74
+ c.total_amount,
75
+ -- Computed permission columns
76
+ (CASE WHEN (v_is_admin1 AND c.status = 'DRAFT') OR (v_is_admin2 AND c.status = 'DRAFT1') THEN TRUE ELSE FALSE END) AS can_edit_quantity,
77
+ (CASE WHEN v_is_admin2 AND c.status = 'DRAFT1' THEN TRUE ELSE FALSE END) AS can_edit_multiplier,
78
+ (CASE WHEN (v_is_admin1 AND c.status = 'DRAFT') OR (v_is_admin2 AND c.status = 'DRAFT1') THEN TRUE ELSE FALSE END) AS can_save,
79
+ t_can_edit_after_approved AS can_edit_after_approved,
80
+ c.detail,
81
+ c.approved_date,
82
+ c.approved_by
83
+ FROM qas.v_collect_point c
84
+ ORDER BY c.created_on DESC;
85
+ END;
86
+ $$ LANGUAGE plpgsql;
87
+
88
+ SELECT * FROM qas.fn_get_collect_point('khoaln@scg.com');
89
+
90
+
91
+ -- =============================================
92
+ -- Example 2: Get with Multiple Permission Flags
93
+ -- Pattern: Permission table + role-based overrides + JSONB access
94
+ -- =============================================
95
+
96
+ DROP FUNCTION IF EXISTS qas.fn_get_review_transaction_4_not_eligible;
97
+ CREATE OR REPLACE FUNCTION qas.fn_get_review_transaction_4_not_eligible(_username VARCHAR)
98
+ RETURNS SETOF qas.v_review_transaction
99
+ AS
100
+ $$
101
+ DECLARE
102
+ t_usergroup VARCHAR;
103
+ t_can_edit_after_approved BOOLEAN := FALSE;
104
+ t_can_reject BOOLEAN := FALSE;
105
+ t_can_not_eligible BOOLEAN := FALSE;
106
+ t_can_confirm BOOLEAN := FALSE;
107
+ t_can_approve BOOLEAN := FALSE;
108
+ t_can_save BOOLEAN := FALSE;
109
+ BEGIN
110
+ -- Get user group
111
+ SELECT usergroup INTO t_usergroup FROM qas.user WHERE username = _username;
112
+
113
+ -- Get base permission
114
+ SELECT can_edit_after_approved INTO t_can_edit_after_approved
115
+ FROM qas.permission
116
+ WHERE usergroup IN (SELECT jsonb_array_elements_text(t_usergroup::jsonb))
117
+ AND menu = 'Collect Point'
118
+ AND can_edit_after_approved IS TRUE;
119
+
120
+ IF t_can_edit_after_approved IS NULL THEN
121
+ t_can_edit_after_approved = FALSE;
122
+ END IF;
123
+
124
+ -- Role-based permission overrides
125
+ IF t_usergroup LIKE '%"Collect Point Admin 1"%' THEN
126
+ t_can_edit_after_approved = FALSE;
127
+ t_can_reject = TRUE;
128
+ t_can_not_eligible = FALSE;
129
+ t_can_confirm = TRUE;
130
+ t_can_approve = FALSE;
131
+ END IF;
132
+
133
+ IF t_usergroup LIKE '%"Collect Point Admin 2"%' THEN
134
+ t_can_edit_after_approved = FALSE;
135
+ t_can_reject = TRUE;
136
+ t_can_not_eligible = FALSE;
137
+ t_can_confirm = FALSE;
138
+ t_can_approve = TRUE;
139
+ END IF;
140
+
141
+ RETURN QUERY
142
+ SELECT t.id_review_transaction,
143
+ t.running_no,
144
+ t.image_name,
145
+ t.image_name_show,
146
+ t.user_id,
147
+ t.ref_id,
148
+ t.last_name,
149
+ t.first_name,
150
+ t.id_sub_dealer,
151
+ t.name_of_store,
152
+ t.post_code,
153
+ t.sub_dealer_province,
154
+ t.store_region,
155
+ t.address,
156
+ t.survey_date,
157
+ t.date_of_upload,
158
+ -- JSONB access with fallback
159
+ (CASE
160
+ WHEN t.doc_date <> '' THEN t.doc_date
161
+ ELSE (CASE
162
+ WHEN (t.detail::jsonb -> 0 ->> 'doc_date')::VARCHAR <> ''
163
+ THEN (t.detail::jsonb -> 0 ->> 'doc_date')::VARCHAR
164
+ ELSE ''
165
+ END)
166
+ END) AS doc_date,
167
+ t.detail,
168
+ t.is_confirm,
169
+ t.confirm_user,
170
+ t.confirm_time,
171
+ t.is_reject,
172
+ t.reject_by,
173
+ t.reject_time,
174
+ t.reject_reason,
175
+ t.not_eligible,
176
+ t.not_eligible_username,
177
+ t.not_eligible_time,
178
+ t.is_approved,
179
+ t.approved_by,
180
+ t.approved_time,
181
+ -- Permission flags
182
+ t_can_edit_after_approved AS can_edit_after_approved,
183
+ t_can_reject AS can_reject,
184
+ t_can_not_eligible AS can_not_eligible,
185
+ t_can_confirm AS can_confirm,
186
+ t_can_approve AS can_approve,
187
+ (CASE WHEN t_can_edit_after_approved AND is_reject IS TRUE THEN TRUE ELSE FALSE END) AS can_save,
188
+ t.doc_number,
189
+ t.doc_number_show,
190
+ t.customer_id,
191
+ t.dealer_code,
192
+ t.dealer_name,
193
+ t.username,
194
+ t.created_on,
195
+ t.total_get_point,
196
+ t.total_get_point_amount,
197
+ t.status,
198
+ t.last_changed_time,
199
+ t.history,
200
+ t.remark
201
+ FROM qas.v_review_transaction t
202
+ WHERE t.not_eligible = TRUE
203
+ ORDER BY t.last_changed_time DESC;
204
+ END;
205
+ $$ LANGUAGE plpgsql;
206
+
207
+ SELECT * FROM qas.fn_get_review_transaction_4_not_eligible('hungdq@scg.com')
208
+ WHERE id_review_transaction = '6639d394-4576-4013-a8b0-8e40cbab9c6d';