mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-05 05:09:11 +00:00
Merge branch 'version-11-hotfix' into v11-work-order-bugs
This commit is contained in:
@@ -174,6 +174,8 @@ def make_gl_entries(doc, credit_account, debit_account, against,
|
|||||||
# GL Entry for crediting the amount in the deferred expense
|
# GL Entry for crediting the amount in the deferred expense
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries
|
from erpnext.accounts.general_ledger import make_gl_entries
|
||||||
|
|
||||||
|
if amount == 0: return
|
||||||
|
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
doc.get_gl_dict({
|
doc.get_gl_dict({
|
||||||
|
|||||||
@@ -100,6 +100,9 @@ class Account(NestedSet):
|
|||||||
if ancestors:
|
if ancestors:
|
||||||
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
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]))
|
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||||
else:
|
else:
|
||||||
descendants = get_descendants_of('Company', self.company)
|
descendants = get_descendants_of('Company', self.company)
|
||||||
@@ -114,21 +117,7 @@ class Account(NestedSet):
|
|||||||
|
|
||||||
if not parent_acc_name_map: return
|
if not parent_acc_name_map: return
|
||||||
|
|
||||||
for company in descendants:
|
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||||
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))
|
|
||||||
|
|
||||||
def validate_group_or_ledger(self):
|
def validate_group_or_ledger(self):
|
||||||
if self.get("__islocal"):
|
if self.get("__islocal"):
|
||||||
@@ -170,6 +159,49 @@ class Account(NestedSet):
|
|||||||
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
||||||
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
|
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):
|
def convert_group_to_ledger(self):
|
||||||
if self.check_if_child_exists():
|
if self.check_if_child_exists():
|
||||||
throw(_("Account with child nodes cannot be converted to ledger"))
|
throw(_("Account with child nodes cannot be converted to ledger"))
|
||||||
|
|||||||
@@ -1791,6 +1791,41 @@
|
|||||||
"translatable": 0,
|
"translatable": 0,
|
||||||
"unique": 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_bulk_edit": 0,
|
||||||
"allow_in_quick_entry": 0,
|
"allow_in_quick_entry": 0,
|
||||||
@@ -2205,7 +2240,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2019-03-27 17:39:54.163016",
|
"modified": "2019-11-06 15:15:45.223497",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Entry",
|
"name": "Payment Entry",
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.validate_duplicate_entry()
|
self.validate_duplicate_entry()
|
||||||
self.validate_allocated_amount()
|
self.validate_allocated_amount()
|
||||||
self.ensure_supplier_is_not_blocked()
|
self.ensure_supplier_is_not_blocked()
|
||||||
|
self.set_status()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.setup_party_account_field()
|
self.setup_party_account_field()
|
||||||
@@ -69,6 +70,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.update_outstanding_amounts()
|
self.update_outstanding_amounts()
|
||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
self.update_expense_claim()
|
self.update_expense_claim()
|
||||||
|
self.set_status()
|
||||||
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
@@ -78,6 +80,7 @@ class PaymentEntry(AccountsController):
|
|||||||
self.update_advance_paid()
|
self.update_advance_paid()
|
||||||
self.update_expense_claim()
|
self.update_expense_claim()
|
||||||
self.delink_advance_entry_references()
|
self.delink_advance_entry_references()
|
||||||
|
self.set_status()
|
||||||
|
|
||||||
def update_outstanding_amounts(self):
|
def update_outstanding_amounts(self):
|
||||||
self.set_missing_ref_details(force=True)
|
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")
|
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
|
||||||
.format(d.reference_name, dr_or_cr))
|
.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):
|
def set_amounts(self):
|
||||||
self.set_amounts_in_company_currency()
|
self.set_amounts_in_company_currency()
|
||||||
self.set_total_allocated_amount()
|
self.set_total_allocated_amount()
|
||||||
|
|||||||
@@ -350,7 +350,7 @@ class SalesInvoice(SellingController):
|
|||||||
timesheet.calculate_percentage_billed()
|
timesheet.calculate_percentage_billed()
|
||||||
timesheet.flags.ignore_validate_update_after_submit = True
|
timesheet.flags.ignore_validate_update_after_submit = True
|
||||||
timesheet.set_status()
|
timesheet.set_status()
|
||||||
timesheet.save()
|
timesheet.save(ignore_permissions=True)
|
||||||
|
|
||||||
def update_time_sheet_detail(self, timesheet, args, sales_invoice):
|
def update_time_sheet_detail(self, timesheet, args, sales_invoice):
|
||||||
for data in timesheet.time_logs:
|
for data in timesheet.time_logs:
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ def get_data(filters):
|
|||||||
accumulate_values_into_parents(accounts, accounts_by_name)
|
accumulate_values_into_parents(accounts, accounts_by_name)
|
||||||
|
|
||||||
data = prepare_data(accounts, filters, total_row, parent_children_map, company_currency)
|
data = prepare_data(accounts, filters, total_row, parent_children_map, company_currency)
|
||||||
data = filter_out_zero_value_rows(data, parent_children_map,
|
data = filter_out_zero_value_rows(data, parent_children_map, show_zero_values=filters.get("show_zero_values"))
|
||||||
show_zero_values=filters.get("show_zero_values"))
|
|
||||||
|
|
||||||
return data
|
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_debit"] = d["opening_debit"] + d["debit"]
|
||||||
d["closing_credit"] = d["opening_credit"] + d["credit"]
|
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":
|
prepare_opening_closing(d)
|
||||||
d["opening_debit"] -= d["opening_credit"]
|
|
||||||
d["closing_debit"] -= d["closing_credit"]
|
|
||||||
|
|
||||||
# For opening
|
for field in value_fields:
|
||||||
check_opening_closing_has_negative_value(d, "opening_debit", "opening_credit")
|
total_row[field] += d[field]
|
||||||
|
|
||||||
# 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"]
|
|
||||||
|
|
||||||
return total_row
|
return total_row
|
||||||
|
|
||||||
@@ -215,6 +192,10 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr
|
|||||||
data = []
|
data = []
|
||||||
|
|
||||||
for d in accounts:
|
for d in accounts:
|
||||||
|
# Prepare opening closing for group account
|
||||||
|
if parent_children_map.get(d.account):
|
||||||
|
prepare_opening_closing(d)
|
||||||
|
|
||||||
has_value = False
|
has_value = False
|
||||||
row = {
|
row = {
|
||||||
"account": d.name,
|
"account": d.name,
|
||||||
@@ -301,11 +282,16 @@ def get_columns():
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
def check_opening_closing_has_negative_value(d, dr_or_cr, switch_to_column):
|
def prepare_opening_closing(row):
|
||||||
# If opening debit has negetive value then move it to opening credit and vice versa.
|
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:
|
for col_type in ["opening", "closing"]:
|
||||||
d[switch_to_column] = abs(d[dr_or_cr])
|
valid_col = col_type + "_" + dr_or_cr
|
||||||
d[dr_or_cr] = 0.0
|
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:
|
else:
|
||||||
d[switch_to_column] = 0.0
|
row[reverse_col] = 0.0
|
||||||
@@ -157,10 +157,11 @@ class Employee(NestedSet):
|
|||||||
def validate_status(self):
|
def validate_status(self):
|
||||||
if self.status == 'Left':
|
if self.status == 'Left':
|
||||||
reports_to = frappe.db.get_all('Employee',
|
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:
|
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: ")
|
throw(_("Employee status cannot be set to 'Left' as following employees are currently reporting to this employee: ")
|
||||||
+ ', '.join(link_to_employees), EmployeeLeftValidationError)
|
+ ', '.join(link_to_employees), EmployeeLeftValidationError)
|
||||||
if not self.relieving_date:
|
if not self.relieving_date:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
@@ -14,10 +15,12 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -41,14 +44,17 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "item_name",
|
"fieldname": "item_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -72,14 +78,17 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "warehouse",
|
"fieldname": "warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -103,14 +112,17 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "column_break_4",
|
"fieldname": "column_break_4",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -132,14 +144,17 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "quantity",
|
"fieldname": "quantity",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -162,14 +177,51 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 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",
|
"fieldname": "actual_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -192,14 +244,86 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 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,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 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",
|
"fieldname": "min_order_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -222,14 +346,17 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "section_break_8",
|
"fieldname": "section_break_8",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -252,14 +379,17 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "sales_order",
|
"fieldname": "sales_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -283,14 +413,17 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"columns": 0,
|
"columns": 0,
|
||||||
|
"fetch_if_empty": 0,
|
||||||
"fieldname": "requested_qty",
|
"fieldname": "requested_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -313,6 +446,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -326,7 +460,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-02-15 13:08:30.535963",
|
"modified": "2019-11-08 14:59:58.805613",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Material Request Plan Item",
|
"name": "Material Request Plan Item",
|
||||||
@@ -340,5 +474,6 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"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.quantity = d.quantity;
|
||||||
item.sales_order = d.sales_order;
|
item.sales_order = d.sales_order;
|
||||||
item.warehouse = d.warehouse;
|
item.warehouse = d.warehouse;
|
||||||
|
item.description = d.description;
|
||||||
|
item.uom = d.uom;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
refresh_field('mr_items');
|
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"),
|
or row.get('default_warehouse') or item_group_defaults.get("default_warehouse"),
|
||||||
'actual_qty': actual_qty,
|
'actual_qty': actual_qty,
|
||||||
'min_order_qty': row['min_order_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):
|
def get_sales_orders(self):
|
||||||
|
|||||||
@@ -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.update_default_supplier_in_item_defaults
|
||||||
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
|
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_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;""")
|
||||||
@@ -60,8 +60,8 @@ def validate_gstin_check_digit(gstin, label='GSTIN'):
|
|||||||
total += digit
|
total += digit
|
||||||
factor = 2 if factor == 1 else 1
|
factor = 2 if factor == 1 else 1
|
||||||
if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
|
if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
|
||||||
frappe.throw(_("Invalid {0}! The check digit validation has failed. " +
|
frappe.throw(_("""Invalid {0}! The check digit validation has failed.
|
||||||
"Please ensure you've typed the {0} correctly.".format(label)))
|
Please ensure you've typed the {0} correctly.""".format(label)))
|
||||||
|
|
||||||
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
||||||
if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
|
if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
|
||||||
|
|||||||
@@ -454,9 +454,8 @@ def get_applicable_shipping_rules(party=None, quotation=None):
|
|||||||
shipping_rules = get_shipping_rules(quotation)
|
shipping_rules = get_shipping_rules(quotation)
|
||||||
|
|
||||||
if shipping_rules:
|
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
|
# 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):
|
def get_shipping_rules(quotation=None, cart_settings=None):
|
||||||
if not quotation:
|
if not quotation:
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ from __future__ import unicode_literals
|
|||||||
import frappe, json
|
import frappe, json
|
||||||
from frappe.utils import cstr, flt
|
from frappe.utils import cstr, flt
|
||||||
from erpnext.stock.get_item_details import get_item_details
|
from erpnext.stock.get_item_details import get_item_details
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class PackedItem(Document):
|
class PackedItem(Document):
|
||||||
@@ -31,8 +30,11 @@ def get_bin_qty(item, warehouse):
|
|||||||
return det and det[0] or frappe._dict()
|
return det and det[0] or frappe._dict()
|
||||||
|
|
||||||
def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
|
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)
|
item = get_packing_item_details(packing_item_code, doc.company)
|
||||||
|
|
||||||
# check if exists
|
# check if exists
|
||||||
exists = 0
|
exists = 0
|
||||||
for d in doc.get("packed_items"):
|
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.uom = item.stock_uom
|
||||||
pi.qty = flt(qty)
|
pi.qty = flt(qty)
|
||||||
pi.description = description
|
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')
|
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)
|
or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse)
|
||||||
|
if not pi.batch_no and not doc.amended_from:
|
||||||
if not pi.batch_no:
|
|
||||||
pi.batch_no = cstr(main_item_row.get("batch_no"))
|
pi.batch_no = cstr(main_item_row.get("batch_no"))
|
||||||
if not pi.target_warehouse:
|
if not pi.target_warehouse:
|
||||||
pi.target_warehouse = main_item_row.get("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.actual_qty = flt(bin.get("actual_qty"))
|
||||||
pi.projected_qty = flt(bin.get("projected_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):
|
def make_packing_list(doc):
|
||||||
"""make packing list for Product Bundle item"""
|
"""make packing list for Product Bundle item"""
|
||||||
|
|
||||||
if doc.get("_action") and doc._action == "update_after_submit": return
|
if doc.get("_action") and doc._action == "update_after_submit": return
|
||||||
|
|
||||||
parent_items = []
|
parent_items = []
|
||||||
@@ -113,3 +118,9 @@ def get_items_from_product_bundle(args):
|
|||||||
|
|
||||||
def on_doctype_update():
|
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
|
||||||
@@ -19,10 +19,26 @@ def execute(filters=None):
|
|||||||
if opening_row:
|
if opening_row:
|
||||||
data.append(opening_row)
|
data.append(opening_row)
|
||||||
|
|
||||||
|
actual_qty = stock_value = 0
|
||||||
|
|
||||||
for sle in sl_entries:
|
for sle in sl_entries:
|
||||||
item_detail = item_details[sle.item_code]
|
item_detail = item_details[sle.item_code]
|
||||||
|
|
||||||
sle.update(item_detail)
|
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)
|
data.append(sle)
|
||||||
|
|
||||||
if include_uom:
|
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,
|
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,
|
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
|
from `tabStock Ledger Entry` sle
|
||||||
where company = %(company)s and
|
where company = %(company)s and
|
||||||
posting_date between %(from_date)s and %(to_date)s
|
posting_date between %(from_date)s and %(to_date)s
|
||||||
|
|||||||
Reference in New Issue
Block a user