Merge branch 'develop' of https://github.com/frappe/erpnext into dashboards

This commit is contained in:
deepeshgarg007 2019-06-01 22:57:51 +05:30
commit ce15591872
97 changed files with 446917 additions and 417731 deletions

View File

@ -321,7 +321,7 @@ def set_discount_amount(rate, item_details):
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
from erpnext.accounts.doctype.pricing_rule.utils import get_apply_on_and_items
for d in pricing_rules.split(','):
if not d: continue
if not d or not frappe.db.exists("Pricing Rule", d): continue
pricing_rule = frappe.get_doc('Pricing Rule', d)
if pricing_rule.price_or_product_discount == 'Price':

View File

@ -480,10 +480,10 @@ def apply_pricing_rule(doc, pr_doc, item_row, value, do_not_validate=False):
rule_applied = {}
for item in doc.get("items"):
if not item.pricing_rules:
item.pricing_rules = item_row.pricing_rules
if item.get(apply_on) in items:
if not item.pricing_rules:
item.pricing_rules = item_row.pricing_rules
for field in ['discount_percentage', 'discount_amount', 'rate']:
if not pr_doc.get(field): continue

View File

@ -68,13 +68,13 @@ class ReceivablePayableReport(object):
if self.filters.based_on_payment_terms:
columns.append({
"label": "Payment Term",
"label": _("Payment Term"),
"fieldname": "payment_term",
"fieldtype": "Data",
"width": 120
})
columns.append({
"label": "Invoice Grand Total",
"label": _("Invoice Grand Total"),
"fieldname": "invoice_grand_total",
"fieldtype": "Currency",
"options": "currency",
@ -83,7 +83,7 @@ class ReceivablePayableReport(object):
for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
columns.append({
"label": label,
"label": _(label),
"fieldname": frappe.scrub(label),
"fieldtype": "Currency",
"options": "currency",

View File

@ -33,6 +33,14 @@ frappe.ui.form.on("Purchase Order", {
}
}
});
frm.set_query("expense_account", "items", function() {
return {
query: "erpnext.controllers.queries.get_expense_account",
filters: {'company': frm.doc.company}
}
});
},
refresh: function(frm) {

View File

@ -60,6 +60,13 @@ def get_data():
"description": _("Import Data from CSV / Excel files."),
"onboard": 1,
},
{
"type": "doctype",
"name": "Chart of Accounts Importer",
"labe": _("Chart Of Accounts Importer"),
"description": _("Import Chart Of Accounts from CSV / Excel files"),
"onboard": 1
},
{
"type": "doctype",
"name": "Letter Head",

View File

@ -279,14 +279,14 @@ def copy_attributes_to_variant(item, variant):
variant.set(field.fieldname, item.get(field.fieldname))
variant.variant_of = item.name
if 'description' in allow_fields:
variant.has_variants = 0
if 'description' not in allow_fields:
if not variant.description:
variant.description = ""
if item.variant_based_on=='Item Attribute':
if variant.attributes:
attributes_description = ""
attributes_description = item.description + " "
for d in variant.attributes:
attributes_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"

View File

@ -316,19 +316,27 @@ class StatusUpdater(Document):
.format(frappe.db.escape(frappe.session.user))
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
ref_fieldname = ref_dt.lower().replace(" ", "_")
zero_amount_refdoc = []
all_zero_amount_refdoc = frappe.db.sql_list("""select name from `tab%s`
where docstatus=1 and base_net_total = 0""" % ref_dt)
ref_fieldname = frappe.scrub(ref_dt)
for item in self.get("items"):
if item.get(ref_fieldname) \
and item.get(ref_fieldname) in all_zero_amount_refdoc \
and item.get(ref_fieldname) not in zero_amount_refdoc:
zero_amount_refdoc.append(item.get(ref_fieldname))
ref_docs = [item.get(ref_fieldname) for item in (self.get('items') or []) if item.get(ref_fieldname)]
if not ref_docs:
return
if zero_amount_refdoc:
self.update_billing_status(zero_amount_refdoc, ref_dt, ref_fieldname)
zero_amount_refdocs = frappe.db.sql_list("""
SELECT
name
from
`tab{ref_dt}`
where
docstatus = 1
and base_net_total = 0
and name in %(ref_docs)s
""".format(ref_dt=ref_dt), {
'ref_docs': ref_docs
})
if zero_amount_refdocs:
self.update_billing_status(zero_amount_refdocs, ref_dt, ref_fieldname)
def update_billing_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
for ref_dn in zero_amount_refdoc:

View File

@ -11,4 +11,6 @@ from frappe.model.document import Document
class Vehicle(Document):
def validate(self):
if getdate(self.start_date) > getdate(self.end_date):
frappe.throw(_("Insurance Start date should be less than Insurance End date"))
frappe.throw(_("Insurance Start date should be less than Insurance End date"))
if getdate(self.carbon_check_date) > getdate():
frappe.throw(_("Last carbon check date cannot be a future date"))

View File

@ -21,7 +21,7 @@
<hr>
<div class="row">
<div class="col-sm-6 ">
<div class ="row multimode-payments">
<div class ="row multimode-payments" style = "margin-right:10px">
</div>
</div>
<div class="col-sm-6 payment-toolbar">

View File

@ -1,5 +1,5 @@
{
"add_total_row": 1,
"add_total_row": 0,
"creation": "2018-09-21 12:46:29.451048",
"disable_prepared_report": 0,
"disabled": 0,
@ -7,7 +7,7 @@
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-02-12 14:30:40.043652",
"modified": "2019-05-24 05:37:02.866139",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Analytics",

View File

@ -135,8 +135,8 @@ class NamingSeries(Document):
def validate_series_name(self, n):
import re
if not re.match("^[\w\- /.#]*$", n, re.UNICODE):
throw(_('Special Characters except "-", "#", "." and "/" not allowed in naming series'))
if not re.match("^[\w\- /.#{}]*$", n, re.UNICODE):
throw(_('Special Characters except "-", "#", ".", "/", "{" and "}" not allowed in naming series'))
def get_options(self, arg=None):
if frappe.get_meta(arg or self.select_doc_for_series).get_field("naming_series"):

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ frappe.ui.form.on("Purchase Receipt", {
frm.custom_make_buttons = {
'Stock Entry': 'Return',
'Purchase Invoice': 'Invoice'
}
};
frm.set_query("asset", "items", function() {
return {
@ -18,7 +18,15 @@ frappe.ui.form.on("Purchase Receipt", {
"purchase_receipt": frm.doc.name
}
}
})
});
frm.set_query("expense_account", "items", function() {
return {
query: "erpnext.controllers.queries.get_expense_account",
filters: {'company': frm.doc.company}
}
});
},
onload: function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {

View File

@ -4,6 +4,7 @@
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"barcode",
"section_break_2",
@ -80,6 +81,7 @@
"rejected_serial_no",
"section_break_50",
"project",
"expense_account",
"cost_center",
"col_break5",
"allow_zero_valuation_rate",
@ -245,6 +247,7 @@
"width": "100px"
},
{
"default": "0",
"fetch_from": "item_code.retain_sample",
"fieldname": "retain_sample",
"fieldtype": "Check",
@ -361,6 +364,7 @@
"read_only": 1
},
{
"default": "0",
"fieldname": "is_free_item",
"fieldtype": "Check",
"label": "Is Free Item",
@ -482,6 +486,7 @@
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "is_fixed_asset",
"fieldtype": "Check",
"hidden": 1,
@ -620,6 +625,7 @@
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "allow_zero_valuation_rate",
"fieldtype": "Check",
"label": "Allow Zero Valuation Rate",
@ -635,6 +641,7 @@
"print_hide": 1
},
{
"default": "0",
"depends_on": "eval:parent.is_subcontracted == 'Yes'",
"fieldname": "include_exploded_items",
"fieldtype": "Check",
@ -739,6 +746,7 @@
},
{
"allow_on_submit": 1,
"default": "0",
"fieldname": "page_break",
"fieldtype": "Check",
"label": "Page Break",
@ -766,11 +774,19 @@
"fieldname": "material_request_item",
"fieldtype": "Data",
"label": "Material Request Item"
},
{
"fieldname": "expense_account",
"fieldtype": "Link",
"hidden": 1,
"label": "Expense Account",
"options": "Account",
"read_only": 1
}
],
"idx": 1,
"istable": 1,
"modified": "2019-05-08 10:25:27.157675",
"modified": "2019-05-30 18:09:21.648599",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",

View File

@ -0,0 +1,58 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
// For license information, please see license.txt
frappe.query_reports["Product Bundle Balance"] = {
"filters": [
{
"fieldname":"date",
"label": __("Date"),
"fieldtype": "Date",
"width": "80",
"reqd": 1,
"default": frappe.datetime.get_today(),
},
{
"fieldname": "item_code",
"label": __("Item"),
"fieldtype": "Link",
"width": "80",
"options": "Item",
"get_query": function() {
return {
query: "erpnext.controllers.queries.item_query",
filters: {"is_stock_item": 0}
};
}
},
{
"fieldname": "item_group",
"label": __("Item Group"),
"fieldtype": "Link",
"width": "80",
"options": "Item Group"
},
{
"fieldname":"brand",
"label": __("Brand"),
"fieldtype": "Link",
"options": "Brand"
},
{
"fieldname": "warehouse",
"label": __("Warehouse"),
"fieldtype": "Link",
"width": "80",
"options": "Warehouse"
},
],
"initial_depth": 0,
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (!data.parent_item) {
value = $(`<span>${value}</span>`);
var $value = $(value).css("font-weight", "bold");
value = $value.wrap("<p></p>").parent().html();
}
return value;
}
};

View File

@ -0,0 +1,23 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2019-03-06 01:40:35.418304",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-03-06 01:40:35.418304",
"modified_by": "Administrator",
"module": "Stock",
"name": "Product Bundle Balance",
"owner": "Administrator",
"ref_doctype": "Stock Ledger Entry",
"report_name": "Product Bundle Balance",
"report_type": "Script Report",
"roles": [
{
"role": "Stock User"
}
]
}

View File

@ -0,0 +1,187 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition
from six import iteritems
def execute(filters=None):
if not filters:
filters = frappe._dict()
columns = get_columns()
item_details, pb_details, parent_items, child_items = get_items(filters)
stock_balance = get_stock_balance(filters, child_items)
data = []
for parent_item in parent_items:
parent_item_detail = item_details[parent_item]
required_items = pb_details[parent_item]
warehouse_company_map = {}
for child_item in required_items:
child_item_balance = stock_balance.get(child_item.item_code, frappe._dict())
for warehouse, sle in iteritems(child_item_balance):
if flt(sle.qty_after_transaction) > 0:
warehouse_company_map[warehouse] = sle.company
for warehouse, company in iteritems(warehouse_company_map):
parent_row = {
"indent": 0,
"item_code": parent_item,
"item_name": parent_item_detail.item_name,
"item_group": parent_item_detail.item_group,
"brand": parent_item_detail.brand,
"description": parent_item_detail.description,
"warehouse": warehouse,
"uom": parent_item_detail.stock_uom,
"company": company,
}
child_rows = []
for child_item_detail in required_items:
child_item_balance = stock_balance.get(child_item_detail.item_code, frappe._dict()).get(warehouse, frappe._dict())
child_row = {
"indent": 1,
"parent_item": parent_item,
"item_code": child_item_detail.item_code,
"item_name": child_item_detail.item_name,
"item_group": child_item_detail.item_group,
"brand": child_item_detail.brand,
"description": child_item_detail.description,
"warehouse": warehouse,
"uom": child_item_detail.uom,
"actual_qty": flt(child_item_balance.qty_after_transaction),
"minimum_qty": flt(child_item_detail.qty),
"company": company,
}
child_row["bundle_qty"] = child_row["actual_qty"] // child_row["minimum_qty"]
child_rows.append(child_row)
min_bundle_qty = min(map(lambda d: d["bundle_qty"], child_rows))
parent_row["bundle_qty"] = min_bundle_qty
data.append(parent_row)
data += child_rows
return columns, data
def get_columns():
columns = [
{"fieldname": "item_code", "label": _("Item"), "fieldtype": "Link", "options": "Item", "width": 300},
{"fieldname": "warehouse", "label": _("Warehouse"), "fieldtype": "Link", "options": "Warehouse", "width": 100},
{"fieldname": "uom", "label": _("UOM"), "fieldtype": "Link", "options": "UOM", "width": 70},
{"fieldname": "bundle_qty", "label": _("Bundle Qty"), "fieldtype": "Float", "width": 100},
{"fieldname": "actual_qty", "label": _("Actual Qty"), "fieldtype": "Float", "width": 100},
{"fieldname": "minimum_qty", "label": _("Minimum Qty"), "fieldtype": "Float", "width": 100},
{"fieldname": "item_group", "label": _("Item Group"), "fieldtype": "Link", "options": "Item Group", "width": 100},
{"fieldname": "brand", "label": _("Brand"), "fieldtype": "Link", "options": "Brand", "width": 100},
{"fieldname": "description", "label": _("Description"), "width": 140},
{"fieldname": "company", "label": _("Company"), "fieldtype": "Link", "options": "Company", "width": 100}
]
return columns
def get_items(filters):
pb_details = frappe._dict()
item_details = frappe._dict()
conditions = get_parent_item_conditions(filters)
parent_item_details = frappe.db.sql("""
select item.name as item_code, item.item_name, pb.description, item.item_group, item.brand, item.stock_uom
from `tabItem` item
inner join `tabProduct Bundle` pb on pb.new_item_code = item.name
where ifnull(item.disabled, 0) = 0 {0}
""".format(conditions), filters, as_dict=1) # nosec
parent_items = []
for d in parent_item_details:
parent_items.append(d.item_code)
item_details[d.item_code] = d
if parent_items:
child_item_details = frappe.db.sql("""
select
pb.new_item_code as parent_item, pbi.item_code, item.item_name, pbi.description, item.item_group, item.brand,
item.stock_uom, pbi.uom, pbi.qty
from `tabProduct Bundle Item` pbi
inner join `tabProduct Bundle` pb on pb.name = pbi.parent
inner join `tabItem` item on item.name = pbi.item_code
where pb.new_item_code in ({0})
""".format(", ".join(["%s"] * len(parent_items))), parent_items, as_dict=1) # nosec
else:
child_item_details = []
child_items = set()
for d in child_item_details:
if d.item_code != d.parent_item:
pb_details.setdefault(d.parent_item, []).append(d)
child_items.add(d.item_code)
item_details[d.item_code] = d
child_items = list(child_items)
return item_details, pb_details, parent_items, child_items
def get_stock_balance(filters, items):
sle = get_stock_ledger_entries(filters, items)
stock_balance = frappe._dict()
for d in sle:
stock_balance.setdefault(d.item_code, frappe._dict())[d.warehouse] = d
return stock_balance
def get_stock_ledger_entries(filters, items):
if not items:
return []
item_conditions_sql = ' and sle.item_code in ({})' \
.format(', '.join([frappe.db.escape(i) for i in items]))
conditions = get_sle_conditions(filters)
return frappe.db.sql("""
select
sle.item_code, sle.warehouse, sle.qty_after_transaction, sle.company
from
`tabStock Ledger Entry` sle force index (posting_sort_index)
left join `tabStock Ledger Entry` sle2 on
sle.item_code = sle2.item_code and sle.warehouse = sle2.warehouse
and (sle.posting_date, sle.posting_time, sle.name) < (sle2.posting_date, sle2.posting_time, sle2.name)
where sle2.name is null and sle.docstatus < 2 %s %s""" % (item_conditions_sql, conditions), as_dict=1) # nosec
def get_parent_item_conditions(filters):
conditions = []
if filters.get("item_code"):
conditions.append("item.item_code = %(item_code)s")
else:
if filters.get("brand"):
conditions.append("item.brand=%(brand)s")
if filters.get("item_group"):
conditions.append(get_item_group_condition(filters.get("item_group")))
conditions = " and ".join(conditions)
return "and {0}".format(conditions) if conditions else ""
def get_sle_conditions(filters):
conditions = ""
if not filters.get("date"):
frappe.throw(_("'Date' is required"))
conditions += " and sle.posting_date <= %s" % frappe.db.escape(filters.get("date"))
if filters.get("warehouse"):
warehouse_details = frappe.db.get_value("Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1)
if warehouse_details:
conditions += " and exists (select name from `tabWarehouse` wh \
where wh.lft >= %s and wh.rgt <= %s and sle.warehouse = wh.name)" % (warehouse_details.lft, warehouse_details.rgt) # nosec
return conditions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
DocType: Account,Accounts,དངུལ་རྩིས།
DocType: Pricing Rule,Buying,ཉོ་བ།
1 DocType: Account Accounts དངུལ་རྩིས།
DocType: Account Accounts དངུལ་རྩིས།
DocType: Pricing Rule Buying ཉོ་བ།

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
DocType: Patient,Married,既婚
1 DocType: Patient Married 既婚
DocType: Patient Married 既婚

View File

View File

File diff suppressed because it is too large Load Diff

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff