mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-15 19:19:17 +00:00
Merge branch 'develop' into feat-manufacturer-is-missing-contacts
This commit is contained in:
@@ -69,7 +69,9 @@ def execute(filters=None):
|
|||||||
add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency)
|
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)
|
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():
|
def get_cash_flow_accounts():
|
||||||
operation_accounts = {
|
operation_accounts = {
|
||||||
@@ -171,4 +173,21 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated
|
|||||||
total_row["total"] += row["total"]
|
total_row["total"] += row["total"]
|
||||||
|
|
||||||
out.append(total_row)
|
out.append(total_row)
|
||||||
out.append({})
|
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
|
||||||
|
|||||||
@@ -66,10 +66,11 @@
|
|||||||
"net_total",
|
"net_total",
|
||||||
"total_net_weight",
|
"total_net_weight",
|
||||||
"taxes_section",
|
"taxes_section",
|
||||||
"taxes_and_charges",
|
"tax_category",
|
||||||
"column_break_50",
|
"column_break_50",
|
||||||
"shipping_rule",
|
"shipping_rule",
|
||||||
"section_break_52",
|
"section_break_52",
|
||||||
|
"taxes_and_charges",
|
||||||
"taxes",
|
"taxes",
|
||||||
"sec_tax_breakup",
|
"sec_tax_breakup",
|
||||||
"other_charges_calculation",
|
"other_charges_calculation",
|
||||||
@@ -569,7 +570,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "taxes_and_charges",
|
"fieldname": "taxes_and_charges",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Taxes and Charges",
|
"label": "Purchase Taxes and Charges Template",
|
||||||
"oldfieldname": "purchase_other_charges",
|
"oldfieldname": "purchase_other_charges",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Purchase Taxes and Charges Template",
|
"options": "Purchase Taxes and Charges Template",
|
||||||
@@ -1032,12 +1033,18 @@
|
|||||||
"fieldname": "update_auto_repeat_reference",
|
"fieldname": "update_auto_repeat_reference",
|
||||||
"fieldtype": "Button",
|
"fieldtype": "Button",
|
||||||
"label": "Update Auto Repeat Reference"
|
"label": "Update Auto Repeat Reference"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "tax_category",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Tax Category",
|
||||||
|
"options": "Tax Category"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2019-06-24 21:22:05.483429",
|
"modified": "2019-07-11 18:25:49.509343",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "page",
|
"type": "page",
|
||||||
"name": "medical_record",
|
"name": "patient_history",
|
||||||
"label": _("Patient Medical Record"),
|
"label": _("Patient History"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "page",
|
"type": "page",
|
||||||
|
|||||||
@@ -21,13 +21,7 @@ def get_data():
|
|||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Issue Priority",
|
"name": "Issue Priority",
|
||||||
"description": _("Issue Priority."),
|
"description": _("Issue Priority."),
|
||||||
},
|
}
|
||||||
{
|
|
||||||
"type": "doctype",
|
|
||||||
"name": "Communication",
|
|
||||||
"description": _("Communication log."),
|
|
||||||
"onboard": 1,
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ frappe.ui.form.on('Patient', {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (frm.doc.patient_name && frappe.user.has_role("Physician")) {
|
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.route_options = { "patient": frm.doc.name };
|
||||||
frappe.set_route("medical_record");
|
frappe.set_route("patient_history");
|
||||||
},"View");
|
},"View");
|
||||||
}
|
}
|
||||||
if (!frm.doc.__islocal && (frappe.user.has_role("Nursing User") || frappe.user.has_role("Physician"))) {
|
if (!frm.doc.__islocal && (frappe.user.has_role("Nursing User") || frappe.user.has_role("Physician"))) {
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ frappe.ui.form.on('Patient Appointment', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
if(frm.doc.patient){
|
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.route_options = {"patient": frm.doc.patient};
|
||||||
frappe.set_route("medical_record");
|
frappe.set_route("patient_history");
|
||||||
},__("View"));
|
},__("View"));
|
||||||
}
|
}
|
||||||
if(frm.doc.status == "Open"){
|
if(frm.doc.status == "Open"){
|
||||||
|
|||||||
@@ -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) {
|
if (frm.doc.patient) {
|
||||||
frappe.route_options = {"patient": frm.doc.patient};
|
frappe.route_options = {"patient": frm.doc.patient};
|
||||||
frappe.set_route("medical_record");
|
frappe.set_route("patient_history");
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint(__("Please select Patient"));
|
frappe.msgprint(__("Please select Patient"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
@@ -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 += "<br><b>Email :</b> " + data.email;
|
|
||||||
if(data.mobile) details += "<br><b>Mobile :</b> " + data.mobile;
|
|
||||||
if(data.occupation) details += "<br><b>Occupation :</b> " + data.occupation;
|
|
||||||
if(data.blood_group) details += "<br><b>Blood group : </b> " + data.blood_group;
|
|
||||||
if(data.allergies) details += "<br><br><b>Allergies : </b> "+ data.allergies;
|
|
||||||
if(data.medication) details += "<br><b>Medication : </b> "+ data.medication;
|
|
||||||
if(data.alcohol_current_use) details += "<br><br><b>Alcohol use : </b> "+ data.alcohol_current_use;
|
|
||||||
if(data.alcohol_past_use) details += "<br><b>Alcohol past use : </b> "+ data.alcohol_past_use;
|
|
||||||
if(data.tobacco_current_use) details += "<br><b>Tobacco use : </b> "+ data.tobacco_current_use;
|
|
||||||
if(data.tobacco_past_use) details += "<br><b>Tobacco past use : </b> "+ data.tobacco_past_use;
|
|
||||||
if(data.medical_history) details += "<br><br><b>Medical history : </b> "+ data.medical_history;
|
|
||||||
if(data.surgical_history) details += "<br><b>Surgical history : </b> "+ data.surgical_history;
|
|
||||||
if(data.surrounding_factors) details += "<br><br><b>Occupational hazards : </b> "+ data.surrounding_factors;
|
|
||||||
if(data.other_risk_factors) details += "<br><b>Other risk factors : </b> " + data.other_risk_factors;
|
|
||||||
if(data.patient_details) details += "<br><br><b>More info : </b> " + data.patient_details;
|
|
||||||
|
|
||||||
if(details){
|
|
||||||
details = "<div style='padding-left:10px; font-size:13px;' align='center'></br><b class='text-muted'>Patient Details</b>" + details + "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
var vitals = "";
|
|
||||||
if(data.temperature) vitals += "<br><b>Temperature :</b> " + data.temperature;
|
|
||||||
if(data.pulse) vitals += "<br><b>Pulse :</b> " + data.pulse;
|
|
||||||
if(data.respiratory_rate) vitals += "<br><b>Respiratory Rate :</b> " + data.respiratory_rate;
|
|
||||||
if(data.bp) vitals += "<br><b>BP :</b> " + data.bp;
|
|
||||||
if(data.bmi) vitals += "<br><b>BMI :</b> " + data.bmi;
|
|
||||||
if(data.height) vitals += "<br><b>Height :</b> " + data.height;
|
|
||||||
if(data.weight) vitals += "<br><b>Weight :</b> " + data.weight;
|
|
||||||
if(data.signs_date) vitals += "<br><b>Date :</b> " + data.signs_date;
|
|
||||||
|
|
||||||
if(vitals){
|
|
||||||
vitals = "<div style='padding-left:10px; font-size:13px;' align='center'></br><b class='text-muted'>Vital Signs</b>" + vitals + "<br></div>";
|
|
||||||
details = vitals + details;
|
|
||||||
}
|
|
||||||
if(details) details += "<div align='center'><br><a class='btn btn-default btn-sm edit-details'>Edit Details</a></b> </div>";
|
|
||||||
|
|
||||||
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: $("<div></div>").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 = $('<div class="list-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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -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
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<div class="row medical_record-row" data-creation="{%= creation.split(" ")[0] + " 00:00:00" %}">
|
|
||||||
<div class="col-xs-3 text-right medical_record-date"><span class="{%= date_class %}">
|
|
||||||
{%= date_sep || "" %}</span>
|
|
||||||
</div>
|
|
||||||
<div class="col-xs-9 medical_record-message"
|
|
||||||
data-doctype="{%= reference_doctype %}"
|
|
||||||
data-docname="{%= reference_name %}"
|
|
||||||
title="{%= by %} / {%= frappe.datetime.str_to_user(creation) %}">
|
|
||||||
<span class="avatar avatar-small">
|
|
||||||
<div class="avatar-frame" style="background-image: url({{ imgsrc }});"></div>
|
|
||||||
<!-- <img src="{%= imgsrc %}"> -->
|
|
||||||
</span>
|
|
||||||
<span class="small">
|
|
||||||
{% if (reference_doctype && reference_name) { %}
|
|
||||||
{%= __("{0}: {1}", [link, "<strong>" + subject + "</strong>"]) %}
|
|
||||||
{% } else { %}
|
|
||||||
{%= subject %}
|
|
||||||
{% } %}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<div class="text-center col-sm-9" style="padding: 40px;">
|
|
||||||
|
|
||||||
<p>{%= __("Select Patient") %}</p>
|
|
||||||
<p class="patient" style="margin: auto; max-width: 300px; margin-bottom: 20px;"></p>
|
|
||||||
</div>
|
|
||||||
0
erpnext/healthcare/page/patient_history/__init__.py
Normal file
0
erpnext/healthcare/page/patient_history/__init__.py
Normal file
@@ -14,6 +14,10 @@
|
|||||||
margin-bottom: -4px;
|
margin-bottom: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.medical_record-row > * {
|
||||||
|
z-index: -999;
|
||||||
|
}
|
||||||
|
|
||||||
.date-indicator {
|
.date-indicator {
|
||||||
background:none;
|
background:none;
|
||||||
font-size:12px;
|
font-size:12px;
|
||||||
@@ -35,6 +39,61 @@
|
|||||||
color: #5e64ff;
|
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 {
|
.date-indicator.blue::after {
|
||||||
background: #5e64ff;
|
background: #5e64ff;
|
||||||
}
|
}
|
||||||
@@ -65,8 +124,3 @@
|
|||||||
#page-medical_record .list-filters {
|
#page-medical_record .list-filters {
|
||||||
display: none ;
|
display: none ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#page-medical_record .octicon-heart {
|
|
||||||
color: #ff5858;
|
|
||||||
margin: 0px 5px;
|
|
||||||
}
|
|
||||||
20
erpnext/healthcare/page/patient_history/patient_history.html
Normal file
20
erpnext/healthcare/page/patient_history/patient_history.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<p class="text-center">{%= __("Select Patient") %}</p>
|
||||||
|
<p class="patient" style="margin: auto; max-width: 300px; margin-bottom: 20px;"></p>
|
||||||
|
<div class="patient_details" style="z-index=0"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-9 patient_documents">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="col-sm-12 show_chart_btns" align="center">
|
||||||
|
</div>
|
||||||
|
<div id="chart" class="col-sm-12 patient_vital_charts">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 patient_documents_list">
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-12 text-center py-3">
|
||||||
|
<a class="btn btn-sm btn-default btn-get-records" style="display:none">More..</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
300
erpnext/healthcare/page/patient_history/patient_history.js
Normal file
300
erpnext/healthcare/page/patient_history/patient_history.js
Normal file
@@ -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+"\
|
||||||
|
<div align='center'><a class='btn octicon octicon-chevron-up btn-default btn-xs\
|
||||||
|
btn-less' data-doctype='"+doctype+"' data-docname='"+docname+"'></a></div>");
|
||||||
|
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("<div class='text-muted' align='center'><br><br>No more records..<br><br></div>");
|
||||||
|
me.page.main.find(".btn-get-records").hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var add_to_records = function(me, data){
|
||||||
|
var details = "<ul class='nav nav-pills nav-stacked'>";
|
||||||
|
var i;
|
||||||
|
for(i=0; i<data.length; i++){
|
||||||
|
if(data[i].reference_doctype){
|
||||||
|
let label = '';
|
||||||
|
if(data[i].subject){
|
||||||
|
label += "<br/>"+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 += `<li data-toggle='pill' class='patient_doc_menu'
|
||||||
|
data-doctype='${data[i].reference_doctype}' data-docname='${data[i].reference_name}'>
|
||||||
|
<div class='col-sm-12 d-flex border-bottom py-3'>`;
|
||||||
|
if (data[i].imgsrc){
|
||||||
|
details += `<span class='mr-3'>
|
||||||
|
<img class='avtar' src='${data[i].imgsrc}' width='32' height='32'>
|
||||||
|
</img>
|
||||||
|
</span>`;
|
||||||
|
}else{
|
||||||
|
details += `<span class='mr-3 avatar avatar-small' style='width:32px; height:32px;'><div align='center' class='standard-image'
|
||||||
|
style='background-color: #fafbfc;'>${data[i].practitioner ? data[i].practitioner.charAt(0) : "U"}</div></span>`;
|
||||||
|
}
|
||||||
|
details += `<div class='d-flex flex-column width-full'>
|
||||||
|
<div>
|
||||||
|
`+time_line_heading+` on
|
||||||
|
<span>
|
||||||
|
${data[i].date_sep}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class='Box p-3 mt-2'>
|
||||||
|
<span class='${data[i].reference_name} document-id'>${label}
|
||||||
|
<div align='center'>
|
||||||
|
<a class='btn octicon octicon-chevron-down btn-default btn-xs btn-more'
|
||||||
|
data-doctype='${data[i].reference_doctype}' data-docname='${data[i].reference_name}'>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<span class='document-html' hidden data-fetched="0">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
details += "</ul>";
|
||||||
|
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("<div class='text-muted' align='center'><br><br>No more records..<br><br></div>");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 += "<div><img class='thumbnail' width=75% src='"+data.image+"'></div>";
|
||||||
|
}
|
||||||
|
details += "<b>" + data.patient_name +"</b><br>" + data.sex;
|
||||||
|
if(data.email) details += "<br>" + data.email;
|
||||||
|
if(data.mobile) details += "<br>" + data.mobile;
|
||||||
|
if(data.occupation) details += "<br><br><b>Occupation :</b> " + data.occupation;
|
||||||
|
if(data.blood_group) details += "<br><b>Blood group : </b> " + data.blood_group;
|
||||||
|
if(data.allergies) details += "<br><br><b>Allergies : </b> "+ data.allergies.replace("\n", "<br>");
|
||||||
|
if(data.medication) details += "<br><b>Medication : </b> "+ data.medication.replace("\n", "<br>");
|
||||||
|
if(data.alcohol_current_use) details += "<br><br><b>Alcohol use : </b> "+ data.alcohol_current_use;
|
||||||
|
if(data.alcohol_past_use) details += "<br><b>Alcohol past use : </b> "+ data.alcohol_past_use;
|
||||||
|
if(data.tobacco_current_use) details += "<br><b>Tobacco use : </b> "+ data.tobacco_current_use;
|
||||||
|
if(data.tobacco_past_use) details += "<br><b>Tobacco past use : </b> "+ data.tobacco_past_use;
|
||||||
|
if(data.medical_history) details += "<br><br><b>Medical history : </b> "+ data.medical_history.replace("\n", "<br>");
|
||||||
|
if(data.surgical_history) details += "<br><b>Surgical history : </b> "+ data.surgical_history.replace("\n", "<br>");
|
||||||
|
if(data.surrounding_factors) details += "<br><br><b>Occupational hazards : </b> "+ data.surrounding_factors.replace("\n", "<br>");
|
||||||
|
if(data.other_risk_factors) details += "<br><b>Other risk factors : </b> " + data.other_risk_factors.replace("\n", "<br>");
|
||||||
|
if(data.patient_details) details += "<br><br><b>More info : </b> " + data.patient_details.replace("\n", "<br>");
|
||||||
|
|
||||||
|
if(details){
|
||||||
|
details = "<div style='padding-left:10px; font-size:13px;' align='center'>" + details + "</div>";
|
||||||
|
}
|
||||||
|
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 = "<div style='padding-top:5px;'><a class='btn btn-default btn-xs btn-show-chart' \
|
||||||
|
data-show-chart-id='bp' data-pts='mmHg' data-title='Blood Pressure'>Blood Pressure</a>\
|
||||||
|
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='pulse_rate' \
|
||||||
|
data-pts='per Minutes' data-title='Respiratory/Pulse Rate'>Respiratory/Pulse Rate</a>\
|
||||||
|
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='temperature' \
|
||||||
|
data-pts='°C or °F' data-title='Temperature'>Temperature</a>\
|
||||||
|
<a class='btn btn-default btn-xs btn-show-chart' data-show-chart-id='bmi' \
|
||||||
|
data-pts='bmi' data-title='BMI'>BMI</a></div>";
|
||||||
|
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<data.length; i++){
|
||||||
|
labels.push(data[i].signs_date+"||"+data[i].signs_time);
|
||||||
|
if(btn_show_id=="bp"){
|
||||||
|
bp_systolic.push(data[i].bp_systolic);
|
||||||
|
bp_diastolic.push(data[i].bp_diastolic);
|
||||||
|
}
|
||||||
|
if(btn_show_id=="temperature"){
|
||||||
|
temperature.push(data[i].temperature);
|
||||||
|
}
|
||||||
|
if(btn_show_id=="pulse_rate"){
|
||||||
|
pulse.push(data[i].pulse);
|
||||||
|
respiratory_rate.push(data[i].respiratory_rate);
|
||||||
|
}
|
||||||
|
if(btn_show_id=="bmi"){
|
||||||
|
bmi.push(data[i].bmi);
|
||||||
|
height.push(data[i].height);
|
||||||
|
weight.push(data[i].weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(btn_show_id=="temperature"){
|
||||||
|
datasets.push({name: "Temperature", values: temperature, chartType:'line'});
|
||||||
|
}
|
||||||
|
if(btn_show_id=="bmi"){
|
||||||
|
datasets.push({name: "BMI", values: bmi, chartType:'line'});
|
||||||
|
datasets.push({name: "Height", values: height, chartType:'line'});
|
||||||
|
datasets.push({name: "Weight", values: weight, chartType:'line'});
|
||||||
|
}
|
||||||
|
if(btn_show_id=="bp"){
|
||||||
|
datasets.push({name: "BP Systolic", values: bp_systolic, chartType:'line'});
|
||||||
|
datasets.push({name: "BP Diastolic", values: bp_diastolic, chartType:'line'});
|
||||||
|
}
|
||||||
|
if(btn_show_id=="pulse_rate"){
|
||||||
|
datasets.push({name: "Heart Rate / Pulse", values: pulse, chartType:'line'});
|
||||||
|
datasets.push({name: "Respiratory Rate", values: respiratory_rate, chartType:'line'});
|
||||||
|
}
|
||||||
|
new Chart( ".patient_vital_charts", {
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: datasets
|
||||||
|
},
|
||||||
|
|
||||||
|
title: title,
|
||||||
|
type: 'axis-mixed', // 'axis-mixed', 'bar', 'line', 'pie', 'percentage'
|
||||||
|
height: 150,
|
||||||
|
colors: ['purple', '#ffa3ef', 'light-blue'],
|
||||||
|
|
||||||
|
tooltipOptions: {
|
||||||
|
formatTooltipX: d => (d + '').toUpperCase(),
|
||||||
|
formatTooltipY: d => d + ' ' + pts,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
me.page.main.find(".patient_vital_charts").html("");
|
||||||
|
me.page.main.find(".show_chart_btns").html("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
{
|
{
|
||||||
"content": null,
|
"content": null,
|
||||||
"creation": "2016-06-09 11:33:14.025787",
|
"creation": "2018-08-08 17:09:13.816199",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Page",
|
"doctype": "Page",
|
||||||
"icon": "icon-play",
|
"icon": "",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"modified": "2018-08-06 11:40:39.705660",
|
"modified": "2018-08-08 17:09:55.969424",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "medical_record",
|
"name": "patient_history",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"page_name": "medical_record",
|
"page_name": "patient_history",
|
||||||
"restrict_to_domain": "Healthcare",
|
"restrict_to_domain": "Healthcare",
|
||||||
"roles": [
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Healthcare Administrator"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"role": "Physician"
|
"role": "Physician"
|
||||||
}
|
}
|
||||||
@@ -21,5 +24,5 @@
|
|||||||
"standard": "Yes",
|
"standard": "Yes",
|
||||||
"style": null,
|
"style": null,
|
||||||
"system_page": 0,
|
"system_page": 0,
|
||||||
"title": "Medical Record"
|
"title": "Patient History"
|
||||||
}
|
}
|
||||||
39
erpnext/healthcare/page/patient_history/patient_history.py
Normal file
39
erpnext/healthcare/page/patient_history/patient_history.py
Normal file
@@ -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
|
||||||
@@ -429,3 +429,116 @@ def get_children(doctype, parent, company, is_root=False):
|
|||||||
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
|
occupancy_msg = str(occupied) + " Occupied out of " + str(occupancy_total)
|
||||||
each["occupied_out_of_vacant"] = occupancy_msg
|
each["occupied_out_of_vacant"] = occupancy_msg
|
||||||
return hc_service_units
|
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 = "<div class='col-md-12 col-sm-12 text-muted'>"
|
||||||
|
for doc in docs:
|
||||||
|
docs_html += render_doc_as_html(doc['doctype'], doc['docname'])['html'] + "<br/>"
|
||||||
|
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 = "<div class='col-md-12 col-sm-12'>"
|
||||||
|
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 + "</div>"
|
||||||
|
elif has_data and not col_on and sec_on:
|
||||||
|
doc_html += "<div class='col-md-12 col-sm-12'\
|
||||||
|
><div class='col-md-12 col-sm-12'>" \
|
||||||
|
+ section_html + html +"</div></div>"
|
||||||
|
while col_on:
|
||||||
|
doc_html += "</div>"
|
||||||
|
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 += "<div class='col-md-12 col-sm-12'\
|
||||||
|
><div class='col-md-6 col\
|
||||||
|
-sm-6'><b>" + section_label + "</b>" + html + "</div><div \
|
||||||
|
class='col-md-6 col-sm-6'>"
|
||||||
|
elif has_data:
|
||||||
|
doc_html += "<div class='col-md-12 col-sm-12'><div class='col-m\
|
||||||
|
d-6 col-sm-6'>" + html + "</div><div class='col-md-6 col-sm-6'>"
|
||||||
|
elif sec_on and not col_on:
|
||||||
|
section_html += "<div class='col-md-6 col-sm-6'>"
|
||||||
|
html = ""
|
||||||
|
col_on += 1
|
||||||
|
if df.label:
|
||||||
|
html += '<br>' + 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 += '<tr>'
|
||||||
|
for cdf in child_meta.fields:
|
||||||
|
if cdf.in_list_view:
|
||||||
|
if create_head:
|
||||||
|
table_head += '<th>' + cdf.label + '</th>'
|
||||||
|
if item.get(cdf.fieldname):
|
||||||
|
table_row += '<td>' + str(item.get(cdf.fieldname)) \
|
||||||
|
+ '</td>'
|
||||||
|
else:
|
||||||
|
table_row += '<td></td>'
|
||||||
|
create_head = False
|
||||||
|
table_row += '</tr>'
|
||||||
|
if sec_on:
|
||||||
|
section_html += '<table class="table table-condensed \
|
||||||
|
bordered">' + table_head + table_row + '</table>'
|
||||||
|
else:
|
||||||
|
html += '<table class="table table-condensed table-bordered">' \
|
||||||
|
+ table_head + table_row + '</table>'
|
||||||
|
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 += "<br>{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 + "</div></div>"
|
||||||
|
elif sec_on and not col_on and has_data:
|
||||||
|
doc_html += "<div class='col-md-12 col-sm-12'\
|
||||||
|
><div class='col-md-12 col-sm-12'>" \
|
||||||
|
+ section_html + html +"</div></div>"
|
||||||
|
if doc_html:
|
||||||
|
doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + "</div>"
|
||||||
|
|
||||||
|
return {'html': doc_html}
|
||||||
|
|||||||
@@ -605,6 +605,7 @@ erpnext.patches.v11_1.delete_scheduling_tool
|
|||||||
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
|
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
|
||||||
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
||||||
erpnext.patches.v12_0.make_item_manufacturer
|
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.move_customer_lead_to_dynamic_column
|
||||||
erpnext.patches.v11_1.set_default_action_for_quality_inspection
|
erpnext.patches.v11_1.set_default_action_for_quality_inspection
|
||||||
erpnext.patches.v11_1.delete_bom_browser
|
erpnext.patches.v11_1.delete_bom_browser
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Copyright (c) 2019
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.delete_doc("Page", "medical_record")
|
||||||
@@ -450,7 +450,7 @@ def make_stock_entry(source_name, target_doc=None):
|
|||||||
"field_map": {
|
"field_map": {
|
||||||
"name": "material_request_item",
|
"name": "material_request_item",
|
||||||
"parent": "material_request",
|
"parent": "material_request",
|
||||||
"uom": "stock_uom",
|
"uom": "stock_uom"
|
||||||
},
|
},
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
|
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
|
||||||
|
|||||||
@@ -61,7 +61,8 @@
|
|||||||
"ste_detail",
|
"ste_detail",
|
||||||
"column_break_51",
|
"column_break_51",
|
||||||
"transferred_qty",
|
"transferred_qty",
|
||||||
"reference_purchase_receipt"
|
"reference_purchase_receipt",
|
||||||
|
"project"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -472,11 +473,18 @@
|
|||||||
"label": "Reference Purchase Receipt",
|
"label": "Reference Purchase Receipt",
|
||||||
"options": "Purchase Receipt",
|
"options": "Purchase Receipt",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "project",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Project",
|
||||||
|
"options": "Project",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-06-14 11:58:41.958144",
|
"modified": "2019-07-12 11:34:53.190749",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry Detail",
|
"name": "Stock Entry Detail",
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ frappe.ui.form.on("Issue", {
|
|||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
frm.email_field = "raised_by";
|
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) {
|
if (frm.doc.service_level_agreement) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters",
|
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) {
|
timeline_refresh: function(frm) {
|
||||||
// create button for "Help Article"
|
// create button for "Help Article"
|
||||||
if(frappe.model.can_create('Help Article')) {
|
if(frappe.model.can_create('Help Article')) {
|
||||||
|
|||||||
@@ -22,10 +22,12 @@
|
|||||||
"service_level_agreement",
|
"service_level_agreement",
|
||||||
"response_by",
|
"response_by",
|
||||||
"response_by_variance",
|
"response_by_variance",
|
||||||
|
"reset_service_level_agreement",
|
||||||
"cb",
|
"cb",
|
||||||
"agreement_fulfilled",
|
"agreement_fulfilled",
|
||||||
"resolution_by",
|
"resolution_by",
|
||||||
"resolution_by_variance",
|
"resolution_by_variance",
|
||||||
|
"service_level_agreement_creation",
|
||||||
"response",
|
"response",
|
||||||
"mins_to_first_response",
|
"mins_to_first_response",
|
||||||
"first_responded_on",
|
"first_responded_on",
|
||||||
@@ -68,9 +70,9 @@
|
|||||||
"fieldname": "subject",
|
"fieldname": "subject",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
"label": "Subject",
|
"label": "Subject",
|
||||||
"reqd": 1,
|
"reqd": 1
|
||||||
"in_standard_filter": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "customer",
|
"fieldname": "customer",
|
||||||
@@ -336,11 +338,24 @@
|
|||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Resolution By Variance",
|
"label": "Resolution By Variance",
|
||||||
"read_only": 1
|
"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",
|
"icon": "fa fa-ticket",
|
||||||
"idx": 7,
|
"idx": 7,
|
||||||
"modified": "2019-06-30 13:19:38.215525",
|
"modified": "2019-07-11 23:57:22.015881",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Issue",
|
"name": "Issue",
|
||||||
@@ -365,4 +380,4 @@
|
|||||||
"timeline_field": "customer",
|
"timeline_field": "customer",
|
||||||
"title_field": "subject",
|
"title_field": "subject",
|
||||||
"track_seen": 1
|
"track_seen": 1
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,7 @@ class Issue(Document):
|
|||||||
|
|
||||||
# Reset SLA
|
# Reset SLA
|
||||||
if replicated_issue.service_level_agreement:
|
if replicated_issue.service_level_agreement:
|
||||||
|
replicated_issue.service_level_agreement_creation = now_datetime()
|
||||||
replicated_issue.service_level_agreement = None
|
replicated_issue.service_level_agreement = None
|
||||||
replicated_issue.agreement_fulfilled = "Ongoing"
|
replicated_issue.agreement_fulfilled = "Ongoing"
|
||||||
replicated_issue.response_by = None
|
replicated_issue.response_by = None
|
||||||
@@ -173,8 +174,9 @@ class Issue(Document):
|
|||||||
|
|
||||||
if not self.creation:
|
if not self.creation:
|
||||||
self.creation = now_datetime()
|
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.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)
|
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)
|
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))
|
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):
|
def get_expected_time_for(parameter, service_level, start_date_time):
|
||||||
current_date_time = start_date_time
|
current_date_time = start_date_time
|
||||||
expected_time = current_date_time
|
expected_time = current_date_time
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ def make_issue(creation=None, customer=None, index=0):
|
|||||||
"customer": customer,
|
"customer": customer,
|
||||||
"raised_by": "test@example.com",
|
"raised_by": "test@example.com",
|
||||||
"description": "Service Level Agreement Issue",
|
"description": "Service Level Agreement Issue",
|
||||||
"creation": creation
|
"creation": creation,
|
||||||
|
"service_level_agreement_creation": creation
|
||||||
}).insert(ignore_permissions=True)
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
return issue
|
return issue
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ def create_service_level_agreement(default_service_level_agreement, service_leve
|
|||||||
|
|
||||||
service_level_agreement = frappe.get_doc({
|
service_level_agreement = frappe.get_doc({
|
||||||
"doctype": "Service Level Agreement",
|
"doctype": "Service Level Agreement",
|
||||||
|
"enable": 1,
|
||||||
"default_service_level_agreement": default_service_level_agreement,
|
"default_service_level_agreement": default_service_level_agreement,
|
||||||
"service_level": service_level,
|
"service_level": service_level,
|
||||||
"holiday_list": holiday_list,
|
"holiday_list": holiday_list,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"sb_00",
|
"sb_00",
|
||||||
"track_service_level_agreement",
|
"track_service_level_agreement",
|
||||||
|
"allow_resetting_service_level_agreement",
|
||||||
"issues_sb",
|
"issues_sb",
|
||||||
"close_issue_after_days",
|
"close_issue_after_days",
|
||||||
"portal_sb",
|
"portal_sb",
|
||||||
@@ -118,10 +119,16 @@
|
|||||||
"fieldname": "track_service_level_agreement",
|
"fieldname": "track_service_level_agreement",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Track Service Level Agreement"
|
"label": "Track Service Level Agreement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "allow_resetting_service_level_agreement",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Allow Resetting Service Level Agreement"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"modified": "2019-07-09 17:11:38.216732",
|
"modified": "2019-07-10 22:52:39.663873",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Support Settings",
|
"name": "Support Settings",
|
||||||
|
|||||||
Reference in New Issue
Block a user