Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Jubilee Integration #932

Draft
wants to merge 37 commits into
base: jubilee-integration
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6910605
Merge pull request #908 from av-dev2/validate_stock_on_so_and_si
av-dev2 Mar 19, 2024
aa7bb98
Merge pull request #910 from av-dev2/allow_is_restricted_for_non_nhif…
av-dev2 Mar 19, 2024
07ccef2
Merge pull request #913 from av-dev2/chore_comparing_warehouse_for_sa…
av-dev2 Mar 19, 2024
0751f15
chore: add readme content
av-dev2 Mar 20, 2024
9cbcd38
Merge pull request #918 from aakvatech/mergify/bp/version-14-hotfix/p…
av-dev2 Mar 20, 2024
ecd5105
fix: KeyError on hsic_map[template] when template is not on HSIC
av-dev2 Mar 21, 2024
9cc77d9
Merge pull request #920 from aakvatech/mergify/bp/version-14-hotfix/p…
av-dev2 Mar 21, 2024
5551af5
feat: Cancel or return therapy sessions via LRPMT Returns doctype
av-dev2 Apr 3, 2024
a8a1001
fix: conflict of 'modified' on lrpmt_returns.json file
av-dev2 Apr 9, 2024
f41b409
Merge pull request #926 from aakvatech/fix_conflicts_for_cancelling_t…
av-dev2 Apr 9, 2024
8c445b5
feat: therapy automation and controls like other LRPM documents
av-dev2 Apr 12, 2024
0ac4909
Merge pull request #925 from aakvatech/mergify/bp/version-14-hotfix/p…
av-dev2 Apr 12, 2024
1b4baeb
Merge branch 'version-14-hotfix' into mergify/bp/version-14-hotfix/pr…
av-dev2 Apr 12, 2024
c7f3c10
Merge pull request #928 from aakvatech/mergify/bp/version-14-hotfix/p…
av-dev2 Apr 12, 2024
d962a10
feat: include 'sessions_cancelled' on all the revenue reports like it…
av-dev2 Apr 12, 2024
188cb1c
Merge pull request #930 from aakvatech/mergify/bp/version-14-hotfix/p…
av-dev2 Apr 12, 2024
66f394f
chore: add list view filters for patient, patient_name, appointment, …
av-dev2 Mar 27, 2024
07dca98
fix: conflicts lrpmt_returns.json
av-dev2 Apr 17, 2024
feb2c52
Merge pull request #931 from aakvatech/mergify/bp/version-14-hotfix/p…
av-dev2 Apr 17, 2024
95826b3
chore: allow rename on 'Company NHIF Settings'
av-dev2 Apr 17, 2024
956ed25
feat: rename 'Company NHIF Settings' to 'Company Insurance Setting' t…
av-dev2 Apr 17, 2024
be6ccf0
chore: change 'Company NHIF Settings' to 'Company Insurance Setting' …
av-dev2 Apr 17, 2024
c3d9e30
chore: add providerid and will be used for jubilee token request
av-dev2 Apr 17, 2024
755cb23
feat: jubilee module
av-dev2 Apr 17, 2024
4355e4d
feat: jubilee response log for storing all request and response log s…
av-dev2 Apr 17, 2024
d623bd5
feat: request token from jubilee server
av-dev2 Apr 17, 2024
446df5c
feat: fetch member card details from jubilee server
av-dev2 Apr 22, 2024
25ec74d
feat: get price package from jubilee
av-dev2 Jun 24, 2024
f3bb919
feat: process jubilee price list, item prices, HSIC
av-dev2 Jun 27, 2024
26313e3
Merge branch 'jubilee-integration' into jubilee-integration
av-dev2 Jun 27, 2024
a740178
fix: resolve the error of 'Document is already modified'
av-dev2 Jul 16, 2024
e24e368
feat: auto create of healthcare insurance subscription for Jubilee pa…
av-dev2 Jul 16, 2024
f514e4a
feat: authoize card via API for jubilee patients
av-dev2 Jul 17, 2024
c74f166
feat: Create and Submit Jubilee Patient Claim via API
av-dev2 Jul 28, 2024
8e4d839
feat: change 'NHIF Folio Counter' to 'Insurance Folio Counter' to han…
av-dev2 Jul 28, 2024
293d01c
feat: create form 2A & B print format for jubilee patient claim
av-dev2 Jul 28, 2024
75d3197
feat: pass and use 'insurance_provider' across the system to differen…
av-dev2 Jul 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Features in ERPNext can be categorized into several key areas:

2. **Healthcare Provider and Facility Management**: Managing information about healthcare providers, facilities, and practitioner availability.

3. **Insurance and Financial Management**: This involves managing NHIF claims, tracking changes, setting up company NHIF settings, and handling patient discount requests.
3. **Insurance and Financial Management**: This involves managing NHIF claims, tracking changes, setting up company Insurance settings, and handling patient discount requests.

4. **Patient Care and Services**: This covers healthcare package orders, referral management, and tracking of patient care services.

Expand Down
2 changes: 1 addition & 1 deletion hms_tz/hms_tz/doctype/lrpmt_returns/lrpmt_returns.json
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}
263 changes: 263 additions & 0 deletions hms_tz/jubilee/api/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
import json
import frappe
import requests
from frappe import _
from time import sleep
from erpnext import get_default_company
from frappe.utils.background_jobs import enqueue
from hms_tz.jubilee.api.token import get_jubilee_service_token
from hms_tz.jubilee.api.price_package import sync_jubilee_price_package
from hms_tz.jubilee.doctype.jubilee_response_log.jubilee_response_log import (
add_jubilee_log,
)


@frappe.whitelist()
def get_member_card_detials(card_no, insurance_provider):
if not card_no or insurance_provider != "Jubilee":
return

company = get_default_company()
if not company:
company = frappe.defaults.get_user_default("Company")

if not company:
company = frappe.get_list(
"Company Insurance Setting",
fields=["company"],
filters={"enable": 1, "insurance_provider": insurance_provider},
)[0].company
if not company:
frappe.throw(_("No companies found to connect to Jubilee"))

token = get_jubilee_service_token(company, insurance_provider)

service_url = frappe.get_cached_value(
"Company Insurance Setting",
{"company": company, "insurance_provider": insurance_provider},
"service_url",
)
headers = {"Authorization": "Bearer " + token}
url = str(service_url) + f"/jubileeapi/Getcarddetails?MemberNo={str(card_no)}"
for i in range(3):
try:
r = requests.get(url, headers=headers, timeout=5)
r.raise_for_status()
frappe.logger().debug({"webhook_success": r.text})

if json.loads(r.text):
add_jubilee_log(
request_type="GetCardDetails",
request_url=url,
request_header=headers,
response_data=json.loads(r.text),
status_code=r.status_code,
ref_doctype="Patient",
)
card = json.loads(r.text)
frappe.msgprint(_(card["Status"]), alert=True)
return card
else:
add_jubilee_log(
request_type="GetCardDetails",
request_url=url,
request_header=headers,
response_data=str(r),
status_code=r.status_code,
ref_doctype="Patient",
)
frappe.msgprint(json.loads(r.text))
frappe.msgprint(
_(
"Getting information from NHIF failed. Try again after sometime, or continue manually."
)
)
except Exception as e:
frappe.logger().debug({"webhook_error": e, "try": i + 1})
sleep(3 * i + 1)
if i != 2:
continue
else:
raise e


@frappe.whitelist()
def create_jubilee_subscription(patient_id, card_no, insurance_provider):
if not insurance_provider or insurance_provider != "Jubilee":
return

subscription_list = frappe.get_list(
"Healthcare Insurance Subscription",
filters={"patient": patient_id, "is_active": 1},
)
if len(subscription_list) > 0:
frappe.msgprint(
_(
"Existing Patient HIS was found. Create the Healthcare Insurance Subscription manually!"
)
)
return

plan_filters = {
"is_active": 1,
"insurance_company": ["like", "Jubilee%"],
}
company = get_default_company()
if company:
plan_filters["company"] = company

# Assumed that company is filtered based on user permissions
plan = frappe.db.get_list(
"Healthcare Insurance Coverage Plan",
filters=plan_filters,
fields=["name", "insurance_company", "company"],
)

if not plan or len(plan) == 0:
frappe.msgprint(
_("No active Healthcare Insurance Coverage Plan found for Jubilee")
)
return

if len(plan) > 1:
frappe.msgprint(
_(
"Multiple active Healthcare Insurance Coverage Plan found for Jubilee,\
<br><br>please create the healthcare Insurance Subscription manually"
)
)
return

sub_doc = frappe.new_doc("Healthcare Insurance Subscription")
sub_doc.patient = patient_id
sub_doc.insurance_company = plan[0].insurance_company
sub_doc.healthcare_insurance_coverage_plan = plan[0].name
sub_doc.coverage_plan_card_number = card_no
sub_doc.save(ignore_permissions=True)
sub_doc.submit()
frappe.msgprint(
_(
f"<h3>AUTO</h3> Healthcare Insurance Subscription: {sub_doc.name} is created for {plan[0].name}"
)
)


@frappe.whitelist()
def get_authorization_number(
company,
card_no,
appointment_no,
insurance_subscription,
insurance_provider="Jubilee",
):
if insurance_provider != "Jubilee":
return

setting_name, service_url = frappe.get_cached_value(
"Company Insurance Setting",
{"company": company, "insurance_provider": insurance_provider, "enable": 1},
["name", "service_url"],
)
if not setting_name:
frappe.throw(
f"Company Insurance Setting not found for company: {company} and API Provider: {insurance_provider}, please Create or Enable one."
)

if not card_no:
frappe.msgprint(
_(
f"Please set Card No in Healthcare Insurance Subscription {insurance_subscription}"
)
)
return

token = get_jubilee_service_token(company, insurance_provider)

headers = {"Content-Type": "application/json", "Authorization": "Bearer " + token}
url = str(service_url) + "/jubileeapi/CheckVerification?MemberNo=" + str(card_no)

r = requests.get(url, headers=headers, timeout=5)
r.raise_for_status()
frappe.logger().debug({"webhook_success": r.text})
if json.loads(r.text):
add_jubilee_log(
request_type="AuthorizeCard",
request_url=url,
request_header=headers,
response_data=json.loads(r.text),
status_code=r.status_code,
ref_doctype="Patient Appointment",
ref_docname=appointment_no,
company=company,
)
card = json.loads(r.text)
if card.get("Status") != "OK":
frappe.throw(title=card.get("Status"), msg=card["Description"])
frappe.msgprint(_(card["Description"]), alert=True)
return card
else:
add_jubilee_log(
request_type="AuthorizeCard",
request_url=url,
request_header=headers,
response_data=json.loads(r.text),
status_code=r.status_code,
ref_doctype="Patient Appointment",
ref_docname=appointment_no,
company=company,
)
frappe.throw(json.loads(r.text))


@frappe.whitelist()
def enqueue_get_jubilee_price_packages(company):
enqueue(
method=get_jubilee_price_packages,
job_name="get_jubilee_price_packages",
queue="default",
timeout=10000000,
is_async=True,
company=company,
)


@frappe.whitelist()
def get_jubilee_price_packages(company, insurance_provider="Jubilee"):
if not company:
frappe.throw(_("No companies found to connect to Jubilee"))

token = get_jubilee_service_token(company, insurance_provider)

service_url = frappe.get_cached_value(
"Company Insurance Setting",
{"company": company, "insurance_provider": insurance_provider},
"service_url",
)
headers = {"Authorization": "Bearer " + token}
url = str(service_url) + "/jubileeapi/GetPriceList"
r = requests.get(url, headers=headers, timeout=300)
if r.status_code != 200:
add_jubilee_log(
request_type="GetPricePackage",
request_url=url,
request_header=headers,
response_data=r.text,
status_code=r.status_code,
ref_doctype="Jubilee Price Package",
company=company,
)
frappe.throw(json.loads(r.text))
else:
if json.loads(r.text):
log_name = add_jubilee_log(
request_type="GetPricePackage",
request_url=url,
request_header=headers,
response_data=r.text,
status_code=r.status_code,
ref_doctype="Jubilee Price Package",
company=company,
)

packages = json.loads(r.text)["Description"]
sync_jubilee_price_package(packages, company, log_name)
Loading