Merge branch 'hotfix'
This commit is contained in:
@@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '11.1.47'
|
__version__ = '11.1.48'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ class BankAccount(Document):
|
|||||||
# Encode characters as numbers
|
# Encode characters as numbers
|
||||||
encoded = [encode_char(c) if ord(c) >= 65 and ord(c) <= 90 else c for c in flipped]
|
encoded = [encode_char(c) if ord(c) >= 65 and ord(c) <= 90 else c for c in flipped]
|
||||||
|
|
||||||
to_check = int(''.join(encoded))
|
try:
|
||||||
|
to_check = int(''.join(encoded))
|
||||||
|
except ValueError:
|
||||||
|
frappe.throw(_('IBAN is not valid'))
|
||||||
|
|
||||||
if to_check % 97 != 1:
|
if to_check % 97 != 1:
|
||||||
frappe.throw(_('IBAN is not valid'))
|
frappe.throw(_('IBAN is not valid'))
|
||||||
|
|||||||
@@ -451,6 +451,10 @@ def make_customer_and_address(customers):
|
|||||||
|
|
||||||
|
|
||||||
def add_customer(data):
|
def add_customer(data):
|
||||||
|
customer = data.get('full_name') or data.get('customer')
|
||||||
|
if frappe.db.exists("Customer", customer.strip()):
|
||||||
|
return customer.strip()
|
||||||
|
|
||||||
customer_doc = frappe.new_doc('Customer')
|
customer_doc = frappe.new_doc('Customer')
|
||||||
customer_doc.customer_name = data.get('full_name') or data.get('customer')
|
customer_doc.customer_name = data.get('full_name') or data.get('customer')
|
||||||
customer_doc.customer_pos_id = data.get('customer_pos_id')
|
customer_doc.customer_pos_id = data.get('customer_pos_id')
|
||||||
|
|||||||
@@ -397,14 +397,18 @@ class SalesInvoice(SellingController):
|
|||||||
if pos.get('account_for_change_amount'):
|
if pos.get('account_for_change_amount'):
|
||||||
self.account_for_change_amount = pos.get('account_for_change_amount')
|
self.account_for_change_amount = pos.get('account_for_change_amount')
|
||||||
|
|
||||||
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
|
for fieldname in ('territory', 'naming_series', 'currency', 'letter_head', 'tc_name',
|
||||||
'company', 'select_print_heading', 'cash_bank_account', 'company_address',
|
'company', 'select_print_heading', 'cash_bank_account', 'write_off_account',
|
||||||
'write_off_account', 'write_off_cost_center', 'apply_discount_on', 'cost_center'):
|
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
|
||||||
if (not for_validate) or (for_validate and not self.get(fieldname)):
|
if (not for_validate) or (for_validate and not self.get(fieldname)):
|
||||||
self.set(fieldname, pos.get(fieldname))
|
self.set(fieldname, pos.get(fieldname))
|
||||||
|
|
||||||
customer_price_list = frappe.get_value("Customer", self.customer, 'default_price_list')
|
customer_price_list = frappe.get_value("Customer", self.customer, 'default_price_list')
|
||||||
|
|
||||||
|
for field in ['taxes_and_charges', 'company_address']:
|
||||||
|
if pos.get(field):
|
||||||
|
self.set(field, pos.get(fieldname))
|
||||||
|
|
||||||
if not customer_price_list:
|
if not customer_price_list:
|
||||||
self.set('selling_price_list', pos.get('selling_price_list'))
|
self.set('selling_price_list', pos.get('selling_price_list'))
|
||||||
|
|
||||||
|
|||||||
@@ -717,7 +717,6 @@ def get_children(doctype, parent, company, is_root=False):
|
|||||||
parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
|
parent_fieldname = 'parent_' + doctype.lower().replace(' ', '_')
|
||||||
fields = [
|
fields = [
|
||||||
'name as value',
|
'name as value',
|
||||||
'root_type',
|
|
||||||
'is_group as expandable'
|
'is_group as expandable'
|
||||||
]
|
]
|
||||||
filters = [['docstatus', '<', 2]]
|
filters = [['docstatus', '<', 2]]
|
||||||
@@ -725,11 +724,11 @@ def get_children(doctype, parent, company, is_root=False):
|
|||||||
filters.append(['ifnull(`{0}`,"")'.format(parent_fieldname), '=', '' if is_root else parent])
|
filters.append(['ifnull(`{0}`,"")'.format(parent_fieldname), '=', '' if is_root else parent])
|
||||||
|
|
||||||
if is_root:
|
if is_root:
|
||||||
fields += ['report_type', 'account_currency'] if doctype == 'Account' else []
|
fields += ['root_type', 'report_type', 'account_currency'] if doctype == 'Account' else []
|
||||||
filters.append(['company', '=', company])
|
filters.append(['company', '=', company])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
fields += ['account_currency'] if doctype == 'Account' else []
|
fields += ['root_type', 'account_currency'] if doctype == 'Account' else []
|
||||||
fields += [parent_fieldname + ' as parent']
|
fields += [parent_fieldname + ' as parent']
|
||||||
|
|
||||||
acc = frappe.get_list(doctype, fields=fields, filters=filters)
|
acc = frappe.get_list(doctype, fields=fields, filters=filters)
|
||||||
|
|||||||
@@ -825,7 +825,7 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||||
grand_total = grand_total - flt(self.write_off_amount)
|
grand_total = grand_total - flt(self.write_off_amount)
|
||||||
if total != grand_total:
|
if total != flt(grand_total, self.precision("grand_total")):
|
||||||
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
||||||
|
|
||||||
def is_rounded_total_disabled(self):
|
def is_rounded_total_disabled(self):
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
|
|
||||||
self.doc.round_floats_in(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"])
|
self.doc.round_floats_in(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"])
|
||||||
|
|
||||||
self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate) \
|
self.doc.base_grand_total = flt(self.doc.grand_total * self.doc.conversion_rate, self.doc.precision("base_grand_total")) \
|
||||||
if (self.doc.taxes_and_charges_added or self.doc.taxes_and_charges_deducted) \
|
if (self.doc.taxes_and_charges_added or self.doc.taxes_and_charges_deducted) \
|
||||||
else self.doc.base_net_total
|
else self.doc.base_net_total
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,8 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
|
|||||||
setup: function () {
|
setup: function () {
|
||||||
|
|
||||||
this.frm.make_methods = {
|
this.frm.make_methods = {
|
||||||
'Quotation': () => erpnext.utils.create_new_doc('Quotation', {
|
'Quotation': this.make_quotation,
|
||||||
'quotation_to': this.frm.doc.doctype,
|
'Opportunity': this.create_opportunity
|
||||||
'party_name': this.frm.doc.name
|
|
||||||
}),
|
|
||||||
'Opportunity': () => erpnext.utils.create_new_doc('Opportunity', {
|
|
||||||
'opportunity_from': this.frm.doc.doctype,
|
|
||||||
'party_name': this.frm.doc.name
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
|
this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ erpnext.SMSManager = function SMSManager(doc) {
|
|||||||
'Purchase Receipt' : 'Items has been received against purchase receipt: ' + doc.name
|
'Purchase Receipt' : 'Items has been received against purchase receipt: ' + doc.name
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_list(['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice'], doc.doctype))
|
if (in_list(['Sales Order', 'Delivery Note', 'Sales Invoice'], doc.doctype))
|
||||||
this.show(doc.contact_person, 'Customer', doc.customer, '', default_msg[doc.doctype]);
|
this.show(doc.contact_person, 'Customer', doc.customer, '', default_msg[doc.doctype]);
|
||||||
else if (in_list(['Purchase Order', 'Purchase Receipt'], doc.doctype))
|
else if (in_list(['Purchase Order', 'Purchase Receipt'], doc.doctype))
|
||||||
this.show(doc.contact_person, 'Supplier', doc.supplier, '', default_msg[doc.doctype]);
|
this.show(doc.contact_person, 'Supplier', doc.supplier, '', default_msg[doc.doctype]);
|
||||||
@@ -28,6 +28,8 @@ erpnext.SMSManager = function SMSManager(doc) {
|
|||||||
this.show('', '', '', doc.mobile_no, default_msg[doc.doctype]);
|
this.show('', '', '', doc.mobile_no, default_msg[doc.doctype]);
|
||||||
else if (doc.doctype == 'Opportunity')
|
else if (doc.doctype == 'Opportunity')
|
||||||
this.show('', '', '', doc.contact_no, default_msg[doc.doctype]);
|
this.show('', '', '', doc.contact_no, default_msg[doc.doctype]);
|
||||||
|
else if (doc.doctype == 'Quotation')
|
||||||
|
this.show(doc.contact_person, doc.quotation_to, doc.party_name, '', default_msg[doc.doctype]);
|
||||||
else if (doc.doctype == 'Material Request')
|
else if (doc.doctype == 'Material Request')
|
||||||
this.show('', '', '', '', default_msg[doc.doctype]);
|
this.show('', '', '', '', default_msg[doc.doctype]);
|
||||||
|
|
||||||
|
|||||||
@@ -503,10 +503,12 @@ def make_material_request(source_name, target_doc=None):
|
|||||||
doc.material_request_type = "Purchase"
|
doc.material_request_type = "Purchase"
|
||||||
|
|
||||||
def update_item(source, target, source_parent):
|
def update_item(source, target, source_parent):
|
||||||
|
# qty is for packed items, because packed items don't have stock_qty field
|
||||||
|
qty = source.get("stock_qty") or source.get("qty")
|
||||||
target.project = source_parent.project
|
target.project = source_parent.project
|
||||||
target.qty = source.stock_qty - requested_item_qty.get(source.name, 0)
|
target.qty = qty - requested_item_qty.get(source.name, 0)
|
||||||
target.conversion_factor = 1
|
target.conversion_factor = 1
|
||||||
target.stock_qty = source.stock_qty - requested_item_qty.get(source.name, 0)
|
target.stock_qty = qty - requested_item_qty.get(source.name, 0)
|
||||||
|
|
||||||
doc = get_mapped_doc("Sales Order", source_name, {
|
doc = get_mapped_doc("Sales Order", source_name, {
|
||||||
"Sales Order": {
|
"Sales Order": {
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
frappe.query_reports["Customer-wise Item Price"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"label": __("Customer"),
|
||||||
|
"fieldname": "customer",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Customer",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": __("Item"),
|
||||||
|
"fieldname": "item",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Item",
|
||||||
|
"get_query": () => {
|
||||||
|
return {
|
||||||
|
query: "erpnext.controllers.queries.item_query",
|
||||||
|
filters: { 'is_sales_item': 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"creation": "2019-06-12 03:25:36.263179",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"letter_head": "Delta9",
|
||||||
|
"modified": "2019-06-12 03:25:36.263179",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Selling",
|
||||||
|
"name": "Customer-wise Item Price",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "Customer",
|
||||||
|
"report_name": "Customer-wise Item Price",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Sales User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Stock Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Accounts User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Accounts Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Sales Master Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Stock User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from erpnext import get_default_company
|
||||||
|
from erpnext.accounts.party import get_party_details
|
||||||
|
from erpnext.stock.get_item_details import get_price_list_rate_for
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
if not filters:
|
||||||
|
filters = {}
|
||||||
|
|
||||||
|
if not filters.get("customer"):
|
||||||
|
frappe.throw(_("Please select a Customer"))
|
||||||
|
|
||||||
|
columns = get_columns(filters)
|
||||||
|
data = get_data(filters)
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
|
||||||
|
def get_columns(filters=None):
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"label": _("Item Code"),
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Item",
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Item Name"),
|
||||||
|
"fieldname": "item_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Selling Rate"),
|
||||||
|
"fieldname": "selling_rate",
|
||||||
|
"fieldtype": "Currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Available Stock"),
|
||||||
|
"fieldname": "available_stock",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Price List"),
|
||||||
|
"fieldname": "price_list",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Price List",
|
||||||
|
"width": 120
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(filters=None):
|
||||||
|
data = []
|
||||||
|
customer_details = get_customer_details(filters)
|
||||||
|
|
||||||
|
items = get_selling_items(filters)
|
||||||
|
item_stock_map = frappe.get_all("Bin", fields=["item_code", "sum(actual_qty) AS available"], group_by="item_code")
|
||||||
|
item_stock_map = {item.item_code: item.available for item in item_stock_map}
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
price_list_rate = get_price_list_rate_for(customer_details, item.item_code) or 0.0
|
||||||
|
available_stock = item_stock_map.get(item.item_code)
|
||||||
|
|
||||||
|
data.append({
|
||||||
|
"item_code": item.item_code,
|
||||||
|
"item_name": item.item_name,
|
||||||
|
"selling_rate": price_list_rate,
|
||||||
|
"price_list": customer_details.get("price_list"),
|
||||||
|
"available_stock": available_stock,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_customer_details(filters):
|
||||||
|
customer_details = get_party_details(party=filters.get("customer"), party_type="Customer")
|
||||||
|
customer_details.update({
|
||||||
|
"company": get_default_company(),
|
||||||
|
"price_list": customer_details.get("selling_price_list")
|
||||||
|
})
|
||||||
|
|
||||||
|
return customer_details
|
||||||
|
|
||||||
|
|
||||||
|
def get_selling_items(filters):
|
||||||
|
if filters.get("item"):
|
||||||
|
item_filters = {"item_code": filters.get("item"), "is_sales_item": 1, "disabled": 0}
|
||||||
|
else:
|
||||||
|
item_filters = {"is_sales_item": 1, "disabled": 0}
|
||||||
|
|
||||||
|
items = frappe.get_all("Item", filters=item_filters, fields=["item_code", "item_name"], order_by="item_name")
|
||||||
|
|
||||||
|
return items
|
||||||
@@ -177,7 +177,8 @@ class StockEntry(StockController):
|
|||||||
item.set(f, item_details.get(f))
|
item.set(f, item_details.get(f))
|
||||||
|
|
||||||
if not item.transfer_qty and item.qty:
|
if not item.transfer_qty and item.qty:
|
||||||
item.transfer_qty = item.qty * item.conversion_factor
|
item.transfer_qty = ( flt(item.qty, item.precision("qty"))
|
||||||
|
* flt(item.conversion_factor, item.precision("conversion_factor")) )
|
||||||
|
|
||||||
if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture")
|
if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture")
|
||||||
and not item.serial_no
|
and not item.serial_no
|
||||||
|
|||||||
Reference in New Issue
Block a user