Merge branch 'v11-pre-release' into version-11
This commit is contained in:
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '11.1.67'
|
||||
__version__ = '11.1.68'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -174,6 +174,8 @@ def make_gl_entries(doc, credit_account, debit_account, against,
|
||||
# GL Entry for crediting the amount in the deferred expense
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
if amount == 0: return
|
||||
|
||||
gl_entries = []
|
||||
gl_entries.append(
|
||||
doc.get_gl_dict({
|
||||
|
||||
@@ -100,7 +100,10 @@ class Account(NestedSet):
|
||||
if ancestors:
|
||||
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
||||
return
|
||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||
|
||||
if not frappe.db.get_value("Account",
|
||||
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
|
||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||
else:
|
||||
descendants = get_descendants_of('Company', self.company)
|
||||
if not descendants: return
|
||||
@@ -114,21 +117,7 @@ class Account(NestedSet):
|
||||
|
||||
if not parent_acc_name_map: return
|
||||
|
||||
for company in descendants:
|
||||
if not parent_acc_name_map.get(company):
|
||||
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
|
||||
.format(company, parent_acc_name))
|
||||
|
||||
doc = frappe.copy_doc(self)
|
||||
doc.flags.ignore_root_company_validation = True
|
||||
doc.update({
|
||||
"company": company,
|
||||
"account_currency": None,
|
||||
"parent_account": parent_acc_name_map[company]
|
||||
})
|
||||
doc.save()
|
||||
frappe.msgprint(_("Account {0} is added in the child company {1}")
|
||||
.format(doc.name, company))
|
||||
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||
|
||||
def validate_group_or_ledger(self):
|
||||
if self.get("__islocal"):
|
||||
@@ -170,6 +159,49 @@ class Account(NestedSet):
|
||||
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
||||
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
|
||||
|
||||
def create_account_for_child_company(self, parent_acc_name_map, descendants, parent_acc_name):
|
||||
for company in descendants:
|
||||
if not parent_acc_name_map.get(company):
|
||||
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
|
||||
.format(company, parent_acc_name))
|
||||
|
||||
filters = {
|
||||
"account_name": self.account_name,
|
||||
"company": company
|
||||
}
|
||||
|
||||
if self.account_number:
|
||||
filters["account_number"] = self.account_number
|
||||
|
||||
child_account = frappe.db.get_value("Account", filters, 'name')
|
||||
|
||||
if not child_account:
|
||||
doc = frappe.copy_doc(self)
|
||||
doc.flags.ignore_root_company_validation = True
|
||||
doc.update({
|
||||
"company": company,
|
||||
# parent account's currency should be passed down to child account's curreny
|
||||
# if it is None, it picks it up from default company currency, which might be unintended
|
||||
"account_currency": self.account_currency,
|
||||
"parent_account": parent_acc_name_map[company]
|
||||
})
|
||||
|
||||
doc.save()
|
||||
frappe.msgprint(_("Account {0} is added in the child company {1}")
|
||||
.format(doc.name, company))
|
||||
elif child_account:
|
||||
# update the parent company's value in child companies
|
||||
doc = frappe.get_doc("Account", child_account)
|
||||
parent_value_changed = False
|
||||
for field in ['account_type', 'account_currency',
|
||||
'freeze_account', 'balance_must_be']:
|
||||
if doc.get(field) != self.get(field):
|
||||
parent_value_changed = True
|
||||
doc.set(field, self.get(field))
|
||||
|
||||
if parent_value_changed:
|
||||
doc.save()
|
||||
|
||||
def convert_group_to_ledger(self):
|
||||
if self.check_if_child_exists():
|
||||
throw(_("Account with child nodes cannot be converted to ledger"))
|
||||
|
||||
@@ -294,7 +294,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
() => {
|
||||
frm.set_party_account_based_on_party = false;
|
||||
if (r.message.bank_account) {
|
||||
frm.set_value("bank_account", r.message.bank_account);
|
||||
frm.set_value("party_bank_account", r.message.bank_account);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -1791,6 +1791,41 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Draft",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nDraft\nSubmitted\nCancelled",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@@ -2205,7 +2240,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-27 17:39:54.163016",
|
||||
"modified": "2019-11-06 15:15:45.223497",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
||||
@@ -60,6 +60,7 @@ class PaymentEntry(AccountsController):
|
||||
self.validate_duplicate_entry()
|
||||
self.validate_allocated_amount()
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
self.set_status()
|
||||
|
||||
def on_submit(self):
|
||||
self.setup_party_account_field()
|
||||
@@ -69,6 +70,7 @@ class PaymentEntry(AccountsController):
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.set_status()
|
||||
|
||||
|
||||
def on_cancel(self):
|
||||
@@ -78,6 +80,7 @@ class PaymentEntry(AccountsController):
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.delink_advance_entry_references()
|
||||
self.set_status()
|
||||
|
||||
def update_outstanding_amounts(self):
|
||||
self.set_missing_ref_details(force=True)
|
||||
@@ -274,6 +277,14 @@ class PaymentEntry(AccountsController):
|
||||
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
|
||||
.format(d.reference_name, dr_or_cr))
|
||||
|
||||
def set_status(self):
|
||||
if self.docstatus == 2:
|
||||
self.status = 'Cancelled'
|
||||
elif self.docstatus == 1:
|
||||
self.status = 'Submitted'
|
||||
else:
|
||||
self.status = 'Draft'
|
||||
|
||||
def set_amounts(self):
|
||||
self.set_amounts_in_company_currency()
|
||||
self.set_total_allocated_amount()
|
||||
|
||||
@@ -350,7 +350,7 @@ class SalesInvoice(SellingController):
|
||||
timesheet.calculate_percentage_billed()
|
||||
timesheet.flags.ignore_validate_update_after_submit = True
|
||||
timesheet.set_status()
|
||||
timesheet.save()
|
||||
timesheet.save(ignore_permissions=True)
|
||||
|
||||
def update_time_sheet_detail(self, timesheet, args, sales_invoice):
|
||||
for data in timesheet.time_logs:
|
||||
@@ -992,10 +992,8 @@ class SalesInvoice(SellingController):
|
||||
continue
|
||||
|
||||
for serial_no in item.serial_no.split("\n"):
|
||||
if serial_no and frappe.db.exists('Serial No', serial_no):
|
||||
sno = frappe.get_doc('Serial No', serial_no)
|
||||
sno.sales_invoice = invoice
|
||||
sno.db_update()
|
||||
if serial_no and frappe.db.get_value('Serial No', serial_no, 'item_code') == item.item_code:
|
||||
frappe.db.set_value('Serial No', serial_no, 'sales_invoice', invoice)
|
||||
|
||||
def validate_serial_numbers(self):
|
||||
"""
|
||||
@@ -1041,8 +1039,9 @@ class SalesInvoice(SellingController):
|
||||
continue
|
||||
|
||||
for serial_no in item.serial_no.split("\n"):
|
||||
sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice")
|
||||
if sales_invoice and self.name != sales_invoice:
|
||||
sales_invoice, item_code = frappe.db.get_value("Serial No", serial_no,
|
||||
["sales_invoice", "item_code"])
|
||||
if sales_invoice and item_code == item.item_code and self.name != sales_invoice:
|
||||
sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
|
||||
if sales_invoice_company == self.company:
|
||||
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
|
||||
|
||||
@@ -187,7 +187,11 @@ class ReceivablePayableReport(object):
|
||||
self.data.append(row)
|
||||
|
||||
def set_invoice_details(self, row):
|
||||
row.update(self.invoice_details.get(row.voucher_no, {}))
|
||||
invoice_details = self.invoice_details.get(row.voucher_no, {})
|
||||
if row.due_date:
|
||||
invoice_details.pop("due_date", None)
|
||||
row.update(invoice_details)
|
||||
|
||||
if row.voucher_type == 'Sales Invoice':
|
||||
if self.filters.show_delivery_notes:
|
||||
self.set_delivery_notes(row)
|
||||
|
||||
@@ -36,6 +36,9 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
self.filters.report_date) or {}
|
||||
|
||||
for party, party_dict in iteritems(self.party_total):
|
||||
if party_dict.outstanding <= 0:
|
||||
continue
|
||||
|
||||
row = frappe._dict()
|
||||
|
||||
row.party = party
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Balance Sheet"] = erpnext.financial_statements;
|
||||
frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
|
||||
|
||||
frappe.query_reports["Balance Sheet"]["filters"].push({
|
||||
"fieldname": "accumulated_values",
|
||||
|
||||
@@ -70,6 +70,7 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
|
||||
if tax_acc not in income_accounts:
|
||||
tax_amount_precision = get_field_precision(frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), currency=company_currency) or 2
|
||||
tax_amount = flt(invoice_tax_map.get(inv.name, {}).get(tax_acc), tax_amount_precision)
|
||||
total_tax += tax_amount
|
||||
row.append(tax_amount)
|
||||
|
||||
# total tax, grand total, outstanding amount & rounded total
|
||||
|
||||
@@ -75,8 +75,7 @@ def get_data(filters):
|
||||
accumulate_values_into_parents(accounts, accounts_by_name)
|
||||
|
||||
data = prepare_data(accounts, filters, total_row, parent_children_map, company_currency)
|
||||
data = filter_out_zero_value_rows(data, parent_children_map,
|
||||
show_zero_values=filters.get("show_zero_values"))
|
||||
data = filter_out_zero_value_rows(data, parent_children_map, show_zero_values=filters.get("show_zero_values"))
|
||||
|
||||
return data
|
||||
|
||||
@@ -175,33 +174,11 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, filters,
|
||||
|
||||
d["closing_debit"] = d["opening_debit"] + d["debit"]
|
||||
d["closing_credit"] = d["opening_credit"] + d["credit"]
|
||||
total_row["debit"] += d["debit"]
|
||||
total_row["credit"] += d["credit"]
|
||||
|
||||
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
|
||||
d["opening_debit"] -= d["opening_credit"]
|
||||
d["closing_debit"] -= d["closing_credit"]
|
||||
prepare_opening_closing(d)
|
||||
|
||||
# For opening
|
||||
check_opening_closing_has_negative_value(d, "opening_debit", "opening_credit")
|
||||
|
||||
# For closing
|
||||
check_opening_closing_has_negative_value(d, "closing_debit", "closing_credit")
|
||||
|
||||
if d["root_type"] == "Liability" or d["root_type"] == "Income":
|
||||
d["opening_credit"] -= d["opening_debit"]
|
||||
d["closing_credit"] -= d["closing_debit"]
|
||||
|
||||
# For opening
|
||||
check_opening_closing_has_negative_value(d, "opening_credit", "opening_debit")
|
||||
|
||||
# For closing
|
||||
check_opening_closing_has_negative_value(d, "closing_credit", "closing_debit")
|
||||
|
||||
total_row["opening_debit"] += d["opening_debit"]
|
||||
total_row["closing_debit"] += d["closing_debit"]
|
||||
total_row["opening_credit"] += d["opening_credit"]
|
||||
total_row["closing_credit"] += d["closing_credit"]
|
||||
for field in value_fields:
|
||||
total_row[field] += d[field]
|
||||
|
||||
return total_row
|
||||
|
||||
@@ -215,6 +192,10 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr
|
||||
data = []
|
||||
|
||||
for d in accounts:
|
||||
# Prepare opening closing for group account
|
||||
if parent_children_map.get(d.account):
|
||||
prepare_opening_closing(d)
|
||||
|
||||
has_value = False
|
||||
row = {
|
||||
"account": d.name,
|
||||
@@ -301,11 +282,16 @@ def get_columns():
|
||||
}
|
||||
]
|
||||
|
||||
def check_opening_closing_has_negative_value(d, dr_or_cr, switch_to_column):
|
||||
# If opening debit has negetive value then move it to opening credit and vice versa.
|
||||
def prepare_opening_closing(row):
|
||||
dr_or_cr = "debit" if row["root_type"] in ["Asset", "Equity", "Expense"] else "credit"
|
||||
reverse_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
||||
|
||||
if d[dr_or_cr] < 0:
|
||||
d[switch_to_column] = abs(d[dr_or_cr])
|
||||
d[dr_or_cr] = 0.0
|
||||
else:
|
||||
d[switch_to_column] = 0.0
|
||||
for col_type in ["opening", "closing"]:
|
||||
valid_col = col_type + "_" + dr_or_cr
|
||||
reverse_col = col_type + "_" + reverse_dr_or_cr
|
||||
row[valid_col] -= row[reverse_col]
|
||||
if row[valid_col] < 0:
|
||||
row[reverse_col] = abs(row[valid_col])
|
||||
row[valid_col] = 0.0
|
||||
else:
|
||||
row[reverse_col] = 0.0
|
||||
@@ -1097,6 +1097,8 @@ def get_supplier_block_status(party_name):
|
||||
@frappe.whitelist()
|
||||
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
|
||||
data = json.loads(trans_items)
|
||||
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
|
||||
|
||||
for d in data:
|
||||
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
|
||||
|
||||
@@ -1118,18 +1120,22 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
|
||||
# if rate is greater than price_list_rate, set margin
|
||||
# or set discount
|
||||
child_item.discount_percentage = 0
|
||||
child_item.margin_type = "Amount"
|
||||
child_item.margin_rate_or_amount = flt(child_item.rate - child_item.price_list_rate,
|
||||
child_item.precision("margin_rate_or_amount"))
|
||||
child_item.rate_with_margin = child_item.rate
|
||||
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = "Amount"
|
||||
child_item.margin_rate_or_amount = flt(child_item.rate - child_item.price_list_rate,
|
||||
child_item.precision("margin_rate_or_amount"))
|
||||
child_item.rate_with_margin = child_item.rate
|
||||
else:
|
||||
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.discount_amount = flt(
|
||||
child_item.price_list_rate) - flt(child_item.rate)
|
||||
child_item.margin_type = ""
|
||||
child_item.margin_rate_or_amount = 0
|
||||
child_item.rate_with_margin = 0
|
||||
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = ""
|
||||
child_item.margin_rate_or_amount = 0
|
||||
child_item.rate_with_margin = 0
|
||||
|
||||
child_item.flags.ignore_validate_update_after_submit = True
|
||||
child_item.save()
|
||||
|
||||
@@ -152,6 +152,20 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
|
||||
conditions = []
|
||||
|
||||
#Get searchfields from meta and use in Item Link field query
|
||||
meta = frappe.get_meta("Item", cached=True)
|
||||
searchfields = meta.get_search_fields()
|
||||
|
||||
if "description" in searchfields:
|
||||
searchfields.remove("description")
|
||||
|
||||
columns = [field for field in searchfields if not field in ["name", "item_group", "description"]]
|
||||
columns = ", ".join(columns)
|
||||
|
||||
searchfields = searchfields + [field for field in[searchfield or "name", "item_code", "item_group", "item_name"]
|
||||
if not field in searchfields]
|
||||
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||
|
||||
description_cond = ''
|
||||
if frappe.db.count('Item', cache=True) < 50000:
|
||||
# scan description only if items are less than 50000
|
||||
@@ -162,17 +176,14 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
|
||||
tabItem.item_group,
|
||||
if(length(tabItem.description) > 40, \
|
||||
concat(substr(tabItem.description, 1, 40), "..."), description) as decription
|
||||
concat(substr(tabItem.description, 1, 40), "..."), description) as description,
|
||||
{columns}
|
||||
from tabItem
|
||||
where tabItem.docstatus < 2
|
||||
and tabItem.has_variants=0
|
||||
and tabItem.disabled=0
|
||||
and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
|
||||
and (tabItem.`{key}` LIKE %(txt)s
|
||||
or tabItem.item_code LIKE %(txt)s
|
||||
or tabItem.item_group LIKE %(txt)s
|
||||
or tabItem.item_name LIKE %(txt)s
|
||||
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
|
||||
and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
|
||||
{description_cond})
|
||||
{fcond} {mcond}
|
||||
order by
|
||||
@@ -182,6 +193,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
name, item_name
|
||||
limit %(start)s, %(page_len)s """.format(
|
||||
key=searchfield,
|
||||
columns=columns,
|
||||
scond=searchfields,
|
||||
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
|
||||
mcond=get_match_cond(doctype).replace('%', '%%'),
|
||||
description_cond = description_cond),
|
||||
@@ -280,22 +293,31 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
"page_len": page_len
|
||||
}
|
||||
|
||||
having_clause = "having sum(sle.actual_qty) > 0"
|
||||
if filters.get("is_return"):
|
||||
having_clause = ""
|
||||
|
||||
if args.get('warehouse'):
|
||||
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||
from `tabStock Ledger Entry` sle
|
||||
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
|
||||
where
|
||||
batch.disabled = 0
|
||||
and sle.item_code = %(item_code)s
|
||||
and sle.warehouse = %(warehouse)s
|
||||
and (sle.batch_no like %(txt)s
|
||||
or batch.manufacturing_date like %(txt)s)
|
||||
and batch.docstatus < 2
|
||||
{0}
|
||||
{match_conditions}
|
||||
group by batch_no having sum(sle.actual_qty) > 0
|
||||
order by batch.expiry_date, sle.batch_no desc
|
||||
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
|
||||
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
||||
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||
from `tabStock Ledger Entry` sle
|
||||
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
|
||||
where
|
||||
batch.disabled = 0
|
||||
and sle.item_code = %(item_code)s
|
||||
and sle.warehouse = %(warehouse)s
|
||||
and (sle.batch_no like %(txt)s
|
||||
or batch.manufacturing_date like %(txt)s)
|
||||
and batch.docstatus < 2
|
||||
{cond}
|
||||
{match_conditions}
|
||||
group by batch_no {having_clause}
|
||||
order by batch.expiry_date, sle.batch_no desc
|
||||
limit %(start)s, %(page_len)s""".format(
|
||||
cond=cond,
|
||||
match_conditions=get_match_cond(doctype),
|
||||
having_clause = having_clause
|
||||
), args)
|
||||
|
||||
return batch_nos
|
||||
else:
|
||||
|
||||
@@ -1468,7 +1468,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-05-17 19:03:32.740910",
|
||||
"modified": "2019-10-22 11:11:32.740910",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Opportunity",
|
||||
|
||||
@@ -233,7 +233,6 @@ scheduler_events = {
|
||||
],
|
||||
"daily": [
|
||||
"erpnext.stock.reorder_item.reorder_item",
|
||||
"erpnext.setup.doctype.email_digest.email_digest.send",
|
||||
"erpnext.support.doctype.issue.issue.auto_close_tickets",
|
||||
"erpnext.crm.doctype.opportunity.opportunity.auto_close_opportunity",
|
||||
"erpnext.controllers.accounts_controller.update_invoice_status",
|
||||
@@ -252,6 +251,7 @@ scheduler_events = {
|
||||
"erpnext.projects.doctype.project.project.send_project_status_email_to_users"
|
||||
],
|
||||
"daily_long": [
|
||||
"erpnext.setup.doctype.email_digest.email_digest.send",
|
||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
||||
],
|
||||
"monthly_long": [
|
||||
|
||||
@@ -157,10 +157,11 @@ class Employee(NestedSet):
|
||||
def validate_status(self):
|
||||
if self.status == 'Left':
|
||||
reports_to = frappe.db.get_all('Employee',
|
||||
filters={'reports_to': self.name}
|
||||
filters={'reports_to': self.name, 'status': "Active"},
|
||||
fields = ['name','employee_name']
|
||||
)
|
||||
if reports_to:
|
||||
link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name) for employee in reports_to]
|
||||
link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name, label=employee.employee_name) for employee in reports_to]
|
||||
throw(_("Employee status cannot be set to 'Left' as following employees are currently reporting to this employee: ")
|
||||
+ ', '.join(link_to_employees), EmployeeLeftValidationError)
|
||||
if not self.relieving_date:
|
||||
|
||||
@@ -38,9 +38,11 @@ class BOM(WebsiteGenerator):
|
||||
names = [d[-1][1:] for d in filter(lambda x: len(x) > 1 and x[-1], names)]
|
||||
|
||||
# split by (-) if cancelled
|
||||
names = [cint(name.split('-')[-1]) for name in names]
|
||||
|
||||
idx = max(names) + 1
|
||||
if names:
|
||||
names = [cint(name.split('-')[-1]) for name in names]
|
||||
idx = max(names) + 1
|
||||
else:
|
||||
idx = 1
|
||||
else:
|
||||
idx = 1
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@@ -14,10 +15,12 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -41,14 +44,17 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -72,14 +78,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -103,14 +112,17 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -132,14 +144,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "quantity",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -162,14 +177,51 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -192,14 +244,86 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Item Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "300px",
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "min_order_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -222,14 +346,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -252,14 +379,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -283,14 +413,17 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "requested_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -313,6 +446,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@@ -326,7 +460,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-02-15 13:08:30.535963",
|
||||
"modified": "2019-11-08 14:59:58.805613",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Material Request Plan Item",
|
||||
@@ -340,5 +474,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@ frappe.ui.form.on('Production Plan', {
|
||||
item.quantity = d.quantity;
|
||||
item.sales_order = d.sales_order;
|
||||
item.warehouse = d.warehouse;
|
||||
item.description = d.description;
|
||||
item.uom = d.uom;
|
||||
});
|
||||
}
|
||||
refresh_field('mr_items');
|
||||
|
||||
@@ -472,7 +472,9 @@ def get_material_request_items(row, sales_order, company, ignore_existing_ordere
|
||||
or row.get('default_warehouse') or item_group_defaults.get("default_warehouse"),
|
||||
'actual_qty': actual_qty,
|
||||
'min_order_qty': row['min_order_qty'],
|
||||
'sales_order': sales_order
|
||||
'sales_order': sales_order,
|
||||
'description': row.get("description"),
|
||||
'uom': row.get("purchase_uom") or row.get("stock_uom")
|
||||
}
|
||||
|
||||
def get_sales_orders(self):
|
||||
|
||||
@@ -318,7 +318,7 @@ frappe.ui.form.on("Work Order", {
|
||||
},
|
||||
|
||||
project: function(frm) {
|
||||
if(!erpnext.in_production_item_onchange) {
|
||||
if(!erpnext.in_production_item_onchange && !frm.doc.bom_no) {
|
||||
frm.trigger("production_item");
|
||||
}
|
||||
},
|
||||
|
||||
@@ -607,3 +607,4 @@ erpnext.patches.v11_1.set_quotation_status
|
||||
erpnext.patches.v11_1.update_default_supplier_in_item_defaults
|
||||
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
|
||||
erpnext.patches.v11_1.set_produced_qty_field_in_sales_order_for_work_order
|
||||
erpnext.patches.v11_1.set_payment_entry_status
|
||||
9
erpnext/patches/v11_1/set_payment_entry_status.py
Normal file
9
erpnext/patches/v11_1/set_payment_entry_status.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doctype("Payment Entry")
|
||||
frappe.db.sql("""update `tabPayment Entry` set status = CASE
|
||||
WHEN docstatus = 1 THEN 'Submitted'
|
||||
WHEN docstatus = 2 THEN 'Cancelled'
|
||||
ELSE 'Draft'
|
||||
END;""")
|
||||
@@ -713,7 +713,7 @@
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "depends_on_tasks",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -1433,4 +1433,4 @@
|
||||
"track_changes": 0,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate
|
||||
from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate, today
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
|
||||
|
||||
@@ -201,6 +201,9 @@ def set_multiple_status(names, status):
|
||||
def set_tasks_as_overdue():
|
||||
tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Closed']]})
|
||||
for task in tasks:
|
||||
if frappe.db.get_value("Task", task.name, "status") in 'Pending Review':
|
||||
if getdate(frappe.db.get_value("Task", task.name, "review_date")) < getdate(today()):
|
||||
continue
|
||||
frappe.get_doc("Task", task.name).update_status()
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -1422,6 +1422,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
'item_code': item.item_code,
|
||||
'posting_date': me.frm.doc.posting_date || frappe.datetime.nowdate(),
|
||||
}
|
||||
|
||||
if (doc.is_return) {
|
||||
filters["is_return"] = 1;
|
||||
}
|
||||
|
||||
if (item.warehouse) filters["warehouse"] = item.warehouse;
|
||||
|
||||
return {
|
||||
|
||||
@@ -60,8 +60,8 @@ def validate_gstin_check_digit(gstin, label='GSTIN'):
|
||||
total += digit
|
||||
factor = 2 if factor == 1 else 1
|
||||
if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
|
||||
frappe.throw(_("Invalid {0}! The check digit validation has failed. " +
|
||||
"Please ensure you've typed the {0} correctly.".format(label)))
|
||||
frappe.throw(_("""Invalid {0}! The check digit validation has failed.
|
||||
Please ensure you've typed the {0} correctly.""".format(label)))
|
||||
|
||||
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
||||
if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
|
||||
|
||||
@@ -142,7 +142,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
|
||||
// delivery note
|
||||
if(flt(doc.per_delivered, 6) < 100 && allow_delivery) {
|
||||
this.frm.add_custom_button(__('Delivery'),
|
||||
this.frm.add_custom_button(__('Delivery Note'),
|
||||
function() { me.make_delivery_note_based_on_delivery_date(); }, __("Make"));
|
||||
|
||||
if(["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1){
|
||||
|
||||
@@ -645,12 +645,15 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
||||
|
||||
if source_parent.project:
|
||||
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
|
||||
if not target.cost_center and target.item_code:
|
||||
if target.item_code:
|
||||
item = get_item_defaults(target.item_code, source_parent.company)
|
||||
item_group = get_item_group_defaults(target.item_code, source_parent.company)
|
||||
target.cost_center = item.get("selling_cost_center") \
|
||||
cost_center = item.get("selling_cost_center") \
|
||||
or item_group.get("selling_cost_center")
|
||||
|
||||
if cost_center:
|
||||
target.cost_center = cost_center
|
||||
|
||||
doclist = get_mapped_doc("Sales Order", source_name, {
|
||||
"Sales Order": {
|
||||
"doctype": "Sales Invoice",
|
||||
|
||||
@@ -454,9 +454,8 @@ def get_applicable_shipping_rules(party=None, quotation=None):
|
||||
shipping_rules = get_shipping_rules(quotation)
|
||||
|
||||
if shipping_rules:
|
||||
rule_label_map = frappe.db.get_values("Shipping Rule", shipping_rules, "label")
|
||||
# we need this in sorted order as per the position of the rule in the settings page
|
||||
return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
|
||||
return [[rule, rule] for rule in shipping_rules]
|
||||
|
||||
def get_shipping_rules(quotation=None, cart_settings=None):
|
||||
if not quotation:
|
||||
|
||||
@@ -6,9 +6,9 @@ frappe.listview_settings['Delivery Note'] = {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
} else if (doc.status === "Closed") {
|
||||
return [__("Closed"), "green", "status,=,Closed"];
|
||||
} else if (doc.grand_total !== 0 && flt(doc.per_billed, 2) < 100) {
|
||||
} else if (flt(doc.per_billed, 2) < 100) {
|
||||
return [__("To Bill"), "orange", "per_billed,<,100"];
|
||||
} else if (doc.grand_total === 0 || flt(doc.per_billed, 2) == 100) {
|
||||
} else if (flt(doc.per_billed, 2) == 100) {
|
||||
return [__("Completed"), "green", "per_billed,=,100"];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7,7 +7,6 @@ from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe.utils import cstr, flt
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PackedItem(Document):
|
||||
@@ -31,8 +30,11 @@ def get_bin_qty(item, warehouse):
|
||||
return det and det[0] or frappe._dict()
|
||||
|
||||
def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
|
||||
if doc.amended_from:
|
||||
old_packed_items_map = get_old_packed_item_details(doc.packed_items)
|
||||
else:
|
||||
old_packed_items_map = False
|
||||
item = get_packing_item_details(packing_item_code, doc.company)
|
||||
|
||||
# check if exists
|
||||
exists = 0
|
||||
for d in doc.get("packed_items"):
|
||||
@@ -52,11 +54,10 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
|
||||
pi.uom = item.stock_uom
|
||||
pi.qty = flt(qty)
|
||||
pi.description = description
|
||||
if not pi.warehouse:
|
||||
if not pi.warehouse and not doc.amended_from:
|
||||
pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos')
|
||||
or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse)
|
||||
|
||||
if not pi.batch_no:
|
||||
if not pi.batch_no and not doc.amended_from:
|
||||
pi.batch_no = cstr(main_item_row.get("batch_no"))
|
||||
if not pi.target_warehouse:
|
||||
pi.target_warehouse = main_item_row.get("target_warehouse")
|
||||
@@ -64,9 +65,13 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
|
||||
pi.actual_qty = flt(bin.get("actual_qty"))
|
||||
pi.projected_qty = flt(bin.get("projected_qty"))
|
||||
|
||||
if old_packed_items_map:
|
||||
pi.batch_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].batch_no
|
||||
pi.serial_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].serial_no
|
||||
pi.warehouse = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].warehouse
|
||||
|
||||
def make_packing_list(doc):
|
||||
"""make packing list for Product Bundle item"""
|
||||
|
||||
if doc.get("_action") and doc._action == "update_after_submit": return
|
||||
|
||||
parent_items = []
|
||||
@@ -108,8 +113,14 @@ def get_items_from_product_bundle(args):
|
||||
"qty": flt(args["quantity"]) * flt(item.qty)
|
||||
})
|
||||
items.append(get_item_details(args))
|
||||
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
|
||||
frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
|
||||
|
||||
def get_old_packed_item_details(old_packed_items):
|
||||
old_packed_items_map = {}
|
||||
for items in old_packed_items:
|
||||
old_packed_items_map.setdefault((items.item_code ,items.parent_item), []).append(items.as_dict())
|
||||
return old_packed_items_map
|
||||
@@ -227,7 +227,9 @@ class StockEntry(StockController):
|
||||
|
||||
for d in self.get("items"):
|
||||
if not d.expense_account:
|
||||
frappe.throw(_("Please enter Difference Account"))
|
||||
frappe.throw(_("Please enter <b>Difference Account</b> or set default <b>Stock Adjustment Account</b> for company {0}")
|
||||
.format(frappe.bold(self.company)))
|
||||
|
||||
elif self.is_opening == "Yes" and frappe.db.get_value("Account", d.expense_account, "report_type") == "Profit and Loss":
|
||||
frappe.throw(_("Difference Account must be a Asset/Liability type account, since this Stock Entry is an Opening Entry"), OpeningEntryAccountError)
|
||||
|
||||
|
||||
@@ -19,10 +19,26 @@ def execute(filters=None):
|
||||
if opening_row:
|
||||
data.append(opening_row)
|
||||
|
||||
actual_qty = stock_value = 0
|
||||
|
||||
for sle in sl_entries:
|
||||
item_detail = item_details[sle.item_code]
|
||||
|
||||
sle.update(item_detail)
|
||||
|
||||
if filters.get("batch_no"):
|
||||
actual_qty += sle.actual_qty
|
||||
stock_value += sle.stock_value_difference
|
||||
|
||||
if sle.voucher_type == 'Stock Reconciliation':
|
||||
actual_qty = sle.qty_after_transaction
|
||||
stock_value = sle.stock_value
|
||||
|
||||
sle.update({
|
||||
"qty_after_transaction": actual_qty,
|
||||
"stock_value": stock_value
|
||||
})
|
||||
|
||||
data.append(sle)
|
||||
|
||||
if include_uom:
|
||||
@@ -67,7 +83,7 @@ def get_stock_ledger_entries(filters, items):
|
||||
|
||||
return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date,
|
||||
item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate,
|
||||
stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project
|
||||
stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project, stock_value_difference
|
||||
from `tabStock Ledger Entry` sle
|
||||
where company = %(company)s and
|
||||
posting_date between %(from_date)s and %(to_date)s
|
||||
|
||||
Reference in New Issue
Block a user