Merge branch 'staging-fixes' into staging

This commit is contained in:
Ameya Shenoy 2018-10-11 06:58:13 +00:00
commit dc279ded15
No known key found for this signature in database
GPG Key ID: AC016A555657D0A3
34 changed files with 9067 additions and 8801 deletions

View File

@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '10.1.57'
__version__ = '10.1.58'
def get_default_company(user=None):
'''Get default company for user'''

View File

@ -22,14 +22,14 @@ class DuplicatePartyAccountError(frappe.ValidationError): pass
@frappe.whitelist()
def get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True, party_address=None):
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True, party_address=None, shipping_address=None):
if not party:
return {}
if not frappe.db.exists(party_type, party):
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
return _get_party_details(party, account, party_type,
company, posting_date, bill_date, price_list, currency, doctype, ignore_permissions, fetch_payment_terms_template, party_address)
company, posting_date, bill_date, price_list, currency, doctype, ignore_permissions, fetch_payment_terms_template, party_address, shipping_address)
def _get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False,
@ -96,7 +96,8 @@ def set_address_details(out, party, party_type, doctype=None, company=None, part
elif doctype and doctype == "Purchase Invoice":
out.update(get_company_address(company))
if out.company_address:
out["shipping_address"] = out["company_address"]
out["shipping_address"] = shipping_address or out["company_address"]
out.shipping_address_display = get_address_display(out["shipping_address"])
out.update(get_fetch_values(doctype, 'shipping_address', out.shipping_address))
get_regional_address_details(out, doctype, company)

View File

@ -161,21 +161,21 @@
</td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %}</td>
{% if(!filters.show_pdc_in_print) { %}
<td style="text-align: right">
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["Credit Note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %}</td>
{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %}</td>
{% } %}
<td style="text-align: right">
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
{% if(filters.show_pdc_in_print) { %}
{% if(report.report_name === "Accounts Receivable") { %}
<td style="text-align: right">
{%= data[i][__("Customer LPO")] %}</td>
{%= data[i]["po_no"] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
<td style="text-align: right">{%= data[i][__("PDC/LC Ref")] %}</td>

View File

@ -104,9 +104,13 @@ class ReceivablePayableReport(object):
]
if args.get('party_type') == 'Customer':
columns += [_("Customer LPO") + ":Data:100"]
columns.append({
"label": _("Customer LPO"),
"fieldtype": "Data",
"fieldname": "po_no",
"width": 100,
})
columns += [_("Delivery Note") + ":Data:100"]
if args.get("party_type") == "Customer":
columns += [
_("Territory") + ":Link/Territory:80",

File diff suppressed because it is too large Load Diff

View File

@ -293,6 +293,16 @@ def get_data():
"label": _("Patient"),
"hidden": 1
},
{
"module_name": "Healthcare Practitioner",
"color": "#2ecc71",
"icon": "fa fa-user-md",
"doctype": "Healthcare Practitioner",
"type": "link",
"link": "List/Healthcare Practitioner",
"label": _("Healthcare Practitioner"),
"hidden": 1
},
{
"module_name": "Patient Appointment",
"color": "#934F92",
@ -322,6 +332,36 @@ def get_data():
"link": "List/Lab Test",
"label": _("Lab Test"),
"hidden": 1
},
{
"module_name": "Vital Signs",
"color": "#2ecc71",
"icon": "fa fa-thermometer-empty",
"doctype": "Vital Signs",
"type": "list",
"link": "List/Vital Signs",
"label": _("Vital Signs"),
"hidden": 1
},
{
"module_name": "Clinical Procedure",
"color": "#FF888B",
"icon": "fa fa-medkit",
"doctype": "Clinical Procedure",
"type": "list",
"link": "List/Clinical Procedure",
"label": _("Clinical Procedure"),
"hidden": 1
},
{
"module_name": "Inpatient Record",
"color": "#7578f6",
"icon": "fa fa-list-alt",
"doctype": "Inpatient Record",
"type": "list",
"link": "List/Inpatient Record",
"label": _("Inpatient Record"),
"hidden": 1
},
{
"module_name": "Hub",

View File

@ -708,22 +708,24 @@ class AccountsController(TransactionBase):
def group_similar_items(self):
group_item_qty = {}
group_item_amount = {}
# to update serial number in print
count = 0
for item in self.items:
group_item_qty[item.item_code] = group_item_qty.get(item.item_code, 0) + item.qty
group_item_amount[item.item_code] = group_item_amount.get(item.item_code, 0) + item.amount
duplicate_list = []
for item in self.items:
if item.item_code in group_item_qty:
count += 1
item.qty = group_item_qty[item.item_code]
item.amount = group_item_amount[item.item_code]
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
item.idx = count
del group_item_qty[item.item_code]
else:
duplicate_list.append(item)
for item in duplicate_list:
self.remove(item)

View File

@ -69,7 +69,7 @@ class BuyingController(StockController):
# set contact and address details for supplier, if they are not mentioned
if getattr(self, "supplier", None):
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions,
doctype=self.doctype, company=self.company, party_address=self.supplier_address))
doctype=self.doctype, company=self.company, party_address=self.supplier_address, shipping_address=self.shipping_address))
self.set_missing_item_details(for_validate)

View File

@ -63,7 +63,7 @@ class SellingController(StockController):
ignore_permissions=self.flags.ignore_permissions,
doctype=self.doctype, company=self.company,
fetch_payment_terms_template=fetch_payment_terms_template,
party_address=self.customer_address, shipping_address=self.shipping_address)
party_address=self.customer_address, shipping_address=self.shipping_address_name)
if not self.meta.get_field("sales_team"):
party_details.pop("sales_team")
self.update_if_missing(party_details)

View File

@ -5,6 +5,9 @@ data = {
'Patient Encounter',
'Lab Test',
'Healthcare',
'Vital Signs',
'Clinical Procedure',
'Inpatient Record',
'Accounts',
'Buying',
'Stock',

View File

@ -4,7 +4,29 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import get_link_to_form
from frappe.model.document import Document
class StudentLeaveApplication(Document):
pass
def validate(self):
self.validate_duplicate()
def validate_duplicate(self):
data = frappe.db.sql(""" select name from `tabStudent Leave Application`
where
((%(from_date)s > from_date and %(from_date)s < to_date) or
(%(to_date)s > from_date and %(to_date)s < to_date) or
(%(from_date)s <= from_date and %(to_date)s >= to_date)) and
name != %(name)s and student = %(student)s and docstatus < 2
""", {
'from_date': self.from_date,
'to_date': self.to_date,
'student': self.student,
'name': self.name
}, as_dict=1)
if data:
link = get_link_to_form("Student Leave Application", data[0].name)
frappe.throw(_("Leave application {0} already exists against the student {1}")
.format(link, self.student))

File diff suppressed because it is too large Load Diff

View File

@ -342,6 +342,8 @@ def manage_fee_validity(appointment_name, method, ref_invoice=None):
def appointments_valid_in_fee_validity(appointment, invoiced):
valid_days = frappe.db.get_value("Healthcare Settings", None, "valid_days")
max_visit = frappe.db.get_value("Healthcare Settings", None, "max_visit")
if int(max_visit) < 1:
max_visit = 1
valid_days_date = add_days(getdate(appointment.appointment_date), int(valid_days))
return frappe.get_list("Patient Appointment",{'patient': appointment.patient, 'invoiced': invoiced,
'appointment_date':("<=", valid_days_date), 'appointment_date':(">=", getdate(appointment.appointment_date)),

View File

@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)"
source_link = "https://github.com/frappe/erpnext"
develop_version = '11.x.x-develop'
staging_version = '11.0.3-beta.9'
staging_version = '11.0.3-beta.10'
error_report_email = "support@erpnext.com"

View File

@ -2,4 +2,13 @@
// For license information, please see license.txt
frappe.ui.form.on('Driver', {
setup: function(frm) {
frm.set_query('transporter', function(){
return {
filters: {
'is_transporter': 1
}
};
});
}
});

File diff suppressed because it is too large Load Diff

View File

@ -498,7 +498,6 @@ execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=
erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group
erpnext.patches.v10_0.add_default_cash_flow_mappers
erpnext.patches.v11_0.make_quality_inspection_template
erpnext.patches.v10_0.remove_and_copy_fields_in_physician
erpnext.patches.v10_0.update_status_for_multiple_source_in_po
erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
erpnext.patches.v10_0.update_territory_and_customer_group
@ -569,3 +568,6 @@ erpnext.patches.v11_0.remove_land_unit_icon
erpnext.patches.v11_0.add_default_dispatch_notification_template
erpnext.patches.v11_0.add_market_segments
erpnext.patches.v11_0.add_sales_stages
erpnext.patches.v11_0.ewaybill_fields_gst_india
erpnext.patches.v11_0.drop_column_max_days_allowed
erpnext.patches.v11_0.change_healthcare_desktop_icons

View File

@ -1,13 +0,0 @@
import frappe
def execute():
if frappe.db.exists("DocType", "Physician"):
frappe.reload_doc("healthcare", "doctype", "physician")
frappe.reload_doc("healthcare", "doctype", "physician_service_unit_schedule")
if frappe.db.has_column('Physician', 'physician_schedules'):
for doc in frappe.get_all('Physician'):
_doc = frappe.get_doc('Physician', doc.name)
if _doc.physician_schedule:
_doc.append('physician_schedules', {'schedule': _doc.physician_schedule})
_doc.save()

View File

@ -0,0 +1,68 @@
import frappe
from frappe import _
def execute():
change_healthcare_desktop_icons()
def change_healthcare_desktop_icons():
change_icons_map = [
{
"module_name": "Patient",
"color": "#6BE273",
"icon": "fa fa-user",
"doctype": "Patient",
"type": "link",
"link": "List/Patient",
"label": _("Patient")
},
{
"module_name": "Patient Encounter",
"color": "#2ecc71",
"icon": "fa fa-stethoscope",
"doctype": "Patient Encounter",
"type": "link",
"link": "List/Patient Encounter",
"label": _("Patient Encounter"),
},
{
"module_name": "Healthcare Practitioner",
"color": "#2ecc71",
"icon": "fa fa-user-md",
"doctype": "Healthcare Practitioner",
"type": "link",
"link": "List/Healthcare Practitioner",
"label": _("Healthcare Practitioner")
},
{
"module_name": "Patient Appointment",
"color": "#934F92",
"icon": "fa fa-calendar-plus-o",
"doctype": "Patient Appointment",
"type": "link",
"link": "List/Patient Appointment",
"label": _("Patient Appointment")
},
{
"module_name": "Lab Test",
"color": "#7578f6",
"icon": "octicon octicon-beaker",
"doctype": "Lab Test",
"type": "link",
"link": "List/Lab Test",
"label": _("Lab Test")
}
]
for spec in change_icons_map:
frappe.db.sql("""
update `tabDesktop Icon`
set module_name = '{0}', color = '{1}', icon = '{2}', _doctype = '{3}', type = '{4}',
link = '{5}', label = '{6}'
where _doctype = '{7}'
""".format(spec['module_name'], spec['color'], spec['icon'], spec['doctype'], spec['type'], spec['link'], spec['label'], spec['doctype']))
frappe.db.sql("""
update `tabDesktop Icon`
set color = '#FF888B', icon = 'fa fa-heartbeat'
where module_name = 'Healthcare' and type = 'module'
""")

View File

@ -0,0 +1,6 @@
import frappe
def execute():
if frappe.db.exists("DocType", "Leave Type"):
if 'max_days_allowed' in frappe.db.get_table_columns("Leave Type"):
frappe.db.sql("alter table `tabLeave Type` drop column max_days_allowed")

View File

@ -0,0 +1,9 @@
import frappe
from erpnext.regional.india.setup import make_custom_fields
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
make_custom_fields()

View File

@ -54,3 +54,13 @@ def execute():
update `tabPractitioner Service Unit Schedule` set parentfield = 'practitioner_schedules'
where parentfield = 'physician_schedules' and parenttype = 'Healthcare Practitioner'
""")
if frappe.db.exists("DocType", "Healthcare Practitioner"):
frappe.reload_doc("healthcare", "doctype", "healthcare_practitioner")
frappe.reload_doc("healthcare", "doctype", "practitioner_service_unit_schedule")
if frappe.db.has_column('Healthcare Practitioner', 'physician_schedule'):
for doc in frappe.get_all('Healthcare Practitioner'):
_doc = frappe.get_doc('Healthcare Practitioner', doc.name)
if _doc.physician_schedule:
_doc.append('practitioner_schedules', {'schedule': _doc.physician_schedule})
_doc.save()

View File

@ -187,6 +187,7 @@ class Project(Document):
frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
def update_percent_complete(self):
if not self.tasks: return
total = frappe.db.sql("""select count(name) from tabTask where project=%s""", self.name)[0][0]
if not total and self.percent_complete:
self.percent_complete = 0

View File

@ -164,6 +164,43 @@ def make_custom_fields(update=True):
fieldtype='Check', insert_after='disabled', print_hide=1)
]
ewaybill_fields = [
{
'fieldname': 'distance',
'label': 'Distance (in km)',
'fieldtype': 'Float',
'insert_after': 'vehicle_no',
'print_hide': 1
},
{
'fieldname': 'gst_transporter_id',
'label': 'GST Transporter ID',
'fieldtype': 'Data',
'insert_after': 'transporter_name',
'fetch_from': 'transporter.gst_transporter_id',
'print_hide': 1
},
{
'fieldname': 'mode_of_transport',
'label': 'Mode of Transport',
'fieldtype': 'Select',
'options': '\nRoad\nAir\nRail\nShip',
'default': 'Road',
'insert_after': 'lr_date',
'print_hide': 1
},
{
'fieldname': 'gst_vehicle_type',
'label': 'GST Vehicle Type',
'fieldtype': 'Select',
'options': '\nRegular\nOver Dimensional Cargo (ODC)',
'default': 'Regular',
'depends_on': 'eval:(doc.mode_of_transport === "Road")',
'insert_after': 'mode_of_transport',
'print_hide': 1
}
]
custom_fields = {
'Address': [
dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data',
@ -175,7 +212,7 @@ def make_custom_fields(update=True):
],
'Purchase Invoice': invoice_gst_fields + purchase_invoice_gst_fields,
'Sales Invoice': invoice_gst_fields + sales_invoice_gst_fields,
'Delivery Note': sales_invoice_gst_fields,
'Delivery Note': sales_invoice_gst_fields + ewaybill_fields,
'Sales Taxes and Charges Template': inter_state_gst_field,
'Purchase Taxes and Charges Template': inter_state_gst_field,
'Item': [
@ -240,6 +277,15 @@ def make_custom_fields(update=True):
fieldtype='Currency', insert_after='monthly_house_rent', read_only=1),
dict(fieldname='total_eligible_hra_exemption', label='Total Eligible HRA Exemption',
fieldtype='Currency', insert_after='monthly_hra_exemption', read_only=1)
],
'Supplier': [
{
'fieldname': 'gst_transporter_id',
'label': 'GST Transporter ID',
'fieldtype': 'Data',
'insert_after': 'supplier_type',
'depends_on': 'eval:doc.is_transporter'
}
]
}

View File

@ -82,7 +82,7 @@ def get_place_of_supply(out, doctype):
if address_name:
address = frappe.db.get_value("Address", address_name, ["gst_state", "gst_state_number"], as_dict=1)
if address.gst_state and address.gst_state_number:
if address and address.gst_state and address.gst_state_number:
return cstr(address.gst_state_number) + "-" + cstr(address.gst_state)
def get_regional_address_details(out, doctype, company):

View File

@ -21,7 +21,7 @@ def get_data(filters):
data = frappe.db.sql("""
SELECT
dn.name as dn_id, dn.posting_date, dn.company, dn.company_gstin, dn.customer, dn.customer_gstin, dni.item_code, dni.item_name, dni.description, dni.gst_hsn_code, dni.uom, dni.qty, dni.amount, dn.transport_mode, dn.distance, dn.transporter_name, dn.transporter, dn.lr_no, dn.lr_date, dn.vehicle_no, dn.vehicle_type, dn.company_address, dn.shipping_address_name
dn.name as dn_id, dn.posting_date, dn.company, dn.company_gstin, dn.customer, dn.customer_gstin, dni.item_code, dni.item_name, dni.description, dni.gst_hsn_code, dni.uom, dni.qty, dni.amount, dn.mode_of_transport, dn.distance, dn.transporter_name, dn.gst_transporter_id, dn.lr_no, dn.lr_date, dn.vehicle_no, dn.gst_vehicle_type, dn.company_address, dn.shipping_address_name
FROM
`tabDelivery Note` AS dn join `tabDelivery Note Item` AS dni on (dni.parent = dn.name)
WHERE
@ -52,6 +52,9 @@ def get_data(filters):
row.posting_date = '/'.join(str(row.posting_date).replace("-", "/").split('/')[::-1])
row.lr_date = '/'.join(str(row.lr_date).replace("-", "/").split('/')[::-1])
if row.gst_vehicle_type == 'Over Dimensional Cargo (ODC)':
row.gst_vehicle_type = 'ODC'
row.item_name = re.sub(special_characters, " ", row.item_name)
row.description = row.item_name
@ -333,8 +336,8 @@ def get_columns():
"width": 100
},
{
"fieldname": "transport_mode",
"label": _("Transport Mode"),
"fieldname": "mode_of_transport",
"label": _("Mode of Transport"),
"fieldtype": "Data",
"width": 100
},
@ -351,20 +354,20 @@ def get_columns():
"width": 120
},
{
"fieldname": "transporter_id",
"fieldname": "gst_transporter_id",
"label": _("Transporter ID"),
"fieldtype": "Data",
"width": 100
},
{
"fieldname": "lr_no",
"label": _("Transporter Doc No"),
"label": _("Transport Receipt No"),
"fieldtype": "Data",
"width": 120
},
{
"fieldname": "lr_date",
"label": _("Transporter Date"),
"label": _("Transport Receipt Date"),
"fieldtype": "Data",
"width": 120
},
@ -375,7 +378,7 @@ def get_columns():
"width": 100
},
{
"fieldname": "vehicle_type",
"fieldname": "gst_vehicle_type",
"label": _("Vehicle Type"),
"fieldtype": "Data",
"width": 100

View File

@ -40,7 +40,6 @@ def execute(filters=None):
def get_columns(customer_naming_type):
columns = [
_("Name") + ":Link/Customer:120",
_("Customer") + ":Link/Customer:120",
_("Credit Limit") + ":Currency:120",
_("Outstanding Amt") + ":Currency:100",

View File

@ -30,7 +30,7 @@ def make_tax_account_and_template(company, account_name, tax_rate, template_name
if accounts:
make_sales_and_purchase_tax_templates(accounts, template_name)
except frappe.NameError:
frappe.message_log.pop()
if frappe.message_log: frappe.message_log.pop()
except RootNotEditable:
pass

View File

@ -1,5 +1,6 @@
from __future__ import unicode_literals
import frappe
from frappe import _
install_docs = [
{"doctype":"Role", "role_name":"Stock Manager", "name":"Stock Manager"},
@ -33,7 +34,11 @@ def get_warehouse_account(warehouse, warehouse_account=None):
account = warehouse.account
if not account and warehouse.parent_warehouse:
if warehouse_account:
account = warehouse_account.get(warehouse.parent_warehouse).account
if warehouse_account.get(warehouse.parent_warehouse):
account = warehouse_account.get(warehouse.parent_warehouse).account
else:
from frappe.utils.nestedset import rebuild_tree
rebuild_tree("Warehouse", "parent_warehouse")
else:
account = frappe.db.sql("""
select
@ -48,6 +53,9 @@ def get_warehouse_account(warehouse, warehouse_account=None):
if not account and warehouse.company:
account = get_company_default_inventory_account(warehouse.company)
if not account:
frappe.throw(_("Please set Account in Warehouse {0} or Default Inventory Account in Company {1}")
.format(warehouse, warehouse.company))
return account
def get_company_default_inventory_account(company):

View File

@ -32,9 +32,19 @@ frappe.ui.form.on("Delivery Note", {
}
})
frm.set_query('transporter_name', function(doc) {
frm.set_query('transporter', function() {
return {
filters: { 'supplier_group': "transporter" }
filters: {
'is_transporter': 1
}
}
});
frm.set_query('driver', function(doc) {
return {
filters: {
'transporter': doc.transporter
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -24,11 +24,9 @@ class DeliveryTrip(Document):
delivery_notes = list(set([stop.delivery_note for stop in self.delivery_stops if stop.delivery_note]))
update_fields = {
"transporter": self.driver,
"transporter_name": self.driver_name,
"transport_mode": "Road",
"driver": self.driver,
"driver_name": self.driver_name,
"vehicle_no": self.vehicle,
"vehicle_type": "Regular",
"lr_no": self.name,
"lr_date": self.date
}
@ -40,6 +38,7 @@ class DeliveryTrip(Document):
value = None if delete else value
setattr(note_doc, field, value)
note_doc.flags.ignore_validate_update_after_submit = True
note_doc.save()
delivery_notes = [get_link_to_form("Delivery Note", note) for note in delivery_notes]