Merge branch 'version-11-hotfix' into version-11

This commit is contained in:
Sahil Khan
2019-09-17 17:00:32 +05:30
16 changed files with 1177 additions and 1094 deletions

View File

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

View File

@@ -41,6 +41,8 @@ def get_pos_data():
items_list = get_items_list(pos_profile, doc.company)
customers = get_customers_list(pos_profile)
doc.plc_conversion_rate = update_plc_conversion_rate(doc, pos_profile)
return {
'doc': doc,
'default_customer': pos_profile.get('customer'),
@@ -53,7 +55,7 @@ def get_pos_data():
'batch_no_data': get_batch_no_data(),
'barcode_data': get_barcode_data(items_list),
'tax_data': get_item_tax_data(),
'price_list_data': get_price_list_data(doc.selling_price_list),
'price_list_data': get_price_list_data(doc.selling_price_list, doc.plc_conversion_rate),
'customer_wise_price_list': get_customer_wise_price_list(),
'bin_data': get_bin_data(pos_profile),
'pricing_rules': get_pricing_rule_data(doc),
@@ -62,6 +64,15 @@ def get_pos_data():
'meta': get_meta()
}
def update_plc_conversion_rate(doc, pos_profile):
conversion_rate = 1.0
price_list_currency = frappe.get_cached_value("Price List", doc.selling_price_list, "currency")
if pos_profile.get("currency") != price_list_currency:
conversion_rate = get_exchange_rate(price_list_currency,
pos_profile.get("currency"), nowdate(), args="for_selling") or 1.0
return conversion_rate
def get_meta():
doctype_meta = {
@@ -317,14 +328,14 @@ def get_item_tax_data():
return itemwise_tax
def get_price_list_data(selling_price_list):
def get_price_list_data(selling_price_list, conversion_rate):
itemwise_price_list = {}
price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
item_code from `tabItem Price` ip where price_list = %(price_list)s""",
{'price_list': selling_price_list}, as_dict=1)
for item in price_lists:
itemwise_price_list[item.item_code] = item.price_list_rate
itemwise_price_list[item.item_code] = item.price_list_rate * conversion_rate
return itemwise_price_list

View File

@@ -207,7 +207,7 @@ class SalesInvoice(SellingController):
for payment in self.payments:
total_amount_in_payments += payment.amount
invoice_total = self.rounded_total or self.grand_total
if total_amount_in_payments < invoice_total:
if flt(total_amount_in_payments, self.precision("grand_total")) < invoice_total:
frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
def validate_pos_paid_amount(self):

View File

@@ -1625,7 +1625,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
setTimeout(function () {
w.print();
w.close();
}, 1000)
}, 1000);
},
submit_invoice: function () {
@@ -1682,6 +1682,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
$(this.wrapper).find('.pos-bill').css('pointer-events', pointer_events);
$(this.wrapper).find('.pos-items-section').css('pointer-events', pointer_events);
this.set_primary_action();
$(this.wrapper).find('#pos-item-disc').prop('disabled',
this.pos_profile_data.allow_user_to_edit_discount ? false : true);
$(this.wrapper).find('#pos-item-price').prop('disabled',
this.pos_profile_data.allow_user_to_edit_rate ? false : true);
},
create_invoice: function () {
@@ -1699,13 +1705,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
if (this.frm.doc.offline_pos_name
&& in_list(existing_pos_list, this.frm.doc.offline_pos_name)) {
this.update_invoice()
//to retrieve and set the default payment
invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
invoice_data[this.frm.doc.offline_pos_name].payments[0].amount = this.frm.doc.net_total
invoice_data[this.frm.doc.offline_pos_name].payments[0].base_amount = this.frm.doc.net_total
this.frm.doc.paid_amount = this.frm.doc.net_total
this.frm.doc.outstanding_amount = 0
} else if(!this.frm.doc.offline_pos_name) {
this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
this.frm.doc.posting_date = frappe.datetime.get_today();
@@ -1907,7 +1906,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
serial_no = me.item_serial_no[key][0];
}
if (this.items[0].has_serial_no && serial_no == "") {
if (this.items && this.items[0].has_serial_no && serial_no == "") {
this.refresh();
frappe.throw(__(repl("Error: Serial no is mandatory for item %(item)s", {
'item': this.items[0].item_code

View File

@@ -364,7 +364,7 @@ class ReceivablePayableReport(object):
on
(ref.parent = payment_entry.name)
where
payment_entry.docstatus = 1
payment_entry.docstatus < 2
and payment_entry.posting_date > %s
and payment_entry.party_type = %s
""", (self.filters.report_date, self.party_type), as_dict=1)
@@ -389,7 +389,7 @@ class ReceivablePayableReport(object):
on
(jea.parent = je.name)
where
je.docstatus = 1
je.docstatus < 2
and je.posting_date > %s
and jea.party_type = %s
and jea.reference_name is not null and jea.reference_name != ''
@@ -685,4 +685,4 @@ class ReceivablePayableReport(object):
'datasets': rows
},
"type": 'percentage'
}
}

View File

@@ -56,8 +56,7 @@ def assign_tasks(asset_maintenance_name, assign_to_member, maintenance_task, nex
def calculate_next_due_date(periodicity, start_date = None, end_date = None, last_completion_date = None, next_due_date = None):
if not start_date and not last_completion_date:
start_date = frappe.utils.now()
if last_completion_date and (last_completion_date > start_date or not start_date):
if last_completion_date and ((start_date and last_completion_date > start_date) or not start_date):
start_date = last_completion_date
if periodicity == 'Daily':
next_due_date = add_days(start_date, 1)
@@ -115,4 +114,4 @@ def get_maintenance_log(asset_name):
select maintenance_status, count(asset_name) as count, asset_name
from `tabAsset Maintenance Log`
where asset_name=%s group by maintenance_status""",
(asset_name), as_dict=1)
(asset_name), as_dict=1)

View File

@@ -87,7 +87,7 @@ class AccountsController(TransactionBase):
self.validate_currency()
if self.doctype == 'Purchase Invoice':
self.validate_paid_amount()
self.calculate_paid_amount()
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
@@ -131,22 +131,23 @@ class AccountsController(TransactionBase):
else:
df.set("print_hide", 1)
def validate_paid_amount(self):
def calculate_paid_amount(self):
if hasattr(self, "is_pos") or hasattr(self, "is_paid"):
is_paid = self.get("is_pos") or self.get("is_paid")
if cint(is_paid) == 1:
if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
if self.cash_bank_account:
self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
self.precision("base_paid_amount"))
else:
# show message that the amount is not paid
self.paid_amount = 0
frappe.throw(
_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
else:
frappe.db.set(self, 'paid_amount', 0)
if is_paid:
if not self.cash_bank_account:
# show message that the amount is not paid
frappe.throw(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
if cint(self.is_return) and (self.grand_total > self.paid_amount):
self.paid_amount = flt(flt(self.grand_total), self.precision("paid_amount"))
elif not flt(self.paid_amount) and flt(self.outstanding_amount) > 0:
self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
self.precision("base_paid_amount"))
def set_missing_values(self, for_validate=False):
if frappe.flags.in_test:

View File

@@ -246,6 +246,8 @@ def make_return_doc(doctype, source_name, target_doc=None):
elif doc.doctype == 'Purchase Invoice':
doc.paid_amount = -1 * source.paid_amount
doc.base_paid_amount = -1 * source.base_paid_amount
doc.payment_terms_template = ''
doc.payment_schedule = []
if doc.get("is_return") and hasattr(doc, "packed_items"):
for d in doc.get("packed_items"):

View File

@@ -39,7 +39,6 @@ def validate_filters(filters):
frappe.throw(_("'Based On' and 'Group By' can not be same"))
def get_data(filters, conditions):
data = []
inc, cond= '',''
query_details = conditions["based_on_select"] + conditions["period_wise_select"]
@@ -47,13 +46,17 @@ def get_data(filters, conditions):
posting_date = 't1.transaction_date'
if conditions.get('trans') in ['Sales Invoice', 'Purchase Invoice', 'Purchase Receipt', 'Delivery Note']:
posting_date = 't1.posting_date'
if filters.period_based_on:
posting_date = 't1.'+filters.period_based_on
if conditions["based_on_select"] in ["t1.project,", "t2.project,"]:
cond = ' and '+ conditions["based_on_select"][:-1] +' IS Not NULL'
if conditions.get('trans') in ['Sales Order', 'Purchase Order']:
cond += " and t1.status != 'Closed'"
if conditions.get('trans') == 'Quotation' and filters.get("group_by") == 'Customer':
cond += " and t1.quotation_to = 'Customer'"
year_start_date, year_end_date = frappe.db.get_value("Fiscal Year",
filters.get('fiscal_year'), ["year_start_date", "year_end_date"])
@@ -64,7 +67,7 @@ def get_data(filters, conditions):
if filters.get("group_by") == 'Item':
sel_col = 't2.item_code'
elif filters.get("group_by") == 'Customer':
sel_col = 't1.customer'
sel_col = 't1.party_name' if conditions.get('trans') == 'Quotation' else 't1.customer'
elif filters.get("group_by") == 'Supplier':
sel_col = 't1.supplier'
@@ -225,7 +228,7 @@ def based_wise_columns_query(based_on, trans):
elif based_on == "Customer":
based_on_details["based_on_cols"] = ["Customer:Link/Customer:120", "Territory:Link/Territory:120"]
based_on_details["based_on_select"] = "t1.customer_name, t1.territory, "
based_on_details["based_on_group_by"] = 't1.customer'
based_on_details["based_on_group_by"] = 't1.party_name' if trans == 'Quotation' else 't1.customer'
based_on_details["addl_tables"] = ''
elif based_on == "Customer Group":

View File

@@ -62,7 +62,8 @@ def _order(*args, **kwargs):
item_woo_com_id = item.get("product_id")
if frappe.get_value("Item",{"woocommerce_id": item_woo_com_id}):
if frappe.get_value("Item",{"woocommerce_id": item_woo_com_id}) or\
frappe.get_value("Item",{"item_name": item.get('name')}):
#Edit
link_item(item,1)
else:

View File

@@ -41,6 +41,12 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.calculate_contribution();
}
// Update paid amount on return/debit note creation
if(this.frm.doc.doctype === "Purchase Invoice" && this.frm.doc.is_return
&& (this.frm.doc.grand_total > this.frm.doc.paid_amount)) {
this.frm.doc.paid_amount = flt(this.frm.doc.grand_total, precision("grand_total"));
}
this.frm.refresh_fields();
},

View File

@@ -3,6 +3,14 @@
erpnext.get_purchase_trends_filters = function() {
return [
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"reqd": 1,
"default": frappe.defaults.get_user_default("Company")
},
{
"fieldname":"period",
"label": __("Period"),
@@ -15,6 +23,23 @@ erpnext.get_purchase_trends_filters = function() {
],
"default": "Monthly"
},
{
"fieldname":"fiscal_year",
"label": __("Fiscal Year"),
"fieldtype": "Link",
"options":'Fiscal Year',
"default": frappe.sys_defaults.fiscal_year
},
{
"fieldname":"period_based_on",
"label": __("Period based On"),
"fieldtype": "Select",
"options": [
{ "value": "posting_date", "label": __("Posting Date") },
{ "value": "bill_date", "label": __("Billing Date") },
],
"default": "posting_date"
},
{
"fieldname":"based_on",
"label": __("Based On"),
@@ -39,19 +64,5 @@ erpnext.get_purchase_trends_filters = function() {
],
"default": ""
},
{
"fieldname":"fiscal_year",
"label": __("Fiscal Year"),
"fieldtype": "Link",
"options":'Fiscal Year',
"default": frappe.sys_defaults.fiscal_year
},
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company")
},
];
}
}

View File

@@ -1,5 +1,11 @@
{%- macro format_float(value, precision=2) -%}
{{ value|round(frappe.utils.cint(precision)) }}
{%- if frappe.utils.cint(precision) == 3 %}
{{ "%.3f" % value|abs }}
{%- elif frappe.utils.cint(precision) == 4 -%}
{{ "%.4f" % value|abs }}
{%- else -%}
{{ "%.2f" % value|abs }}
{%- endif %}
{%- endmacro -%}
{%- macro render_address(address) %}

View File

@@ -151,7 +151,7 @@ class NamingSeries(Document):
def insert_series(self, series):
"""insert series if missing"""
if not frappe.db.get_value('Series', series, 'name', order_by="name"):
if frappe.db.get_value('Series', series, 'name', order_by="name") == None:
frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
def update_series_start(self):

File diff suppressed because it is too large Load Diff

View File

@@ -87,6 +87,7 @@ class Issue(Document):
from copy import deepcopy
replicated_issue = deepcopy(self)
replicated_issue.subject = subject
replicated_issue.issue_split_from = self.name
frappe.get_doc(replicated_issue).insert()
# Replicate linked Communications
# todo get all communications in timeline before this, and modify them to append them to new doc
@@ -96,6 +97,15 @@ class Issue(Document):
doc = frappe.get_doc("Communication", communication.name)
doc.reference_name = replicated_issue.name
doc.save(ignore_permissions=True)
frappe.get_doc({
"doctype": "Comment",
"comment_type": "Info",
"reference_doctype": "Issue",
"reference_name": replicated_issue.name,
"content": " - Split the Issue from <a href='#Form/Issue/{0}'>{1}</a>".format(self.name, frappe.bold(self.name))
}).insert(ignore_permissions=True)
return replicated_issue.name
def get_list_context(context=None):
@@ -177,4 +187,4 @@ def make_issue_from_communication(communication, ignore_communication_links=Fals
link_communication_to_document(doc, "Issue", issue.name, ignore_communication_links)
return issue.name
return issue.name