Merge branch 'version-12-hotfix' into import-italian-invoice

This commit is contained in:
Marica
2020-05-27 21:53:18 +05:30
committed by GitHub
37 changed files with 210 additions and 127 deletions

View File

@@ -605,10 +605,14 @@ def get_party_shipping_address(doctype, name):
else:
return ''
def get_partywise_advanced_payment_amount(party_type, posting_date = None, company=None):
def get_partywise_advanced_payment_amount(party_type, posting_date = None, future_payment=0, company=None):
cond = "1=1"
if posting_date:
cond = "posting_date <= '{0}'".format(posting_date)
if future_payment:
cond = "posting_date <= '{0}' OR DATE(creation) <= '{0}' """.format(posting_date)
else:
cond = "posting_date <= '{0}'".format(posting_date)
if company:
cond += "and company = '{0}'".format(company)

View File

@@ -135,12 +135,5 @@ frappe.query_reports["Accounts Payable"] = {
}
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Accounts Payable', 9);

View File

@@ -104,12 +104,5 @@ frappe.query_reports["Accounts Payable Summary"] = {
}
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Accounts Payable Summary', 9);

View File

@@ -199,12 +199,5 @@ frappe.query_reports["Accounts Receivable"] = {
}
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Accounts Receivable', 9);

View File

@@ -534,7 +534,7 @@ class ReceivablePayableReport(object):
def get_ageing_data(self, entry_date, row):
# [0-30, 30-60, 60-90, 90-120, 120-above]
row.range1 = row.range2 = row.range3 = row.range4 = range5 = 0.0
row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
if not (self.age_as_on and entry_date):
return
@@ -559,6 +559,14 @@ class ReceivablePayableReport(object):
conditions, values = self.prepare_conditions()
order_by = self.get_order_by_condition()
if self.filters.show_future_payments:
values.insert(2, self.filters.report_date)
date_condition = """AND (posting_date <= %s
OR (against_voucher IS NULL AND DATE(creation) <= %s))"""
else:
date_condition = "AND posting_date <=%s"
if self.filters.get(scrub(self.party_type)):
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
else:
@@ -574,9 +582,8 @@ class ReceivablePayableReport(object):
docstatus < 2
and party_type=%s
and (party is not null and party != '')
and posting_date <= %s
{1} {2}"""
.format(select_fields, conditions, order_by), values, as_dict=True)
{1} {2} {3}"""
.format(select_fields, date_condition, conditions, order_by), values, as_dict=True)
def get_sales_invoices_or_customers_based_on_sales_person(self):
if self.filters.get("sales_person"):

View File

@@ -111,7 +111,12 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
}
},
{
"fieldname":"show_future_payments",
"label": __("Show Future Payments"),
"fieldtype": "Check",
},
],
onload: function(report) {
@@ -122,11 +127,4 @@ frappe.query_reports["Accounts Receivable Summary"] = {
}
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Accounts Receivable Summary', 9);

View File

@@ -33,7 +33,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
self.get_party_total(args)
party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
self.filters.report_date, self.filters.company) or {}
self.filters.report_date, self.filters.show_future_payments, self.filters.company) or {}
for party, party_dict in iteritems(self.party_total):
if party_dict.outstanding == 0:

View File

@@ -111,7 +111,7 @@ def get_assets(filters):
0
end), 0) as depreciation_amount_during_the_period
from `tabAsset` a, `tabDepreciation Schedule` ds
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent and ifnull(ds.journal_entry, '') != ''
group by a.asset_category
union
SELECT a.asset_category,

View File

@@ -4,6 +4,8 @@
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
erpnext.utils.add_dimensions('Balance Sheet', 10);
frappe.query_reports["Balance Sheet"]["filters"].push({
"fieldname": "accumulated_values",
"label": __("Accumulated Values"),

View File

@@ -5,6 +5,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Cash Flow"] = $.extend({},
erpnext.financial_statements);
erpnext.utils.add_dimensions('Cash Flow', 10);
// The last item in the array is the definition for Presentation Currency
// filter. It won't be used in cash flow for now so we pop it. Please take
// of this if you are working here.

View File

@@ -160,12 +160,5 @@ frappe.query_reports["General Ledger"] = {
]
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('General Ledger', 15)

View File

@@ -6,6 +6,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Profit and Loss Statement"] = $.extend({},
erpnext.financial_statements);
erpnext.utils.add_dimensions('Profit and Loss Statement', 10);
frappe.query_reports["Profit and Loss Statement"]["filters"].push(
{
"fieldname": "project",

View File

@@ -56,11 +56,4 @@ frappe.query_reports["Purchase Register"] = {
]
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Purchase Register"].filters.splice(7, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Purchase Register', 7);

View File

@@ -68,12 +68,5 @@ frappe.query_reports["Sales Register"] = {
]
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Sales Register', 7);

View File

@@ -102,14 +102,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"initial_depth": 3
}
erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Trial Balance"].filters.splice(6, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
erpnext.utils.add_dimensions('Trial Balance', 6);
});

View File

@@ -155,7 +155,7 @@ def has_website_permission(doc, ptype, user, verbose=False):
return frappe.db.exists(doctype, get_customer_filter(doc, customers))
elif suppliers:
fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier'
return frappe.db.exists(doctype, filters={
return frappe.db.exists(doctype, {
'name': doc.name,
fieldname: ["in", suppliers]
})

View File

@@ -0,0 +1,17 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
from frappe import _
def get_data():
return {
'fieldname': 'assessment_plan',
'non_standard_fieldnames': {
},
'transactions': [
{
'label': _('Assessment'),
'items': ['Assessment Result']
}
]
}

View File

@@ -0,0 +1,25 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
from frappe import _
def get_data():
return {
'fieldname': 'course',
'non_standard_fieldnames': {
},
'transactions': [
{
'label': _('Course'),
'items': ['Course Enrollment', 'Course Schedule']
},
{
'label': _('Student'),
'items': ['Student Group']
},
{
'label': _('Assessment'),
'items': ['Assessment Plan']
},
]
}

View File

@@ -95,10 +95,10 @@ def create_sales_order(shopify_order, shopify_settings, company=None):
items = get_order_items(shopify_order.get("line_items"), shopify_settings)
if not items:
message = 'Following items are exists in order but relevant record not found in Product master'
message = 'Following items exists in the shopify order but relevant records were not found in the shopify Product master'
message += "\n" + ", ".join(product_not_exists)
make_shopify_log(status="Error", exception=e, rollback=True)
make_shopify_log(status="Error", exception=message, rollback=True)
return ''

View File

@@ -182,7 +182,8 @@ def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_l
company_abbr = frappe.db.get_value('Company', woocommerce_settings.company, 'abbr')
default_warehouse = _("Stores - {0}", sys_lang).format(company_abbr)
if not frappe.db.exists("Warehouse", default_warehouse):
if not frappe.db.exists("Warehouse", default_warehouse) \
and not woocommerce_settings.warehouse:
frappe.throw(_("Please set Warehouse in Woocommerce Settings"))
for item in order.get("line_items"):

View File

@@ -428,14 +428,23 @@ def get_leave_details(employee, date):
leave_allocation = {}
for d in allocation_records:
allocation = allocation_records.get(d, frappe._dict())
total_allocated_leaves = frappe.db.get_value('Leave Allocation', {
'from_date': ('<=', date),
'to_date': ('>=', date),
'leave_type': allocation.leave_type,
}, 'SUM(total_leaves_allocated)') or 0
remaining_leaves = get_leave_balance_on(employee, d, date, to_date = allocation.to_date,
consider_all_leaves_in_the_allocation_period=True)
end_date = allocation.to_date
leaves_taken = get_leaves_for_period(employee, d, allocation.from_date, end_date) * -1
leaves_pending = get_pending_leaves_for_period(employee, d, allocation.from_date, end_date)
leave_allocation[d] = {
"total_leaves": allocation.total_leaves_allocated,
"total_leaves": total_allocated_leaves,
"expired_leaves": total_allocated_leaves - (remaining_leaves + leaves_taken),
"leaves_taken": leaves_taken,
"pending_leaves": leaves_pending,
"remaining_leaves": remaining_leaves}

View File

@@ -4,11 +4,12 @@
<table class="table table-bordered small">
<thead>
<tr>
<th style="width: 20%">{{ __("Leave Type") }}</th>
<th style="width: 20%" class="text-right">{{ __("Total Allocated Leaves") }}</th>
<th style="width: 20%" class="text-right">{{ __("Used Leaves") }}</th>
<th style="width: 20%" class="text-right">{{ __("Pending Leaves") }}</th>
<th style="width: 20%" class="text-right">{{ __("Available Leaves") }}</th>
<th style="width: 16%">{{ __("Leave Type") }}</th>
<th style="width: 16%" class="text-right">{{ __("Total Allocated Leaves") }}</th>
<th style="width: 16%" class="text-right">{{ __("Expired Leaves") }}</th>
<th style="width: 16%" class="text-right">{{ __("Used Leaves") }}</th>
<th style="width: 16%" class="text-right">{{ __("Pending Leaves") }}</th>
<th style="width: 16%" class="text-right">{{ __("Available Leaves") }}</th>
</tr>
</thead>
@@ -17,6 +18,7 @@
<tr>
<td> {%= key %} </td>
<td class="text-right"> {%= value["total_leaves"] %} </td>
<td class="text-right"> {%= value["expired_leaves"] %} </td>
<td class="text-right"> {%= value["leaves_taken"] %} </td>
<td class="text-right"> {%= value["pending_leaves"] %} </td>
<td class="text-right"> {%= value["remaining_leaves"] %} </td>

View File

@@ -20,6 +20,9 @@ def get_template():
args = frappe.local.form_dict
if getdate(args.from_date) > getdate(args.to_date):
frappe.throw(_("To Date should be greater than From Date"))
w = UnicodeWriter()
w = add_header(w)

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
from frappe.utils import flt, add_days
from erpnext.hr.doctype.leave_application.leave_application \
import get_leave_balance_on, get_leaves_for_period
@@ -26,8 +26,8 @@ def get_columns(leave_types):
for leave_type in leave_types:
columns.append(_(leave_type) + " " + _("Opening") + ":Float:160")
columns.append(_(leave_type) + " " + _("Allocated") + ":Float:160")
columns.append(_(leave_type) + " " + _("Expired") + ":Float:160")
columns.append(_(leave_type) + " " + _("Taken") + ":Float:160")
columns.append(_(leave_type) + " " + _("Expired") + ":Float:160")
columns.append(_(leave_type) + " " + _("Balance") + ":Float:160")
return columns
@@ -84,7 +84,7 @@ def calculate_leaves_details(filters, leave_type, employee):
# removing expired leaves
leaves_taken = leaves_deducted - remove_expired_leave(ledger_entries)
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
opening = get_leave_balance_on(employee.name, leave_type, add_days(filters.from_date, -1))
new_allocation , expired_allocation = get_allocated_and_expired_leaves(ledger_entries, filters.from_date, filters.to_date)
@@ -94,7 +94,7 @@ def calculate_leaves_details(filters, leave_type, employee):
#Formula for calculating closing balance
closing = max(opening + new_allocation - (leaves_taken + expired_leaves), 0)
return [opening, new_allocation, expired_leaves, leaves_taken, closing]
return [opening, new_allocation, leaves_taken, expired_leaves, closing]
def remove_expired_leave(records):
@@ -113,7 +113,7 @@ def get_allocated_and_expired_leaves(records, from_date, to_date):
expired_leaves = 0
for record in records:
if record.to_date <= getdate(to_date) and record.leaves>0:
if record.to_date < getdate(to_date) and record.leaves>0:
expired_leaves += record.leaves
if record.from_date >= getdate(from_date) and record.leaves>0:

View File

@@ -45,16 +45,16 @@ def get_columns():
'fieldtype': 'Float',
'fieldname': 'new_allocation',
'width': 120,
}, {
'label': _('Expired Leaves'),
'fieldtype': 'Float',
'fieldname': 'expired_leaves',
'width': 120,
}, {
'label': _('Leaves Taken'),
'fieldtype': 'float',
'fieldname': 'leaves_taken',
'width': 120,
}, {
'label': _('Expired Leaves'),
'fieldtype': 'Float',
'fieldname': 'expired_leaves',
'width': 120,
}, {
'label': _('Closing Balance'),
'fieldtype': 'float',
@@ -96,8 +96,8 @@ def get_data(filters):
leave_details = calculate_leaves_details(filters, leave_type, employee)
row.opening_balance = flt(leave_details[0])
row.new_allocation = flt(leave_details[1])
row.expired_leaves = flt(leave_details[2])
row.leaves_taken = flt(leave_details[3])
row.leaves_taken = flt(leave_details[2])
row.expired_leaves = flt(leave_details[3])
row.closing_balance = flt(leave_details[4])
data.append(row)

View File

@@ -667,4 +667,5 @@ execute:frappe.delete_doc_if_exists("Page", "appointment-analytic")
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
erpnext.patches.v12_0.set_serial_no_status #2020-05-21
erpnext.patches.v12_0.update_price_list_currency_in_bom
erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
erpnext.patches.v12_0.update_uom_conversion_factor
erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions

View File

@@ -0,0 +1,11 @@
from __future__ import unicode_literals
import frappe, json
def execute():
from erpnext.setup.setup_wizard.operations.install_fixtures import add_uom_data
frappe.reload_doc("setup", "doctype", "UOM Conversion Factor")
frappe.reload_doc("setup", "doctype", "UOM")
frappe.reload_doc("stock", "doctype", "UOM Category")
add_uom_data()

View File

@@ -62,7 +62,7 @@ erpnext.financial_statements = {
}
};
function get_filters(){
function get_filters() {
let filters = [
{
"fieldname":"company",
@@ -129,15 +129,6 @@ function get_filters(){
}
]
erpnext.dimension_filters.forEach((dimension) => {
filters.push({
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
});
return filters;
}

View File

@@ -191,6 +191,23 @@ $.extend(erpnext.utils, {
})
},
add_dimensions: function(report_name, index) {
let filters = frappe.query_reports[report_name].filters;
erpnext.dimension_filters.forEach((dimension) => {
let found = filters.some(el => el.fieldname === dimension['fieldname']);
if (!found) {
filters.splice(index, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
"fieldtype": "Link",
"options": dimension["document_type"]
});
}
});
},
make_subscription: function(doctype, docname) {
frappe.call({
method: "frappe.automation.doctype.auto_repeat.auto_repeat.make_auto_repeat",

View File

@@ -1,6 +1,8 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from erpnext.controllers.taxes_and_totals import get_itemised_tax
from six import iteritems
def update_itemised_tax_data(doc):
if not doc.taxes: return
@@ -9,7 +11,14 @@ def update_itemised_tax_data(doc):
for row in doc.items:
tax_rate = 0.0
if itemised_tax.get(row.item_code):
item_tax_rate = frappe.parse_json(row.item_tax_rate)
# First check if tax rate is present
# If not then look up in item_wise_tax_detail
if item_tax_rate:
for account, rate in iteritems(item_tax_rate):
tax_rate += rate
elif itemised_tax.get(row.item_code):
tax_rate = sum([tax.get('tax_rate', 0) for d, tax in itemised_tax.get(row.item_code).items()])
row.tax_rate = flt(tax_rate, row.precision("tax_rate"))

View File

@@ -1571,5 +1571,19 @@
"to_uom": "Parts Per Million",
"abbr": "ppm",
"value": "10000"
},
{
"category": "Mass",
"from_uom": "Pound",
"to_uom": "Ounce",
"abbr": "oz",
"value": "16"
},
{
"category": "Mass",
"from_uom": "Gram",
"to_uom": "Ounce",
"abbr": "oz",
"value": "0.035274"
}
]

View File

@@ -335,13 +335,14 @@ def add_uom_data():
"category_name": _(d.get("category"))
}).insert(ignore_permissions=True)
uom_conversion = frappe.get_doc({
"doctype": "UOM Conversion Factor",
"category": _(d.get("category")),
"from_uom": _(d.get("from_uom")),
"to_uom": _(d.get("to_uom")),
"value": d.get("value")
}).insert(ignore_permissions=True)
if not frappe.db.exists("UOM Conversion Factor", {"from_uom": _(d.get("from_uom")), "to_uom": _(d.get("to_uom"))}):
uom_conversion = frappe.get_doc({
"doctype": "UOM Conversion Factor",
"category": _(d.get("category")),
"from_uom": _(d.get("from_uom")),
"to_uom": _(d.get("to_uom")),
"value": d.get("value")
}).insert(ignore_permissions=True)
def add_market_segments():
records = [

View File

@@ -319,7 +319,7 @@ def apply_cart_settings(party=None, quotation=None):
def set_price_list_and_rate(quotation, cart_settings):
"""set price list based on billing territory"""
_set_price_list(quotation, cart_settings)
_set_price_list(cart_settings, quotation)
# reset values
quotation.price_list_currency = quotation.currency = \
@@ -334,23 +334,28 @@ def set_price_list_and_rate(quotation, cart_settings):
# set it in cookies for using in product page
frappe.local.cookie_manager.set_cookie("selling_price_list", quotation.selling_price_list)
def _set_price_list(quotation, cart_settings):
def _set_price_list(cart_settings, quotation=None):
"""Set price list based on customer or shopping cart default"""
from erpnext.accounts.party import get_default_price_list
# check if customer price list exists
selling_price_list = None
if quotation.party_name:
selling_price_list = frappe.db.get_value('Customer', quotation.party_name, 'default_price_list')
if quotation and quotation.get("party_name"):
selling_price_list = frappe.db.get_value('Customer', quotation.get("party_name"), 'default_price_list')
# else check for territory based price list
if not selling_price_list:
selling_price_list = cart_settings.price_list
if not selling_price_list and quotation.party_name:
selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.party_name))
party_name = quotation.get("party_name") if quotation else get_party().get("name")
quotation.selling_price_list = selling_price_list
if not selling_price_list and party_name:
selling_price_list = get_default_price_list(frappe.get_doc("Customer", party_name))
if quotation:
quotation.selling_price_list = selling_price_list
return selling_price_list
def set_taxes(quotation, cart_settings):
"""set taxes based on billing territory"""

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from erpnext.shopping_cart.cart import _get_cart_quotation
from erpnext.shopping_cart.cart import _get_cart_quotation, _set_price_list
from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings \
import get_shopping_cart_settings, show_quantity_in_website
from erpnext.utilities.product import get_price, get_qty_in_stock, get_non_stock_item_status
@@ -21,9 +21,11 @@ def get_product_info_for_website(item_code, skip_quotation_creation=False):
if not skip_quotation_creation:
cart_quotation = _get_cart_quotation()
selling_price_list = cart_quotation.get("selling_price_list") if cart_quotation else _set_price_list(cart_settings, None)
price = get_price(
item_code,
cart_quotation.selling_price_list,
selling_price_list,
cart_settings.default_customer_group,
cart_settings.company
)
@@ -42,7 +44,7 @@ def get_product_info_for_website(item_code, skip_quotation_creation=False):
if product_info["price"]:
if frappe.session.user != "Guest":
item = cart_quotation.get({"item_code": item_code})
item = cart_quotation.get({"item_code": item_code}) if cart_quotation else None
if item:
product_info["qty"] = item[0].qty

View File

@@ -31,10 +31,16 @@ frappe.ui.form.on('Pick List', {
};
});
frm.set_query('item_code', 'locations', () => {
return erpnext.queries.item({ "is_stock_item": 1 });
});
frm.set_query('batch_no', 'locations', (frm, cdt, cdn) => {
const row = locals[cdt][cdn];
return {
query: 'erpnext.controllers.queries.get_batch_no',
filters: {
is_stock_item: 1
}
item_code: row.item_code,
warehouse: row.warehouse
},
};
});
},

View File

@@ -24,6 +24,9 @@ class PickList(Document):
for item in self.locations:
if not frappe.get_cached_value('Item', item.item_code, 'has_serial_no'):
continue
if not item.serial_no:
frappe.throw(_("Row #{0}: {1} does not have any available serial numbers in {2}".format(
frappe.bold(item.idx), frappe.bold(item.item_code), frappe.bold(item.warehouse))))
if len(item.serial_no.split('\n')) == item.picked_qty:
continue
frappe.throw(_('For item {0} at row {1}, count of serial numbers does not match with the picked quantity')

View File

@@ -180,7 +180,7 @@ def get_child_warehouses(warehouse):
lft, rgt = frappe.get_cached_value("Warehouse", warehouse, ["lft", "rgt"])
return frappe.db.sql_list("""select name from `tabWarehouse`
where lft >= %s and rgt =< %s""", (lft, rgt))
where lft >= %s and rgt <= %s""", (lft, rgt))
def get_warehouses_based_on_account(account, company=None):
warehouses = []