Merge branch 'version-11-hotfix' into version-11
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.52'
|
__version__ = '11.1.53'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@@ -613,13 +613,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
|||||||
|
|
||||||
orders = []
|
orders = []
|
||||||
if voucher_type:
|
if voucher_type:
|
||||||
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"
|
if party_account_currency == company_currency:
|
||||||
|
grand_total_field = "base_grand_total"
|
||||||
|
rounded_total_field = "base_rounded_total"
|
||||||
|
else:
|
||||||
|
grand_total_field = "grand_total"
|
||||||
|
rounded_total_field = "rounded_total"
|
||||||
|
|
||||||
orders = frappe.db.sql("""
|
orders = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
name as voucher_no,
|
name as voucher_no,
|
||||||
{ref_field} as invoice_amount,
|
if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount,
|
||||||
({ref_field} - advance_paid) as outstanding_amount,
|
(if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount,
|
||||||
transaction_date as posting_date
|
transaction_date as posting_date
|
||||||
from
|
from
|
||||||
`tab{voucher_type}`
|
`tab{voucher_type}`
|
||||||
@@ -627,17 +632,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
|||||||
{party_type} = %s
|
{party_type} = %s
|
||||||
and docstatus = 1
|
and docstatus = 1
|
||||||
and ifnull(status, "") != "Closed"
|
and ifnull(status, "") != "Closed"
|
||||||
and {ref_field} > advance_paid
|
and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid
|
||||||
and abs(100 - per_billed) > 0.01
|
and abs(100 - per_billed) > 0.01
|
||||||
{condition}
|
{condition}
|
||||||
order by
|
order by
|
||||||
transaction_date, name
|
transaction_date, name
|
||||||
""".format(**{
|
""".format(**{
|
||||||
"ref_field": ref_field,
|
"rounded_total_field": rounded_total_field,
|
||||||
|
"grand_total_field": grand_total_field,
|
||||||
"voucher_type": voucher_type,
|
"voucher_type": voucher_type,
|
||||||
"party_type": scrub(party_type),
|
"party_type": scrub(party_type),
|
||||||
"condition": condition
|
"condition": condition
|
||||||
}), party, as_dict=True)
|
}), (party), as_dict=True)
|
||||||
|
|
||||||
order_list = []
|
order_list = []
|
||||||
for d in orders:
|
for d in orders:
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ def update_last_purchase_rate(doc, is_submit):
|
|||||||
# for it to be considered for latest purchase rate
|
# for it to be considered for latest purchase rate
|
||||||
if flt(d.conversion_factor):
|
if flt(d.conversion_factor):
|
||||||
last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor)
|
last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor)
|
||||||
else:
|
# Check if item code is present
|
||||||
|
# Conversion factor should not be mandatory for non itemized items
|
||||||
|
elif d.item_code:
|
||||||
frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
|
frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx))
|
||||||
|
|
||||||
# update last purchsae rate
|
# update last purchsae rate
|
||||||
|
|||||||
@@ -1112,6 +1112,10 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
|
|||||||
.format(child_item.idx, child_item.item_code))
|
.format(child_item.idx, child_item.item_code))
|
||||||
else:
|
else:
|
||||||
child_item.rate = flt(d.get("rate"))
|
child_item.rate = flt(d.get("rate"))
|
||||||
|
if flt(child_item.price_list_rate):
|
||||||
|
child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0, \
|
||||||
|
child_item.precision("discount_percentage"))
|
||||||
|
|
||||||
child_item.flags.ignore_validate_update_after_submit = True
|
child_item.flags.ignore_validate_update_after_submit = True
|
||||||
child_item.save()
|
child_item.save()
|
||||||
|
|
||||||
|
|||||||
@@ -395,7 +395,9 @@ class BuyingController(StockController):
|
|||||||
def set_qty_as_per_stock_uom(self):
|
def set_qty_as_per_stock_uom(self):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.meta.get_field("stock_qty"):
|
if d.meta.get_field("stock_qty"):
|
||||||
if not d.conversion_factor:
|
# Check if item code is present
|
||||||
|
# Conversion factor should not be mandatory for non itemized items
|
||||||
|
if not d.conversion_factor and d.item_code:
|
||||||
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
|
frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx))
|
||||||
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
|
d.stock_qty = flt(d.qty) * flt(d.conversion_factor)
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
|
|
||||||
item.net_rate = item.rate
|
item.net_rate = item.rate
|
||||||
|
|
||||||
if not item.qty and self.doc.is_return:
|
if not item.qty and self.doc.get("is_return"):
|
||||||
item.amount = flt(-1 * item.rate, item.precision("amount"))
|
item.amount = flt(-1 * item.rate, item.precision("amount"))
|
||||||
else:
|
else:
|
||||||
item.amount = flt(item.rate * item.qty, item.precision("amount"))
|
item.amount = flt(item.rate * item.qty, item.precision("amount"))
|
||||||
|
|||||||
@@ -130,6 +130,11 @@ def get_customers_suppliers(doctype, user):
|
|||||||
suppliers = []
|
suppliers = []
|
||||||
meta = frappe.get_meta(doctype)
|
meta = frappe.get_meta(doctype)
|
||||||
|
|
||||||
|
customer_field_name = get_customer_field_name(doctype)
|
||||||
|
|
||||||
|
has_customer_field = meta.has_field(customer_field_name)
|
||||||
|
has_supplier_field = meta.has_field('supplier')
|
||||||
|
|
||||||
if has_common(["Supplier", "Customer"], frappe.get_roles(user)):
|
if has_common(["Supplier", "Customer"], frappe.get_roles(user)):
|
||||||
contacts = frappe.db.sql("""
|
contacts = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
@@ -141,27 +146,40 @@ def get_customers_suppliers(doctype, user):
|
|||||||
where
|
where
|
||||||
`tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s
|
`tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s
|
||||||
""", user, as_dict=1)
|
""", user, as_dict=1)
|
||||||
customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] \
|
customers = [c.link_name for c in contacts if c.link_doctype == 'Customer']
|
||||||
if meta.get_field("customer") else None
|
suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier']
|
||||||
suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] \
|
|
||||||
if meta.get_field("supplier") else None
|
|
||||||
elif frappe.has_permission(doctype, 'read', user=user):
|
elif frappe.has_permission(doctype, 'read', user=user):
|
||||||
customers = [customer.name for customer in frappe.get_list("Customer")] \
|
customer_list = frappe.get_list("Customer")
|
||||||
if meta.get_field("customer") else None
|
customers = suppliers = [customer.name for customer in customer_list]
|
||||||
suppliers = [supplier.name for supplier in frappe.get_list("Customer")] \
|
|
||||||
if meta.get_field("supplier") else None
|
|
||||||
|
|
||||||
return customers, suppliers
|
return customers if has_customer_field else None, \
|
||||||
|
suppliers if has_supplier_field else None
|
||||||
|
|
||||||
def has_website_permission(doc, ptype, user, verbose=False):
|
def has_website_permission(doc, ptype, user, verbose=False):
|
||||||
doctype = doc.doctype
|
doctype = doc.doctype
|
||||||
customers, suppliers = get_customers_suppliers(doctype, user)
|
customers, suppliers = get_customers_suppliers(doctype, user)
|
||||||
if customers:
|
if customers:
|
||||||
return frappe.get_all(doctype, filters=[(doctype, "customer", "in", customers),
|
return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers))
|
||||||
(doctype, "name", "=", doc.name)]) and True or False
|
|
||||||
elif suppliers:
|
elif suppliers:
|
||||||
fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier'
|
fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier'
|
||||||
return frappe.get_all(doctype, filters=[(doctype, fieldname, "in", suppliers),
|
return frappe.db.exists(doctype, filters={
|
||||||
(doctype, "name", "=", doc.name)]) and True or False
|
'name': doc.name,
|
||||||
|
fieldname: ["in", suppliers]
|
||||||
|
})
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_customer_filter(doc, customers):
|
||||||
|
doctype = doc.doctype
|
||||||
|
filters = frappe._dict()
|
||||||
|
filters.name = doc.name
|
||||||
|
filters[get_customer_field_name(doctype)] = ['in', customers]
|
||||||
|
if doctype == 'Quotation':
|
||||||
|
filters.party_type = 'Customer'
|
||||||
|
return filters
|
||||||
|
|
||||||
|
def get_customer_field_name(doctype):
|
||||||
|
if doctype == 'Quotation':
|
||||||
|
return 'party_name'
|
||||||
|
else:
|
||||||
|
return 'customer'
|
||||||
@@ -64,13 +64,20 @@ class EmployeeAdvance(Document):
|
|||||||
|
|
||||||
def update_claimed_amount(self):
|
def update_claimed_amount(self):
|
||||||
claimed_amount = frappe.db.sql("""
|
claimed_amount = frappe.db.sql("""
|
||||||
select sum(ifnull(allocated_amount, 0))
|
SELECT sum(ifnull(allocated_amount, 0))
|
||||||
from `tabExpense Claim Advance`
|
FROM `tabExpense Claim Advance` eca, `tabExpense Claim` ec
|
||||||
where employee_advance = %s and docstatus=1 and allocated_amount > 0
|
WHERE
|
||||||
|
eca.employee_advance = %s
|
||||||
|
AND ec.approval_status="Approved"
|
||||||
|
AND ec.name = eca.parent
|
||||||
|
AND ec.docstatus=1
|
||||||
|
AND eca.allocated_amount > 0
|
||||||
""", self.name)[0][0] or 0
|
""", self.name)[0][0] or 0
|
||||||
|
|
||||||
if claimed_amount:
|
|
||||||
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
|
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
|
||||||
|
self.reload()
|
||||||
|
self.set_status()
|
||||||
|
frappe.db.set_value("Employee Advance", self.name, "status", self.status)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_due_advance_amount(employee, posting_date):
|
def get_due_advance_amount(employee, posting_date):
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ frappe.ui.form.on("Expense Claim", {
|
|||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frm.trigger("toggle_fields");
|
frm.trigger("toggle_fields");
|
||||||
|
|
||||||
if(frm.doc.docstatus == 1) {
|
if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") {
|
||||||
frm.add_custom_button(__('Accounting Ledger'), function() {
|
frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
voucher_no: frm.doc.name,
|
voucher_no: frm.doc.name,
|
||||||
@@ -189,7 +189,7 @@ frappe.ui.form.on("Expense Claim", {
|
|||||||
}, __("View"));
|
}, __("View"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus===1
|
if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && cint(frm.doc.grand_total) > 0
|
||||||
&& (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount))
|
&& (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount))
|
||||||
&& frappe.model.can_create("Payment Entry")) {
|
&& frappe.model.can_create("Payment Entry")) {
|
||||||
frm.add_custom_button(__('Payment'),
|
frm.add_custom_button(__('Payment'),
|
||||||
|
|||||||
@@ -262,27 +262,44 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
var fields = [
|
const fields = [{
|
||||||
{fieldtype:'Table', fieldname: 'items',
|
label: 'Items',
|
||||||
|
fieldtype: 'Table',
|
||||||
|
fieldname: 'items',
|
||||||
description: __('Select BOM and Qty for Production'),
|
description: __('Select BOM and Qty for Production'),
|
||||||
fields: [
|
fields: [{
|
||||||
{fieldtype:'Read Only', fieldname:'item_code',
|
fieldtype: 'Read Only',
|
||||||
label: __('Item Code'), in_list_view:1},
|
fieldname: 'item_code',
|
||||||
{fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1,
|
label: __('Item Code'),
|
||||||
label: __('Select BOM'), in_list_view:1, get_query: function(doc) {
|
in_list_view: 1
|
||||||
return {filters: {item: doc.item_code}};
|
}, {
|
||||||
}},
|
fieldtype: 'Link',
|
||||||
{fieldtype:'Float', fieldname:'pending_qty', reqd: 1,
|
fieldname: 'bom',
|
||||||
label: __('Qty'), in_list_view:1},
|
options: 'BOM',
|
||||||
{fieldtype:'Data', fieldname:'sales_order_item', reqd: 1,
|
reqd: 1,
|
||||||
label: __('Sales Order Item'), hidden:1}
|
label: __('Select BOM'),
|
||||||
],
|
in_list_view: 1,
|
||||||
|
get_query: function (doc) {
|
||||||
|
return { filters: { item: doc.item_code } };
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
fieldtype: 'Float',
|
||||||
|
fieldname: 'pending_qty',
|
||||||
|
reqd: 1,
|
||||||
|
label: __('Qty'),
|
||||||
|
in_list_view: 1
|
||||||
|
}, {
|
||||||
|
fieldtype: 'Data',
|
||||||
|
fieldname: 'sales_order_item',
|
||||||
|
reqd: 1,
|
||||||
|
label: __('Sales Order Item'),
|
||||||
|
hidden: 1
|
||||||
|
}],
|
||||||
data: r.message,
|
data: r.message,
|
||||||
get_data: function() {
|
get_data: () => {
|
||||||
return r.message
|
return r.message
|
||||||
}
|
}
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
var d = new frappe.ui.Dialog({
|
var d = new frappe.ui.Dialog({
|
||||||
title: __('Select Items to Manufacture'),
|
title: __('Select Items to Manufacture'),
|
||||||
fields: fields,
|
fields: fields,
|
||||||
|
|||||||
@@ -202,13 +202,12 @@ def _get_cart_quotation(party=None):
|
|||||||
if quotation:
|
if quotation:
|
||||||
qdoc = frappe.get_doc("Quotation", quotation[0].name)
|
qdoc = frappe.get_doc("Quotation", quotation[0].name)
|
||||||
else:
|
else:
|
||||||
[company, price_list] = frappe.db.get_value("Shopping Cart Settings", None, ["company", "price_list"])
|
company = frappe.db.get_value("Shopping Cart Settings", None, ["company"])
|
||||||
qdoc = frappe.get_doc({
|
qdoc = frappe.get_doc({
|
||||||
"doctype": "Quotation",
|
"doctype": "Quotation",
|
||||||
"naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-",
|
"naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-",
|
||||||
"quotation_to": party.doctype,
|
"quotation_to": party.doctype,
|
||||||
"company": company,
|
"company": company,
|
||||||
"selling_price_list": price_list,
|
|
||||||
"order_type": "Shopping Cart",
|
"order_type": "Shopping Cart",
|
||||||
"status": "Draft",
|
"status": "Draft",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user