diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py
index 75d99e75deb..cd3d8dc1258 100644
--- a/erpnext/accounts/report/cash_flow/cash_flow.py
+++ b/erpnext/accounts/report/cash_flow/cash_flow.py
@@ -69,7 +69,9 @@ def execute(filters=None):
add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company)
- return columns, data
+ chart = get_chart_data(columns, data)
+
+ return columns, data, None, chart
def get_cash_flow_accounts():
operation_accounts = {
@@ -171,4 +173,21 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated
total_row["total"] += row["total"]
out.append(total_row)
- out.append({})
\ No newline at end of file
+ out.append({})
+
+def get_chart_data(columns, data):
+ labels = [d.get("label") for d in columns[2:]]
+ datasets = [{'name':account.get('account').replace("'", ""), 'values': [account.get('total')]} for account in data if account.get('parent_account') == None and account.get('currency')]
+ datasets = datasets[:-1]
+
+ chart = {
+ "data": {
+ 'labels': labels,
+ 'datasets': datasets
+ },
+ "type": "bar"
+ }
+
+ chart["fieldtype"] = "Currency"
+
+ return chart
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index dead1f030c5..5dce3497829 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -66,10 +66,11 @@
"net_total",
"total_net_weight",
"taxes_section",
- "taxes_and_charges",
+ "tax_category",
"column_break_50",
"shipping_rule",
"section_break_52",
+ "taxes_and_charges",
"taxes",
"sec_tax_breakup",
"other_charges_calculation",
@@ -569,7 +570,7 @@
{
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
- "label": "Taxes and Charges",
+ "label": "Purchase Taxes and Charges Template",
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
@@ -1032,12 +1033,18 @@
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
"label": "Update Auto Repeat Reference"
+ },
+ {
+ "fieldname": "tax_category",
+ "fieldtype": "Link",
+ "label": "Tax Category",
+ "options": "Tax Category"
}
],
"icon": "fa fa-file-text",
"idx": 105,
"is_submittable": 1,
- "modified": "2019-06-24 21:22:05.483429",
+ "modified": "2019-07-11 18:25:49.509343",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/config/healthcare.py b/erpnext/config/healthcare.py
index 13111116184..756d22e416b 100644
--- a/erpnext/config/healthcare.py
+++ b/erpnext/config/healthcare.py
@@ -26,8 +26,8 @@ def get_data():
},
{
"type": "page",
- "name": "medical_record",
- "label": _("Patient Medical Record"),
+ "name": "patient_history",
+ "label": _("Patient History"),
},
{
"type": "page",
diff --git a/erpnext/config/support.py b/erpnext/config/support.py
index 36b42141963..151c4f743e1 100644
--- a/erpnext/config/support.py
+++ b/erpnext/config/support.py
@@ -21,13 +21,7 @@ def get_data():
"type": "doctype",
"name": "Issue Priority",
"description": _("Issue Priority."),
- },
- {
- "type": "doctype",
- "name": "Communication",
- "description": _("Communication log."),
- "onboard": 1,
- },
+ }
]
},
{
diff --git a/erpnext/healthcare/doctype/patient/patient.js b/erpnext/healthcare/doctype/patient/patient.js
index 169281430ce..1a34fe8076f 100644
--- a/erpnext/healthcare/doctype/patient/patient.js
+++ b/erpnext/healthcare/doctype/patient/patient.js
@@ -21,9 +21,9 @@ frappe.ui.form.on('Patient', {
});
}
if (frm.doc.patient_name && frappe.user.has_role("Physician")) {
- frm.add_custom_button(__('Medical Record'), function () {
+ frm.add_custom_button(__('Patient History'), function () {
frappe.route_options = { "patient": frm.doc.name };
- frappe.set_route("medical_record");
+ frappe.set_route("patient_history");
},"View");
}
if (!frm.doc.__islocal && (frappe.user.has_role("Nursing User") || frappe.user.has_role("Physician"))) {
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
index b3cbd1f753d..858145eef3c 100644
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.js
@@ -30,9 +30,9 @@ frappe.ui.form.on('Patient Appointment', {
};
});
if(frm.doc.patient){
- frm.add_custom_button(__('Medical Record'), function() {
+ frm.add_custom_button(__('Patient History'), function() {
frappe.route_options = {"patient": frm.doc.patient};
- frappe.set_route("medical_record");
+ frappe.set_route("patient_history");
},__("View"));
}
if(frm.doc.status == "Open"){
diff --git a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
index 7ea45688fd9..088bc8161b1 100644
--- a/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
+++ b/erpnext/healthcare/doctype/patient_encounter/patient_encounter.js
@@ -41,10 +41,10 @@ frappe.ui.form.on('Patient Encounter', {
}
});
}
- frm.add_custom_button(__('Medical Record'), function() {
+ frm.add_custom_button(__('Patient History'), function() {
if (frm.doc.patient) {
frappe.route_options = {"patient": frm.doc.patient};
- frappe.set_route("medical_record");
+ frappe.set_route("patient_history");
} else {
frappe.msgprint(__("Please select Patient"));
}
diff --git a/erpnext/healthcare/page/medical_record/__init__.py b/erpnext/healthcare/page/medical_record/__init__.py
deleted file mode 100644
index baffc488252..00000000000
--- a/erpnext/healthcare/page/medical_record/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/healthcare/page/medical_record/medical_record.js b/erpnext/healthcare/page/medical_record/medical_record.js
deleted file mode 100644
index df19d8f4dca..00000000000
--- a/erpnext/healthcare/page/medical_record/medical_record.js
+++ /dev/null
@@ -1,182 +0,0 @@
-frappe.provide("frappe.medical_record");
-frappe.pages['medical_record'].on_page_load = function(wrapper) {
- var me = this;
- var page = frappe.ui.make_app_page({
- parent: wrapper,
- title: 'Medical Record',
- });
-
- frappe.breadcrumbs.add("Medical");
-
- page.main.html(frappe.render_template("patient_select", {}));
- var patient = frappe.ui.form.make_control({
- parent: page.main.find(".patient"),
- df: {
- fieldtype: "Link",
- options: "Patient",
- fieldname: "patient",
- change: function(){
- page.main.find(".frappe-list").html("");
- draw_page(patient.get_value(), me);
- }
- },
- only_input: true,
- });
- patient.refresh();
-
-
- this.page.main.on("click", ".medical_record-message", function() {
- var doctype = $(this).attr("data-doctype"),
- docname = $(this).attr("data-docname");
-
- if (doctype && docname) {
- frappe.route_options = {
- scroll_to: { "doctype": doctype, "name": docname }
- };
- frappe.set_route(["Form", doctype, docname]);
- }
- });
-
- this.page.sidebar.on("click", ".edit-details", function() {
- patient = patient.get_value();
- if (patient) {
- frappe.set_route(["Form", "Patient", patient]);
- }
- });
-
-};
-
-frappe.pages['medical_record'].refresh = function() {
- var me = this;
-
- if(frappe.route_options) {
- if(frappe.route_options.patient){
- me.page.main.find(".frappe-list").html("");
- var patient = frappe.route_options.patient;
- draw_page(patient,me);
- me.page.main.find("[data-fieldname='patient']").val(patient);
- frappe.route_options = null;
- }
- }
-};
-var show_patient_info = function(patient, me){
- frappe.call({
- "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
- args: {
- patient: patient
- },
- callback: function (r) {
- var data = r.message;
- var details = "";
- if(data.email) details += "
Email : " + data.email;
- if(data.mobile) details += "
Mobile : " + data.mobile;
- if(data.occupation) details += "
Occupation : " + data.occupation;
- if(data.blood_group) details += "
Blood group : " + data.blood_group;
- if(data.allergies) details += "
Allergies : "+ data.allergies;
- if(data.medication) details += "
Medication : "+ data.medication;
- if(data.alcohol_current_use) details += "
Alcohol use : "+ data.alcohol_current_use;
- if(data.alcohol_past_use) details += "
Alcohol past use : "+ data.alcohol_past_use;
- if(data.tobacco_current_use) details += "
Tobacco use : "+ data.tobacco_current_use;
- if(data.tobacco_past_use) details += "
Tobacco past use : "+ data.tobacco_past_use;
- if(data.medical_history) details += "
Medical history : "+ data.medical_history;
- if(data.surgical_history) details += "
Surgical history : "+ data.surgical_history;
- if(data.surrounding_factors) details += "
Occupational hazards : "+ data.surrounding_factors;
- if(data.other_risk_factors) details += "
Other risk factors : " + data.other_risk_factors;
- if(data.patient_details) details += "
More info : " + data.patient_details;
-
- if(details){
- details = "
Patient Details" + details + "
";
- }
-
- var vitals = "";
- if(data.temperature) vitals += "
Temperature : " + data.temperature;
- if(data.pulse) vitals += "
Pulse : " + data.pulse;
- if(data.respiratory_rate) vitals += "
Respiratory Rate : " + data.respiratory_rate;
- if(data.bp) vitals += "
BP : " + data.bp;
- if(data.bmi) vitals += "
BMI : " + data.bmi;
- if(data.height) vitals += "
Height : " + data.height;
- if(data.weight) vitals += "
Weight : " + data.weight;
- if(data.signs_date) vitals += "
Date : " + data.signs_date;
-
- if(vitals){
- vitals = "Vital Signs" + vitals + "
";
- details = vitals + details;
- }
- if(details) details += "";
-
- me.page.sidebar.addClass("col-sm-3");
- me.page.sidebar.html(details);
- me.page.wrapper.find(".layout-main-section-wrapper").addClass("col-sm-9");
- }
- });
-};
-var draw_page = function(patient, me){
- frappe.model.with_doctype("Patient Medical Record", function() {
- me.page.list = new frappe.ui.BaseList({
- hide_refresh: true,
- page: me.page,
- method: 'erpnext.healthcare.page.medical_record.medical_record.get_feed',
- args: {name: patient},
- parent: $("").appendTo(me.page.main),
- render_view: function(values) {
- var me = this;
- var wrapper = me.page.main.find(".result-list").get(0);
- values.map(function (value) {
- var row = $('').data("data", value).appendTo($(wrapper)).get(0);
- new frappe.medical_record.Feed(row, value);
- });
- },
- show_filters: true,
- doctype: "Patient Medical Record",
- });
- show_patient_info(patient, me);
- me.page.list.run();
- });
-};
-
-frappe.medical_record.last_feed_date = false;
-frappe.medical_record.Feed = Class.extend({
- init: function(row, data) {
- this.scrub_data(data);
- this.add_date_separator(row, data);
- if(!data.add_class)
- data.add_class = "label-default";
-
- data.link = "";
- if (data.reference_doctype && data.reference_name) {
- data.link = frappe.format(data.reference_name, {fieldtype: "Link", options: data.reference_doctype},
- {label: __(data.reference_doctype)});
- }
-
- $(row)
- .append(frappe.render_template("medical_record_row", data))
- .find("a").addClass("grey");
- },
- scrub_data: function(data) {
- data.by = frappe.user.full_name(data.owner);
- data.imgsrc = frappe.utils.get_file_link(frappe.user_info(data.owner).image);
-
- data.icon = "icon-flag";
- },
- add_date_separator: function(row, data) {
- var date = frappe.datetime.str_to_obj(data.creation);
- var last = frappe.medical_record.last_feed_date;
-
- if((last && frappe.datetime.obj_to_str(last) != frappe.datetime.obj_to_str(date)) || (!last)) {
- var diff = frappe.datetime.get_day_diff(frappe.datetime.get_today(), frappe.datetime.obj_to_str(date));
- if(diff < 1) {
- var pdate = 'Today';
- } else if(diff < 2) {
- pdate = 'Yesterday';
- } else {
- pdate = frappe.datetime.global_date_format(date);
- }
- data.date_sep = pdate;
- data.date_class = pdate=='Today' ? "date-indicator blue" : "date-indicator";
- } else {
- data.date_sep = null;
- data.date_class = "";
- }
- frappe.medical_record.last_feed_date = date;
- }
-});
diff --git a/erpnext/healthcare/page/medical_record/medical_record.py b/erpnext/healthcare/page/medical_record/medical_record.py
deleted file mode 100644
index 22c5852b05e..00000000000
--- a/erpnext/healthcare/page/medical_record/medical_record.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2015, ESS LLP and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-@frappe.whitelist()
-def get_feed(start, page_length, name):
- """get feed"""
- result = frappe.db.sql("""select name, owner, modified, creation,
- reference_doctype, reference_name, subject
- from `tabPatient Medical Record`
- where patient=%(patient)s
- order by creation desc
- limit %(start)s, %(page_length)s""",
- {
- "start": cint(start),
- "page_length": cint(page_length),
- "patient": name
- }, as_dict=True)
-
- return result
diff --git a/erpnext/healthcare/page/medical_record/medical_record_row.html b/erpnext/healthcare/page/medical_record/medical_record_row.html
deleted file mode 100644
index 9a670c9aa72..00000000000
--- a/erpnext/healthcare/page/medical_record/medical_record_row.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
- {%= date_sep || "" %}
-
-
-
-
-
-
-
- {% if (reference_doctype && reference_name) { %}
- {%= __("{0}: {1}", [link, "" + subject + ""]) %}
- {% } else { %}
- {%= subject %}
- {% } %}
-
-
-
diff --git a/erpnext/healthcare/page/medical_record/patient_select.html b/erpnext/healthcare/page/medical_record/patient_select.html
deleted file mode 100644
index 321baf738d7..00000000000
--- a/erpnext/healthcare/page/medical_record/patient_select.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
{%= __("Select Patient") %}
-
-
diff --git a/erpnext/healthcare/page/patient_history/__init__.py b/erpnext/healthcare/page/patient_history/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/erpnext/healthcare/page/medical_record/medical_record.css b/erpnext/healthcare/page/patient_history/patient_history.css
similarity index 62%
rename from erpnext/healthcare/page/medical_record/medical_record.css
rename to erpnext/healthcare/page/patient_history/patient_history.css
index 977625bbd17..865d6abee00 100644
--- a/erpnext/healthcare/page/medical_record/medical_record.css
+++ b/erpnext/healthcare/page/patient_history/patient_history.css
@@ -14,6 +14,10 @@
margin-bottom: -4px;
}
+.medical_record-row > * {
+ z-index: -999;
+}
+
.date-indicator {
background:none;
font-size:12px;
@@ -35,6 +39,61 @@
color: #5e64ff;
}
+.div-bg-color {
+ background: #fafbfc;
+}
+
+.bg-color-white {
+ background: #FFFFFF;
+}
+
+.d-flex {
+ display: flex;
+}
+
+.width-full {
+ width: 100%;
+}
+
+.p-3 {
+ padding: 16px;
+}
+
+.mt-2 {
+ margin-top: 8px;
+}
+
+.mr-3 {
+ margin-right: 16px;
+}
+
+.Box {
+ background-color: #fff;
+ border: 1px solid #d1d5da;
+ border-radius: 3px;
+}
+
+.flex-column {
+ flex-direction: column;
+}
+
+.avatar {
+ display: inline-block;
+ overflow: hidden;
+ line-height: 1;
+ vertical-align: middle;
+ border-radius: 3px;
+}
+
+.py-3 {
+ padding-top: 16px;
+ padding-bottom: 16px;
+}
+
+.border-bottom {
+ border-bottom: 1px #e1e4e8 solid;
+}
+
.date-indicator.blue::after {
background: #5e64ff;
}
@@ -65,8 +124,3 @@
#page-medical_record .list-filters {
display: none ;
}
-
-#page-medical_record .octicon-heart {
- color: #ff5858;
- margin: 0px 5px;
-}
diff --git a/erpnext/healthcare/page/patient_history/patient_history.html b/erpnext/healthcare/page/patient_history/patient_history.html
new file mode 100644
index 00000000000..7a9446dffd7
--- /dev/null
+++ b/erpnext/healthcare/page/patient_history/patient_history.html
@@ -0,0 +1,20 @@
+
+
+
{%= __("Select Patient") %}
+
+
+
+
+
\ No newline at end of file
diff --git a/erpnext/healthcare/page/patient_history/patient_history.js b/erpnext/healthcare/page/patient_history/patient_history.js
new file mode 100644
index 00000000000..87fe7edd297
--- /dev/null
+++ b/erpnext/healthcare/page/patient_history/patient_history.js
@@ -0,0 +1,300 @@
+frappe.provide("frappe.patient_history");
+frappe.pages['patient_history'].on_page_load = function(wrapper) {
+ var me = this;
+ var page = frappe.ui.make_app_page({
+ parent: wrapper,
+ title: 'Patient History',
+ single_column: true
+ });
+
+ frappe.breadcrumbs.add("Healthcare");
+ let pid = '';
+ page.main.html(frappe.render_template("patient_history", {}));
+ var patient = frappe.ui.form.make_control({
+ parent: page.main.find(".patient"),
+ df: {
+ fieldtype: "Link",
+ options: "Patient",
+ fieldname: "patient",
+ change: function(){
+ if(pid != patient.get_value() && patient.get_value()){
+ me.start = 0;
+ me.page.main.find(".patient_documents_list").html("");
+ get_documents(patient.get_value(), me);
+ show_patient_info(patient.get_value(), me);
+ show_patient_vital_charts(patient.get_value(), me, "bp", "mmHg", "Blood Pressure");
+ }
+ pid = patient.get_value();
+ }
+ },
+ only_input: true,
+ });
+ patient.refresh();
+
+ if (frappe.route_options){
+ patient.set_value(frappe.route_options.patient);
+ }
+
+ this.page.main.on("click", ".btn-show-chart", function() {
+ var btn_show_id = $(this).attr("data-show-chart-id"), pts = $(this).attr("data-pts");
+ var title = $(this).attr("data-title");
+ show_patient_vital_charts(patient.get_value(), me, btn_show_id, pts, title);
+ });
+
+ this.page.main.on("click", ".btn-more", function() {
+ var doctype = $(this).attr("data-doctype"), docname = $(this).attr("data-docname");
+ if(me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched') == "1"){
+ me.page.main.find("."+docname).hide();
+ me.page.main.find("."+docname).parent().find('.document-html').show();
+ }else{
+ if(doctype && docname){
+ let exclude = ["patient", "patient_name", 'patient_sex', "encounter_date"];
+ frappe.call({
+ method: "erpnext.healthcare.utils.render_doc_as_html",
+ args:{
+ doctype: doctype,
+ docname: docname,
+ exclude_fields: exclude
+ },
+ callback: function(r) {
+ if (r.message){
+ me.page.main.find("."+docname).hide();
+ me.page.main.find("."+docname).parent().find('.document-html').html(r.message.html+"\
+
");
+ me.page.main.find("."+docname).parent().find('.document-html').show();
+ me.page.main.find("."+docname).parent().find('.document-html').attr('data-fetched', "1");
+ }
+ },
+ freeze: true
+ });
+ }
+ }
+ });
+
+ this.page.main.on("click", ".btn-less", function() {
+ var docname = $(this).attr("data-docname");
+ me.page.main.find("."+docname).parent().find('.document-id').show();
+ me.page.main.find("."+docname).parent().find('.document-html').hide();
+ });
+ me.start = 0;
+ me.page.main.on("click", ".btn-get-records", function(){
+ get_documents(patient.get_value(), me);
+ });
+};
+
+var get_documents = function(patient, me){
+ frappe.call({
+ "method": "erpnext.healthcare.page.patient_history.patient_history.get_feed",
+ args: {
+ name: patient,
+ start: me.start,
+ page_length: 20
+ },
+ callback: function (r) {
+ var data = r.message;
+ if(data.length){
+ add_to_records(me, data);
+ }else{
+ me.page.main.find(".patient_documents_list").append("
No more records..
");
+ me.page.main.find(".btn-get-records").hide();
+ }
+ }
+ });
+};
+
+var add_to_records = function(me, data){
+ var details = "
";
+ var i;
+ for(i=0; i"+data[i].subject;
+ }
+ data[i] = add_date_separator(data[i]);
+ if(frappe.user_info(data[i].owner).image){
+ data[i].imgsrc = frappe.utils.get_file_link(frappe.user_info(data[i].owner).image);
+ }
+ else{
+ data[i].imgsrc = false;
+ }
+ var time_line_heading = data[i].practitioner ? `${data[i].practitioner} ` : ``;
+ time_line_heading += data[i].reference_doctype + " - "+ data[i].reference_name;
+ details += ``;
+ }
+ }
+ details += "
";
+ me.page.main.find(".patient_documents_list").append(details);
+ me.start += data.length;
+ if(data.length===20){
+ me.page.main.find(".btn-get-records").show();
+ }else{
+ me.page.main.find(".btn-get-records").hide();
+ me.page.main.find(".patient_documents_list").append("
No more records..
");
+ }
+};
+
+var add_date_separator = function(data) {
+ var date = frappe.datetime.str_to_obj(data.creation);
+
+ var diff = frappe.datetime.get_day_diff(frappe.datetime.get_today(), frappe.datetime.obj_to_str(date));
+ if(diff < 1) {
+ var pdate = 'Today';
+ } else if(diff < 2) {
+ pdate = 'Yesterday';
+ } else {
+ pdate = frappe.datetime.global_date_format(date);
+ }
+ data.date_sep = pdate;
+ return data;
+};
+
+var show_patient_info = function(patient, me){
+ frappe.call({
+ "method": "erpnext.healthcare.doctype.patient.patient.get_patient_detail",
+ args: {
+ patient: patient
+ },
+ callback: function (r) {
+ var data = r.message;
+ var details = "";
+ if(data.image){
+ details += "
";
+ }
+ details += "
" + data.patient_name +"" + data.sex;
+ if(data.email) details += "
" + data.email;
+ if(data.mobile) details += "
" + data.mobile;
+ if(data.occupation) details += "
Occupation : " + data.occupation;
+ if(data.blood_group) details += "
Blood group : " + data.blood_group;
+ if(data.allergies) details += "
Allergies : "+ data.allergies.replace("\n", "
");
+ if(data.medication) details += "
Medication : "+ data.medication.replace("\n", "
");
+ if(data.alcohol_current_use) details += "
Alcohol use : "+ data.alcohol_current_use;
+ if(data.alcohol_past_use) details += "
Alcohol past use : "+ data.alcohol_past_use;
+ if(data.tobacco_current_use) details += "
Tobacco use : "+ data.tobacco_current_use;
+ if(data.tobacco_past_use) details += "
Tobacco past use : "+ data.tobacco_past_use;
+ if(data.medical_history) details += "
Medical history : "+ data.medical_history.replace("\n", "
");
+ if(data.surgical_history) details += "
Surgical history : "+ data.surgical_history.replace("\n", "
");
+ if(data.surrounding_factors) details += "
Occupational hazards : "+ data.surrounding_factors.replace("\n", "
");
+ if(data.other_risk_factors) details += "
Other risk factors : " + data.other_risk_factors.replace("\n", "
");
+ if(data.patient_details) details += "
More info : " + data.patient_details.replace("\n", "
");
+
+ if(details){
+ details = "
" + details + "
";
+ }
+ me.page.main.find(".patient_details").html(details);
+ }
+ });
+};
+
+var show_patient_vital_charts = function(patient, me, btn_show_id, pts, title) {
+ frappe.call({
+ method: "erpnext.healthcare.utils.get_patient_vitals",
+ args:{
+ patient: patient
+ },
+ callback: function(r) {
+ if (r.message){
+ var show_chart_btns_html = "
";
+ me.page.main.find(".show_chart_btns").html(show_chart_btns_html);
+ var data = r.message;
+ let labels = [], datasets = [];
+ let bp_systolic = [], bp_diastolic = [], temperature = [];
+ let pulse = [], respiratory_rate = [], bmi = [], height = [], weight = [];
+ for(var i=0; i
(d + '').toUpperCase(),
+ formatTooltipY: d => d + ' ' + pts,
+ }
+ });
+ }else{
+ me.page.main.find(".patient_vital_charts").html("");
+ me.page.main.find(".show_chart_btns").html("");
+ }
+ }
+ });
+};
diff --git a/erpnext/healthcare/page/medical_record/medical_record.json b/erpnext/healthcare/page/patient_history/patient_history.json
similarity index 57%
rename from erpnext/healthcare/page/medical_record/medical_record.json
rename to erpnext/healthcare/page/patient_history/patient_history.json
index ca30c3be29e..b3892a41c60 100644
--- a/erpnext/healthcare/page/medical_record/medical_record.json
+++ b/erpnext/healthcare/page/patient_history/patient_history.json
@@ -1,18 +1,21 @@
{
"content": null,
- "creation": "2016-06-09 11:33:14.025787",
+ "creation": "2018-08-08 17:09:13.816199",
"docstatus": 0,
"doctype": "Page",
- "icon": "icon-play",
+ "icon": "",
"idx": 0,
- "modified": "2018-08-06 11:40:39.705660",
+ "modified": "2018-08-08 17:09:55.969424",
"modified_by": "Administrator",
"module": "Healthcare",
- "name": "medical_record",
+ "name": "patient_history",
"owner": "Administrator",
- "page_name": "medical_record",
+ "page_name": "patient_history",
"restrict_to_domain": "Healthcare",
"roles": [
+ {
+ "role": "Healthcare Administrator"
+ },
{
"role": "Physician"
}
@@ -21,5 +24,5 @@
"standard": "Yes",
"style": null,
"system_page": 0,
- "title": "Medical Record"
+ "title": "Patient History"
}
\ No newline at end of file
diff --git a/erpnext/healthcare/page/patient_history/patient_history.py b/erpnext/healthcare/page/patient_history/patient_history.py
new file mode 100644
index 00000000000..772aa4ef5eb
--- /dev/null
+++ b/erpnext/healthcare/page/patient_history/patient_history.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2018, ESS LLP and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import cint
+from erpnext.healthcare.utils import render_docs_as_html
+
+@frappe.whitelist()
+def get_feed(name, start=0, page_length=20):
+ """get feed"""
+ result = frappe.db.sql("""select name, owner, creation,
+ reference_doctype, reference_name, subject
+ from `tabPatient Medical Record`
+ where patient=%(patient)s
+ order by creation desc
+ limit %(start)s, %(page_length)s""",
+ {
+ "patient": name,
+ "start": cint(start),
+ "page_length": cint(page_length)
+ }, as_dict=True)
+ return result
+
+@frappe.whitelist()
+def get_feed_for_dt(doctype, docname):
+ """get feed"""
+ result = frappe.db.sql("""select name, owner, modified, creation,
+ reference_doctype, reference_name, subject
+ from `tabPatient Medical Record`
+ where reference_name=%(docname)s and reference_doctype=%(doctype)s
+ order by creation desc""",
+ {
+ "docname": docname,
+ "doctype": doctype
+ }, as_dict=True)
+
+ return result
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 6a226d9c6b2..97bb98f6779 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -429,3 +429,116 @@ def get_children(doctype, parent, company, is_root=False):
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
each["occupied_out_of_vacant"] = occupancy_msg
return hc_service_units
+
+@frappe.whitelist()
+def get_patient_vitals(patient, from_date=None, to_date=None):
+ if not patient: return
+ vitals = frappe.db.sql("""select * from `tabVital Signs` where \
+ docstatus=1 and patient=%s order by signs_date, signs_time""", \
+ (patient), as_dict=1)
+ if vitals and vitals[0]:
+ return vitals
+ else:
+ return False
+
+@frappe.whitelist()
+def render_docs_as_html(docs):
+ # docs key value pair {doctype: docname}
+ docs_html = ""
+ for doc in docs:
+ docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + "
"
+ return {'html': docs_html}
+
+@frappe.whitelist()
+def render_doc_as_html(doctype, docname, exclude_fields = []):
+ #render document as html, three column layout will break
+ doc = frappe.get_doc(doctype, docname)
+ meta = frappe.get_meta(doctype)
+ doc_html = "
"
+ section_html = ""
+ section_label = ""
+ html = ""
+ sec_on = False
+ col_on = 0
+ has_data = False
+ for df in meta.fields:
+ #on section break append append previous section and html to doc html
+ if df.fieldtype == "Section Break":
+ if has_data and col_on and sec_on:
+ doc_html += section_html + html + "
"
+ elif has_data and not col_on and sec_on:
+ doc_html += "
" \
+ + section_html + html +"
"
+ while col_on:
+ doc_html += "
"
+ col_on -= 1
+ sec_on = True
+ has_data= False
+ col_on = 0
+ section_html = ""
+ html = ""
+ if df.label:
+ section_label = df.label
+ continue
+ #on column break append html to section html or doc html
+ if df.fieldtype == "Column Break":
+ if sec_on and has_data:
+ section_html += "" + section_label + "" + html + "
"
+ elif has_data:
+ doc_html += "
" + html + "
"
+ elif sec_on and not col_on:
+ section_html += "
"
+ html = ""
+ col_on += 1
+ if df.label:
+ html += '
' + df.label
+ continue
+ #on table iterate in items and create table based on in_list_view, append to section html or doc html
+ if df.fieldtype == "Table":
+ items = doc.get(df.fieldname)
+ if not items: continue
+ child_meta = frappe.get_meta(df.options)
+ if not has_data : has_data = True
+ table_head = ""
+ table_row = ""
+ create_head = True
+ for item in items:
+ table_row += '
'
+ for cdf in child_meta.fields:
+ if cdf.in_list_view:
+ if create_head:
+ table_head += '| ' + cdf.label + ' | '
+ if item.get(cdf.fieldname):
+ table_row += '' + str(item.get(cdf.fieldname)) \
+ + ' | '
+ else:
+ table_row += ' | '
+ create_head = False
+ table_row += '
'
+ if sec_on:
+ section_html += '
' + table_head + table_row + '
'
+ else:
+ html += '
' \
+ + table_head + table_row + '
'
+ continue
+ #on other field types add label and value to html
+ if not df.hidden and not df.print_hide and doc.get(df.fieldname) and df.fieldname not in exclude_fields:
+ html += "
{0} : {1}".format(df.label or df.fieldname, \
+ doc.get(df.fieldname))
+ if not has_data : has_data = True
+ if sec_on and col_on and has_data:
+ doc_html += section_html + html + "
"
+ elif sec_on and not col_on and has_data:
+ doc_html += "
" \
+ + section_html + html +"
"
+ if doc_html:
+ doc_html = "
" %(doctype, docname) + doc_html + "
"
+
+ return {'html': doc_html}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 571c2dc75b4..a29378547ea 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -605,6 +605,7 @@ erpnext.patches.v11_1.delete_scheduling_tool
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
erpnext.patches.v12_0.make_item_manufacturer
+erpnext.patches.v12_0.remove_patient_medical_record_page
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
erpnext.patches.v11_1.set_default_action_for_quality_inspection
erpnext.patches.v11_1.delete_bom_browser
diff --git a/erpnext/patches/v12_0/remove_patient_medical_record_page.py b/erpnext/patches/v12_0/remove_patient_medical_record_page.py
new file mode 100644
index 00000000000..904bfe4bf19
--- /dev/null
+++ b/erpnext/patches/v12_0/remove_patient_medical_record_page.py
@@ -0,0 +1,7 @@
+# Copyright (c) 2019
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.delete_doc("Page", "medical_record")
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 2b079e7995f..f2fe44879db 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -450,7 +450,7 @@ def make_stock_entry(source_name, target_doc=None):
"field_map": {
"name": "material_request_item",
"parent": "material_request",
- "uom": "stock_uom",
+ "uom": "stock_uom"
},
"postprocess": update_item,
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index 59337004579..912a4651b3c 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -61,7 +61,8 @@
"ste_detail",
"column_break_51",
"transferred_qty",
- "reference_purchase_receipt"
+ "reference_purchase_receipt",
+ "project"
],
"fields": [
{
@@ -472,11 +473,18 @@
"label": "Reference Purchase Receipt",
"options": "Purchase Receipt",
"read_only": 1
+ },
+ {
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "options": "Project",
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-06-14 11:58:41.958144",
+ "modified": "2019-07-12 11:34:53.190749",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index 2d9650c5a4d..aec9db9d4ac 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -2,6 +2,12 @@ frappe.ui.form.on("Issue", {
onload: function(frm) {
frm.email_field = "raised_by";
+ frappe.db.get_value("Support Settings", {name: "Support Settings"}, "allow_resetting_service_level_agreement", (r) => {
+ if (!r.allow_resetting_service_level_agreement) {
+ frm.set_df_property("reset_service_level_agreement", "hidden", 1) ;
+ }
+ });
+
if (frm.doc.service_level_agreement) {
frappe.call({
method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters",
@@ -73,6 +79,42 @@ frappe.ui.form.on("Issue", {
}
},
+ reset_service_level_agreement: function(frm) {
+ let reset_sla = new frappe.ui.Dialog({
+ title: __("Reset Service Level Agreement"),
+ fields: [
+ {
+ fieldtype: "Data",
+ fieldname: "reason",
+ label: __("Reason"),
+ reqd: 1
+ }
+ ],
+ primary_action_label: __("Reset"),
+ primary_action: (values) => {
+ reset_sla.disable_primary_action();
+ reset_sla.hide();
+ reset_sla.clear();
+
+ frappe.show_alert({
+ indicator: 'green',
+ message: __('Resetting Service Level Agreement.')
+ });
+
+ frm.call("reset_service_level_agreement", {
+ reason: values.reason,
+ user: frappe.session.user_email
+ }, () => {
+ reset_sla.enable_primary_action();
+ frm.refresh();
+ frappe.msgprint(__("Service Level Agreement Reset."));
+ });
+ }
+ });
+
+ reset_sla.show();
+ },
+
timeline_refresh: function(frm) {
// create button for "Help Article"
if(frappe.model.can_create('Help Article')) {
diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json
index 72153dcdea3..41fe380e757 100644
--- a/erpnext/support/doctype/issue/issue.json
+++ b/erpnext/support/doctype/issue/issue.json
@@ -22,10 +22,12 @@
"service_level_agreement",
"response_by",
"response_by_variance",
+ "reset_service_level_agreement",
"cb",
"agreement_fulfilled",
"resolution_by",
"resolution_by_variance",
+ "service_level_agreement_creation",
"response",
"mins_to_first_response",
"first_responded_on",
@@ -68,9 +70,9 @@
"fieldname": "subject",
"fieldtype": "Data",
"in_global_search": 1,
+ "in_standard_filter": 1,
"label": "Subject",
- "reqd": 1,
- "in_standard_filter": 1
+ "reqd": 1
},
{
"fieldname": "customer",
@@ -336,11 +338,24 @@
"fieldtype": "Float",
"label": "Resolution By Variance",
"read_only": 1
+ },
+ {
+ "fieldname": "service_level_agreement_creation",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "label": "Service Level Agreement Creation",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval: doc.service_level_agreement",
+ "fieldname": "reset_service_level_agreement",
+ "fieldtype": "Button",
+ "label": "Reset Service Level Agreement"
}
],
"icon": "fa fa-ticket",
"idx": 7,
- "modified": "2019-06-30 13:19:38.215525",
+ "modified": "2019-07-11 23:57:22.015881",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",
@@ -365,4 +380,4 @@
"timeline_field": "customer",
"title_field": "subject",
"track_seen": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index 226676fec33..ce9fb121459 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -121,6 +121,7 @@ class Issue(Document):
# Reset SLA
if replicated_issue.service_level_agreement:
+ replicated_issue.service_level_agreement_creation = now_datetime()
replicated_issue.service_level_agreement = None
replicated_issue.agreement_fulfilled = "Ongoing"
replicated_issue.response_by = None
@@ -173,8 +174,9 @@ class Issue(Document):
if not self.creation:
self.creation = now_datetime()
+ self.service_level_agreement_creation = now_datetime()
- start_date_time = get_datetime(self.creation)
+ start_date_time = get_datetime(self.service_level_agreement_creation)
self.response_by = get_expected_time_for(parameter='response', service_level=priority, start_date_time=start_date_time)
self.resolution_by = get_expected_time_for(parameter='resolution', service_level=priority, start_date_time=start_date_time)
@@ -193,6 +195,23 @@ class Issue(Document):
self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
frappe.msgprint(_("Service Level Agreement has been changed to {0}.").format(self.service_level_agreement))
+ def reset_service_level_agreement(self, reason, user):
+ if not frappe.db.get_single_value("Support Settings", "allow_resetting_service_level_agreement"):
+ frappe.throw(_("Allow Resetting Service Level Agreement from Support Settings."))
+
+ frappe.get_doc({
+ "doctype": "Comment",
+ "comment_type": "Info",
+ "reference_doctype": self.doctype,
+ "reference_name": self.name,
+ "comment_email": user,
+ "content": " resetted Service Level Agreement - {0}".format(_(reason)),
+ }).insert(ignore_permissions=True)
+
+ self.service_level_agreement_creation = now_datetime()
+ self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
+ self.save()
+
def get_expected_time_for(parameter, service_level, start_date_time):
current_date_time = start_date_time
expected_time = current_date_time
diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py
index eb1736e6c98..7a5e3e300db 100644
--- a/erpnext/support/doctype/issue/test_issue.py
+++ b/erpnext/support/doctype/issue/test_issue.py
@@ -80,7 +80,8 @@ def make_issue(creation=None, customer=None, index=0):
"customer": customer,
"raised_by": "test@example.com",
"description": "Service Level Agreement Issue",
- "creation": creation
+ "creation": creation,
+ "service_level_agreement_creation": creation
}).insert(ignore_permissions=True)
return issue
diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
index 68b82d10eca..4a741ea4e18 100644
--- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
@@ -76,6 +76,7 @@ def create_service_level_agreement(default_service_level_agreement, service_leve
service_level_agreement = frappe.get_doc({
"doctype": "Service Level Agreement",
+ "enable": 1,
"default_service_level_agreement": default_service_level_agreement,
"service_level": service_level,
"holiday_list": holiday_list,
diff --git a/erpnext/support/doctype/support_settings/support_settings.json b/erpnext/support/doctype/support_settings/support_settings.json
index 2dced15d4e6..be9e0645915 100644
--- a/erpnext/support/doctype/support_settings/support_settings.json
+++ b/erpnext/support/doctype/support_settings/support_settings.json
@@ -6,6 +6,7 @@
"field_order": [
"sb_00",
"track_service_level_agreement",
+ "allow_resetting_service_level_agreement",
"issues_sb",
"close_issue_after_days",
"portal_sb",
@@ -118,10 +119,16 @@
"fieldname": "track_service_level_agreement",
"fieldtype": "Check",
"label": "Track Service Level Agreement"
+ },
+ {
+ "default": "0",
+ "fieldname": "allow_resetting_service_level_agreement",
+ "fieldtype": "Check",
+ "label": "Allow Resetting Service Level Agreement"
}
],
"issingle": 1,
- "modified": "2019-07-09 17:11:38.216732",
+ "modified": "2019-07-10 22:52:39.663873",
"modified_by": "Administrator",
"module": "Support",
"name": "Support Settings",