Merge pull request #16950 from hrwX/fix-issue-credit
Fix(Delivery Note): Fix issue credit note
diff --git a/README.md b/README.md
index 8c13e1e..b1979d0 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,6 @@
</p>
[![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext)
-[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
[![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 4870b19..e510e38 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '11.1.14'
+__version__ = '11.1.17'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index e638fc7..3afb4bc 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -2,9 +2,9 @@
import frappe
from frappe import _
-from frappe.utils import date_diff, add_months, today, getdate, add_days, flt
+from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day
from erpnext.accounts.utils import get_account_currency
-from erpnext.accounts.general_ledger import make_gl_entries
+from frappe.email import sendmail_to_system_managers
def validate_service_stop_date(doc):
''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
@@ -33,47 +33,49 @@
frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
def convert_deferred_expense_to_expense(start_date=None, end_date=None):
+ # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
+ if not start_date:
+ start_date = add_months(today(), -1)
+ if not end_date:
+ end_date = add_days(today(), -1)
+
# check for the purchase invoice for which GL entries has to be done
invoices = frappe.db.sql_list('''
- select distinct parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
+ select distinct parent from `tabPurchase Invoice Item`
+ where service_start_date<=%s and service_end_date>=%s
and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0
- ''', (end_date or today(), start_date or add_months(today(), -1)))
+ ''', (end_date, start_date))
# For each invoice, book deferred expense
for invoice in invoices:
doc = frappe.get_doc("Purchase Invoice", invoice)
- book_deferred_income_or_expense(doc, start_date, end_date)
+ book_deferred_income_or_expense(doc, end_date)
def convert_deferred_revenue_to_income(start_date=None, end_date=None):
+ # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
+ if not start_date:
+ start_date = add_months(today(), -1)
+ if not end_date:
+ end_date = add_days(today(), -1)
+
# check for the sales invoice for which GL entries has to be done
invoices = frappe.db.sql_list('''
- select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
+ select distinct parent from `tabSales Invoice Item`
+ where service_start_date<=%s and service_end_date>=%s
and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0
- ''', (end_date or today(), start_date or add_months(today(), -1)))
+ ''', (end_date, start_date))
- # For each invoice, book deferred revenue
for invoice in invoices:
doc = frappe.get_doc("Sales Invoice", invoice)
- book_deferred_income_or_expense(doc, start_date, end_date)
+ book_deferred_income_or_expense(doc, end_date)
-def get_booking_dates(doc, item, start_date=None, end_date=None):
+def get_booking_dates(doc, item, posting_date=None):
+ if not posting_date:
+ posting_date = add_days(today(), -1)
+
+ last_gl_entry = False
+
deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account"
- last_gl_entry, skip = False, False
-
- booking_end_date = getdate(add_days(today(), -1) if not end_date else end_date)
- if booking_end_date < item.service_start_date or \
- (item.service_stop_date and booking_end_date.month > item.service_stop_date.month):
- return None, None, None, True
- elif booking_end_date >= item.service_end_date:
- last_gl_entry = True
- booking_end_date = item.service_end_date
- elif item.service_stop_date and item.service_stop_date <= booking_end_date:
- last_gl_entry = True
- booking_end_date = item.service_stop_date
-
- booking_start_date = getdate(add_months(today(), -1) if not start_date else start_date)
- booking_start_date = booking_start_date \
- if booking_start_date > item.service_start_date else item.service_start_date
prev_gl_entry = frappe.db.sql('''
select name, posting_date from `tabGL Entry` where company=%s and account=%s and
@@ -81,17 +83,28 @@
order by posting_date desc limit 1
''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
- if not prev_gl_entry and item.service_start_date < booking_start_date:
- booking_start_date = item.service_start_date
- elif prev_gl_entry:
- booking_start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
- skip = True if booking_start_date > booking_end_date else False
+ if prev_gl_entry:
+ start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
+ else:
+ start_date = item.service_start_date
- return last_gl_entry, booking_start_date, booking_end_date, skip
+ end_date = get_last_day(start_date)
+ if end_date >= item.service_end_date:
+ end_date = item.service_end_date
+ last_gl_entry = True
+ elif item.service_stop_date and end_date >= item.service_stop_date:
+ end_date = item.service_stop_date
+ last_gl_entry = True
-def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days):
- account_currency = get_account_currency(item.expense_account)
+ if end_date > getdate(posting_date):
+ end_date = posting_date
+ if getdate(start_date) <= getdate(end_date):
+ return start_date, end_date, last_gl_entry
+ else:
+ return None, None, None
+
+def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency):
if doc.doctype == "Sales Invoice":
total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
deferred_account = "deferred_revenue_account"
@@ -123,28 +136,15 @@
return amount, base_amount
-def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
- # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
- # start_date: 1st of the last month or the start date
- # end_date: end_date or today-1
+def book_deferred_income_or_expense(doc, posting_date=None):
enable_check = "enable_deferred_revenue" \
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
- gl_entries = []
- for item in doc.get('items'):
- if not item.get(enable_check): continue
-
- skip = False
- last_gl_entry, booking_start_date, booking_end_date, skip = \
- get_booking_dates(doc, item, start_date, end_date)
-
- if skip: continue
- total_days = date_diff(item.service_end_date, item.service_start_date) + 1
- total_booking_days = date_diff(booking_end_date, booking_start_date) + 1
+ def _book_deferred_revenue_or_expense(item):
+ start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
+ if not (start_date and end_date): return
account_currency = get_account_currency(item.expense_account)
- amount, base_amount = calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days)
-
if doc.doctype == "Sales Invoice":
against, project = doc.customer, doc.project
credit_account, debit_account = item.income_account, item.deferred_revenue_account
@@ -152,36 +152,62 @@
against, project = doc.supplier, item.project
credit_account, debit_account = item.deferred_expense_account, item.expense_account
- # GL Entry for crediting the amount in the deferred expense
- gl_entries.append(
- doc.get_gl_dict({
- "account": credit_account,
- "against": against,
- "credit": base_amount,
- "credit_in_account_currency": amount,
- "cost_center": item.cost_center,
- "voucher_detail_no": item.name,
- 'posting_date': booking_end_date,
- 'project': project
- }, account_currency)
- )
- # GL Entry to debit the amount from the expense
- gl_entries.append(
- doc.get_gl_dict({
- "account": debit_account,
- "against": against,
- "debit": base_amount,
- "debit_in_account_currency": amount,
- "cost_center": item.cost_center,
- "voucher_detail_no": item.name,
- 'posting_date': booking_end_date,
- 'project': project
- }, account_currency)
- )
+ total_days = date_diff(item.service_end_date, item.service_start_date) + 1
+ total_booking_days = date_diff(end_date, start_date) + 1
+
+ amount, base_amount = calculate_amount(doc, item, last_gl_entry,
+ total_days, total_booking_days, account_currency)
+
+ make_gl_entries(doc, credit_account, debit_account, against,
+ amount, base_amount, end_date, project, account_currency, item.cost_center, item.name)
+
+ if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
+ _book_deferred_revenue_or_expense(item)
+
+
+ for item in doc.get('items'):
+ if item.get(enable_check):
+ _book_deferred_revenue_or_expense(item)
+
+def make_gl_entries(doc, credit_account, debit_account, against,
+ amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no):
+ # GL Entry for crediting the amount in the deferred expense
+ from erpnext.accounts.general_ledger import make_gl_entries
+
+ gl_entries = []
+ gl_entries.append(
+ doc.get_gl_dict({
+ "account": credit_account,
+ "against": against,
+ "credit": base_amount,
+ "credit_in_account_currency": amount,
+ "cost_center": cost_center,
+ "voucher_detail_no": voucher_detail_no,
+ 'posting_date': posting_date,
+ 'project': project
+ }, account_currency)
+ )
+ # GL Entry to debit the amount from the expense
+ gl_entries.append(
+ doc.get_gl_dict({
+ "account": debit_account,
+ "against": against,
+ "debit": base_amount,
+ "debit_in_account_currency": amount,
+ "cost_center": cost_center,
+ "voucher_detail_no": voucher_detail_no,
+ 'posting_date': posting_date,
+ 'project': project
+ }, account_currency)
+ )
+
if gl_entries:
try:
make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
frappe.db.commit()
except:
frappe.db.rollback()
- frappe.log_error(message = frappe.get_traceback(), title = _("Error while processing deferred accounting for {0}").format(doc.name))
\ No newline at end of file
+ title = _("Error while processing deferred accounting for {0}").format(doc.name)
+ traceback = frappe.get_traceback()
+ frappe.log_error(message=traceback , title=title)
+ sendmail_to_system_managers(title, traceback)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 427f3db..3d9604d 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -98,6 +98,8 @@
ancestors = get_root_company(self.company)
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]))
else:
descendants = get_descendants_of('Company', self.company)
@@ -110,6 +112,8 @@
["company", "name"], as_dict=True):
acc_name_map[d["company"]] = d["name"]
+ if not acc_name_map: return
+
for company in descendants:
doc = frappe.copy_doc(self)
doc.flags.ignore_root_company_validation = True
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index df0486c..27f5349 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -23,6 +23,10 @@
if(r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
+
+ frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => {
+ frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
+ });
}
}
});
@@ -133,9 +137,10 @@
{
label:__("Add Child"),
condition: function(node) {
- return frappe.boot.user.can_create.indexOf("Account") !== -1 &&
- !frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() &&
- node.expandable && !node.hide_add;
+ return frappe.boot.user.can_create.indexOf("Account") !== -1
+ && (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
+ || frappe.flags.ignore_root_company_validation)
+ && node.expandable && !node.hide_add;
},
click: function() {
var me = frappe.treeview_settings['Account'].treeview;
diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py
index 4c057d9..90177c6 100644
--- a/erpnext/accounts/doctype/account/test_account.py
+++ b/erpnext/accounts/doctype/account/test_account.py
@@ -144,7 +144,7 @@
# related to Account Inventory Integration
["_Test Account Stock In Hand", "Current Assets", 0, None, None],
-
+
# fixed asset depreciation
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
["_Test Accumulated Depreciations", "Current Assets", 0, None, None],
@@ -181,13 +181,17 @@
return account
def create_account(**kwargs):
- account = frappe.get_doc(dict(
- doctype = "Account",
- account_name = kwargs.get('account_name'),
- account_type = kwargs.get('account_type'),
- parent_account = kwargs.get('parent_account'),
- company = kwargs.get('company')
- ))
-
- account.save()
- return account.name
+ account = frappe.db.get_value("Account", filters={"account_name": kwargs.get("account_name"), "company": kwargs.get("company")})
+ if account:
+ return account
+ else:
+ account = frappe.get_doc(dict(
+ doctype = "Account",
+ account_name = kwargs.get('account_name'),
+ account_type = kwargs.get('account_type'),
+ parent_account = kwargs.get('parent_account'),
+ company = kwargs.get('company')
+ ))
+
+ account.save()
+ return account.name
diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
index 9172762..fae5213 100644
--- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py
@@ -23,36 +23,36 @@
journal_entries = frappe.db.sql("""
- select
- "Journal Entry" as payment_document, t1.name as payment_entry,
- t1.cheque_no as cheque_number, t1.cheque_date,
+ select
+ "Journal Entry" as payment_document, t1.name as payment_entry,
+ t1.cheque_no as cheque_number, t1.cheque_date,
sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit,
- t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
+ t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
t2.parent = t1.name and t2.account = %s and t1.docstatus=1
- and t1.posting_date >= %s and t1.posting_date <= %s
+ and t1.posting_date >= %s and t1.posting_date <= %s
and ifnull(t1.is_opening, 'No') = 'No' {0}
group by t2.account, t1.name
order by t1.posting_date ASC, t1.name DESC
""".format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1)
payment_entries = frappe.db.sql("""
- select
- "Payment Entry" as payment_document, name as payment_entry,
- reference_no as cheque_number, reference_date as cheque_date,
- if(paid_from=%(account)s, paid_amount, "") as credit,
- if(paid_from=%(account)s, "", received_amount) as debit,
+ select
+ "Payment Entry" as payment_document, name as payment_entry,
+ reference_no as cheque_number, reference_date as cheque_date,
+ if(paid_from=%(account)s, paid_amount, 0) as credit,
+ if(paid_from=%(account)s, 0, received_amount) as debit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`
where
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date >= %(from)s and posting_date <= %(to)s {0}
- order by
+ order by
posting_date ASC, name DESC
- """.format(condition),
+ """.format(condition),
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
pos_entries = []
@@ -79,8 +79,12 @@
for d in entries:
row = self.append('payment_entries', {})
- amount = d.debit if d.debit else d.credit
- d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr"))
+
+ amount = flt(d.get('debit', 0)) - flt(d.get('credit', 0))
+
+ formatted_amount = fmt_money(abs(amount), 2, d.account_currency)
+ d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr"))
+
d.pop("credit")
d.pop("debit")
d.pop("account_currency")
@@ -103,10 +107,10 @@
d.clearance_date = None
frappe.db.set_value(d.payment_document, d.payment_entry, "clearance_date", d.clearance_date)
- frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s
- where name=%s""".format(d.payment_document),
+ frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s
+ where name=%s""".format(d.payment_document),
(d.clearance_date, nowdate(), d.payment_entry))
-
+
clearance_date_updated = True
if clearance_date_updated:
diff --git a/erpnext/accounts/doctype/budget/budget.json b/erpnext/accounts/doctype/budget/budget.json
index a803b65..50ad2e5 100644
--- a/erpnext/accounts/doctype/budget/budget.json
+++ b/erpnext/accounts/doctype/budget/budget.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
@@ -19,6 +20,7 @@
"collapsible": 0,
"columns": 0,
"default": "Cost Center",
+ "fetch_if_empty": 0,
"fieldname": "budget_against",
"fieldtype": "Select",
"hidden": 0,
@@ -52,6 +54,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -86,6 +89,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.budget_against == 'Cost Center'",
+ "fetch_if_empty": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
@@ -120,6 +124,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.budget_against == 'Project'",
+ "fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -153,6 +158,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "fiscal_year",
"fieldtype": "Link",
"hidden": 0,
@@ -186,6 +192,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -218,6 +225,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)",
+ "fetch_if_empty": 0,
"fieldname": "monthly_distribution",
"fieldtype": "Link",
"hidden": 0,
@@ -251,6 +259,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -283,6 +292,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
@@ -315,6 +325,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "applicable_on_material_request",
"fieldtype": "Check",
"hidden": 0,
@@ -343,12 +354,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Stop",
"depends_on": "eval:doc.applicable_on_material_request == 1",
+ "fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded_on_mr",
"fieldtype": "Select",
"hidden": 0,
@@ -378,12 +390,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Warn",
"depends_on": "eval:doc.applicable_on_material_request == 1",
+ "fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr",
"fieldtype": "Select",
"hidden": 0,
@@ -417,6 +430,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_13",
"fieldtype": "Column Break",
"hidden": 0,
@@ -448,6 +462,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "applicable_on_purchase_order",
"fieldtype": "Check",
"hidden": 0,
@@ -476,12 +491,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Stop",
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
+ "fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded_on_po",
"fieldtype": "Select",
"hidden": 0,
@@ -511,12 +527,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Warn",
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
+ "fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po",
"fieldtype": "Select",
"hidden": 0,
@@ -550,6 +567,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_16",
"fieldtype": "Section Break",
"hidden": 0,
@@ -581,6 +599,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "applicable_on_booking_actual_expenses",
"fieldtype": "Check",
"hidden": 0,
@@ -609,12 +628,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Stop",
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
+ "fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded",
"fieldtype": "Select",
"hidden": 0,
@@ -644,12 +664,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
- "allow_on_submit": 0,
+ "allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Warn",
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
+ "fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded",
"fieldtype": "Select",
"hidden": 0,
@@ -683,6 +704,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_21",
"fieldtype": "Section Break",
"hidden": 0,
@@ -715,6 +737,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
+ "fetch_if_empty": 0,
"fieldname": "accounts",
"fieldtype": "Table",
"hidden": 0,
@@ -735,7 +758,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -752,7 +775,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-09-12 11:02:41.825923",
+ "modified": "2019-03-22 12:06:02.323099",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget",
@@ -785,7 +808,7 @@
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
+ "track_changes": 1,
+ "track_seen": 0,
"track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 7c48b5c..92342f4 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -52,11 +52,6 @@
self.update_loan()
self.update_inter_company_jv()
- def before_print(self):
- self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Journal Entry",
- "voucher_no": self.name} ,
- fields=["account", "party_type", "party", "debit", "credit", "remarks"]
- )
def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index f356ef8..9100410 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -70,11 +70,6 @@
self.update_advance_paid()
self.update_expense_claim()
- def before_print(self):
- self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Payment Entry",
- "voucher_no": self.name} ,
- fields=["account", "party_type", "party", "debit", "credit", "remarks"]
- )
def on_cancel(self):
self.setup_party_account_field()
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 014efd9..64c4124 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -214,9 +214,10 @@
def check_if_payment_entry_exists(self):
if self.status == "Paid":
- payment_entry = frappe.db.sql_list("""select parent from `tabPayment Entry Reference`
- where reference_name=%s""", self.reference_name)
- if payment_entry:
+ if frappe.get_all("Payment Entry Reference",
+ filters={"reference_name": self.reference_name, "docstatus": ["<", 2]},
+ fields=["parent"],
+ limit=1):
frappe.throw(_("Payment Entry already exists"), title=_('Error'))
def make_communication_entry(self):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index b4fd91f..c94c85c 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -510,6 +510,15 @@
}
}
}
+
+ frm.set_query("cost_center", function() {
+ return {
+ filters: {
+ company: frm.doc.company,
+ is_group: 0
+ }
+ };
+ });
},
onload: function(frm) {
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index bc44bc8..450f2d0 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -55,11 +55,6 @@
if not self.on_hold:
self.release_date = ''
- def before_print(self):
- self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Purchase Invoice",
- "voucher_no": self.name} ,
- fields=["account", "party_type", "party", "debit", "credit"]
- )
def invoice_is_blocked(self):
return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate()))
@@ -223,7 +218,7 @@
self.validate_item_code()
self.validate_warehouse()
if auto_accounting_for_stock:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
for item in self.get("items"):
# in case of auto inventory accounting,
@@ -374,7 +369,8 @@
if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock:
from erpnext.controllers.stock_controller import update_gl_entries_after
items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
+ update_gl_entries_after(self.posting_date, self.posting_time,
+ warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
@@ -433,7 +429,7 @@
stock_items = self.get_stock_items()
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
if self.update_stock and self.auto_accounting_for_stock:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
voucher_wise_stock_value = {}
if self.update_stock:
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 3816632..0399cf9 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -564,6 +564,15 @@
};
});
+ frm.set_query("cost_center", function() {
+ return {
+ filters: {
+ company: frm.doc.company,
+ is_group: 0
+ }
+ };
+ });
+
frm.custom_make_buttons = {
'Delivery Note': 'Delivery',
'Sales Invoice': 'Sales Return',
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 62d8ffd..489343c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -205,11 +205,6 @@
def before_cancel(self):
self.update_time_sheet(None)
- def before_print(self):
- self.gl_entries = frappe.get_list("GL Entry",filters={"voucher_type": "Sales Invoice",
- "voucher_no": self.name} ,
- fields=["account", "party_type", "party", "debit", "credit"]
- )
def on_cancel(self):
self.check_close_sales_order("sales_order")
@@ -405,7 +400,7 @@
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
'company', 'select_print_heading', 'cash_bank_account', 'company_address',
- 'write_off_account', 'write_off_cost_center', 'apply_discount_on'):
+ 'write_off_account', 'write_off_cost_center', 'apply_discount_on', 'cost_center'):
if (not for_validate) or (for_validate and not self.get(fieldname)):
self.set(fieldname, pos.get(fieldname))
@@ -695,7 +690,8 @@
if repost_future_gle and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
items, warehouses = self.get_items_and_warehouses()
- update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
+ update_gl_entries_after(self.posting_date, self.posting_time,
+ warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
from erpnext.accounts.general_ledger import delete_gl_entries
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index f9364e2..45a2950 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -14,8 +14,9 @@
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
from frappe.model.naming import make_autoname
-from erpnext.accounts.doctype.account.test_account import get_inventory_account
+from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
+from erpnext.stock.doctype.item.test_item import create_item
from six import iteritems
class TestSalesInvoice(unittest.TestCase):
def make(self):
@@ -762,7 +763,7 @@
set_perpetual_inventory(0)
frappe.db.sql("delete from `tabPOS Profile`")
-
+
def test_pos_si_without_payment(self):
set_perpetual_inventory()
make_pos_profile()
@@ -1514,6 +1515,56 @@
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
+ def test_deferred_revenue(self):
+ deferred_account = create_account(account_name="Deferred Revenue",
+ parent_account="Current Liabilities - _TC", company="_Test Company")
+
+ item = create_item("_Test Item for Deferred Accounting")
+ item.enable_deferred_revenue = 1
+ item.deferred_revenue_account = deferred_account
+ item.no_of_months = 12
+ item.save()
+
+ si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True)
+ si.items[0].enable_deferred_revenue = 1
+ si.items[0].service_start_date = "2019-01-10"
+ si.items[0].service_end_date = "2019-03-15"
+ si.items[0].deferred_revenue_account = deferred_account
+ si.save()
+ si.submit()
+
+ from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
+ convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-01-31")
+
+ expected_gle = [
+ [deferred_account, 33.85, 0.0, "2019-01-31"],
+ ["Sales - _TC", 0.0, 33.85, "2019-01-31"]
+ ]
+
+ self.check_gl_entries(si.name, expected_gle, "2019-01-10")
+
+ convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-03-31")
+
+ expected_gle = [
+ [deferred_account, 43.08, 0.0, "2019-02-28"],
+ ["Sales - _TC", 0.0, 43.08, "2019-02-28"],
+ [deferred_account, 23.07, 0.0, "2019-03-15"],
+ ["Sales - _TC", 0.0, 23.07, "2019-03-15"]
+ ]
+
+ self.check_gl_entries(si.name, expected_gle, "2019-01-31")
+
+ def check_gl_entries(self, voucher_no, expected_gle, posting_date):
+ gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
+ from `tabGL Entry`
+ where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
+ order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1)
+
+ for i, gle in enumerate(gl_entries):
+ self.assertEqual(expected_gle[i][0], gle.account)
+ self.assertEqual(expected_gle[i][1], gle.debit)
+ self.assertEqual(expected_gle[i][2], gle.credit)
+ self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
@@ -1611,4 +1662,4 @@
if against_voucher_type == 'Purchase Invoice':
bal = bal * -1
- return bal
+ return bal
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index c3274b9..4550ded 100755
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -333,6 +333,7 @@
var me = this;
this.frm = {}
this.load_data(true);
+ this.frm.doc.offline_pos_name = '';
this.setup();
this.set_default_customer()
},
@@ -345,7 +346,6 @@
if (load_doc) {
this.frm.doc = JSON.parse(localStorage.getItem('doc'));
- this.frm.doc.offline_pos_name = null;
}
$.each(this.meta, function (i, data) {
@@ -641,7 +641,7 @@
me.list_customers_btn.toggleClass("view_customer");
me.pos_bill.show();
me.list_customers_btn.show();
- me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name')
+ me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name');
me.edit_record();
})
@@ -984,7 +984,7 @@
}
if(!this.customer_doc.fields_dict.customer_pos_id.value) {
- this.customer_doc.set_value("customer_pos_id", $.now())
+ this.customer_doc.set_value("customer_pos_id", frappe.datetime.now_datetime())
}
},
@@ -1686,10 +1686,18 @@
create_invoice: function () {
var me = this;
+ var existing_pos_list = [];
var invoice_data = {};
this.si_docs = this.get_doc_from_localstorage();
- if (this.frm.doc.offline_pos_name) {
+ if(this.si_docs) {
+ this.si_docs.forEach((row) => {
+ existing_pos_list.push(Object.keys(row));
+ });
+ }
+
+ if (this.frm.doc.offline_pos_name
+ && in_list(existing_pos_list, this.frm.doc.offline_pos_name)) {
this.update_invoice()
//to retrieve and set the default payment
invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
@@ -1698,8 +1706,8 @@
this.frm.doc.paid_amount = this.frm.doc.net_total
this.frm.doc.outstanding_amount = 0
- } else {
- this.frm.doc.offline_pos_name = $.now();
+ } else if(!this.frm.doc.offline_pos_name) {
+ this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
this.frm.doc.posting_date = frappe.datetime.get_today();
this.frm.doc.posting_time = frappe.datetime.now_time();
this.frm.doc.pos_total_qty = this.frm.doc.qty_total;
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 5855ac3..67bd0bd 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -573,11 +573,17 @@
else:
return ''
-def get_partywise_advanced_payment_amount(party_type="Customer"):
+def get_partywise_advanced_payment_amount(party_type, posting_date = None):
+ cond = "1=1"
+ if posting_date:
+ cond = "posting_date <= '{0}'".format(posting_date)
+
data = frappe.db.sql(""" SELECT party, sum({0}) as amount
FROM `tabGL Entry`
- WHERE party_type = %s and against_voucher is null GROUP BY party"""
- .format(("credit - debit") if party_type == "Customer" else "debit") , party_type)
+ WHERE
+ party_type = %s and against_voucher is null
+ and {1} GROUP BY party"""
+ .format(("credit") if party_type == "Customer" else "debit", cond) , party_type)
if data:
return frappe._dict(data)
\ No newline at end of file
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
index 73ca8b4..244aa8a 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -136,7 +136,8 @@
partywise_total = self.get_partywise_total(party_naming_by, args)
- partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type")) or {}
+ partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type"),
+ self.filters.get("report_date")) or {}
for party, party_dict in iteritems(partywise_total):
row = [party]
@@ -145,8 +146,12 @@
row += [partywise_advance_amount.get(party, 0)]
+ paid_amt = 0
+ if party_dict.paid_amt > 0:
+ paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0))
+
row += [
- party_dict.invoiced_amt, party_dict.paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
+ party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4,
]
@@ -205,7 +210,7 @@
cols += ["invoiced_amt", "paid_amt", "credit_amt",
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref",
- "pdc/lc_amount", "remaining_balance"]
+ "pdc/lc_amount"]
if args.get("party_type") == "Supplier":
cols += ["supplier_group", "remarks"]
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
index 39706ac..a0d8c5f 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.py
@@ -134,6 +134,13 @@
"width": 300
},
{
+ "fieldname": "currency",
+ "label": _("Currency"),
+ "fieldtype": "Link",
+ "options": "Currency",
+ "hidden": 1
+ },
+ {
"fieldname": "income",
"label": _("Income"),
"fieldtype": "Currency",
@@ -153,13 +160,6 @@
"fieldtype": "Currency",
"options": "currency",
"width": 120
- },
- {
- "fieldname": "currency",
- "label": _("Currency"),
- "fieldtype": "Link",
- "options": "Currency",
- "hidden": 1
}
]
@@ -191,4 +191,4 @@
for entry in gl_entries:
gl_entries_by_account.setdefault(entry.based_on, []).append(entry)
- return gl_entries_by_account
\ No newline at end of file
+ return gl_entries_by_account
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index e33b90d..3f8abb7 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -66,8 +66,8 @@
total_tax += tax_amount
row.append(tax_amount)
- # total tax, grand total, outstanding amount & rounded total
- row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount]
+ # total tax, grand total, rounded total & outstanding amount
+ row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 0), inv.outstanding_amount]
data.append(row)
return columns, data
diff --git a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
index 6fd16f2..f812977 100644
--- a/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
+++ b/erpnext/accounts/report/supplier_ledger_summary/supplier_ledger_summary.js
@@ -35,9 +35,9 @@
},
{
"fieldname":"party",
- "label": __("Customer"),
+ "label": __("Supplier"),
"fieldtype": "Link",
- "options": "Customer",
+ "options": "Supplier",
on_change: () => {
var party = frappe.query_report.get_filter_value('party');
if (party) {
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index d4e1840..2de5104 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -544,14 +544,14 @@
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no))
-def get_stock_and_account_difference(account_list=None, posting_date=None):
+def get_stock_and_account_difference(account_list=None, posting_date=None, company=None):
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
if not posting_date: posting_date = nowdate()
difference = {}
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(company)
for warehouse, account_data in iteritems(warehouse_account):
if account_data.get('account') in account_list:
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 6b14595..cfacb5a 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -256,7 +256,7 @@
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
- factor = percentage_value / total_number_of_depreciations
+ factor = percentage_value / cint(total_number_of_depreciations)
depreciation_amount = flt(depreciable_value * factor / 100, 0)
value_after_depreciation = flt(depreciable_value) - depreciation_amount
@@ -276,7 +276,7 @@
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked)) * prorata_temporis
else:
- depreciation_amount = self.get_depreciation_amount(depreciable_value, row)
+ depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row)
return depreciation_amount
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index a4a636d..7201606 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -388,9 +388,10 @@
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 = frappe.db.get_value("Project", obj.project, "cost_center") \
- or item.get("buying_cost_center") \
- or item_group.get("buying_cost_center")
+ target.cost_center = (obj.cost_center
+ or frappe.db.get_value("Project", obj.project, "cost_center")
+ or item.get("buying_cost_center")
+ or item_group.get("buying_cost_center"))
doc = get_mapped_doc("Purchase Order", source_name, {
"Purchase Order": {
diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py
index 94f3102..99b8ce0 100644
--- a/erpnext/config/selling.py
+++ b/erpnext/config/selling.py
@@ -325,7 +325,7 @@
{
"type": "help",
"label": _("Sales Order to Payment"),
- "youtube_id": "7AMq4lqkN4A"
+ "youtube_id": "1eP90MWoDQM"
},
{
"type": "help",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 34bbe7b..86b1ab6 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -116,6 +116,12 @@
self.validate_non_invoice_documents_schedule()
def before_print(self):
+ if self.doctype in ['Journal Entry', 'Payment Entry', 'Sales Invoice', 'Purchase Invoice']:
+ self.gl_entries = frappe.get_list("GL Entry", filters={
+ "voucher_type": self.doctype,
+ "voucher_no": self.name
+ }, fields=["account", "party_type", "party", "debit", "credit", "remarks"])
+
if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice',
'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']:
if self.get("group_same_items"):
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 0a3cd34..d1ffd7d 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -26,7 +26,7 @@
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
if self.docstatus==1:
if not gl_entries:
@@ -36,7 +36,7 @@
if repost_future_gle:
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
- warehouse_account)
+ warehouse_account, company=self.company)
elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
gl_entries = []
gl_entries = self.get_asset_gl_entry(gl_entries)
@@ -46,7 +46,7 @@
default_cost_center=None):
if not warehouse_account:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(self.company)
sle_map = self.get_stock_ledger_details()
voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map)
@@ -199,7 +199,8 @@
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]
- acc_diff = get_stock_and_account_difference(account_list, expected_gle[0].posting_date)
+ acc_diff = get_stock_and_account_difference(account_list,
+ expected_gle[0].posting_date, self.company)
cost_center = self.get_company_default("cost_center")
stock_adjustment_account = self.get_company_default("stock_adjustment_account")
@@ -361,13 +362,13 @@
frappe.get_doc("Blanket Order", blanket_order).update_ordered_qty()
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
- warehouse_account=None):
+ warehouse_account=None, company=None):
def _delete_gl_entries(voucher_type, voucher_no):
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
if not warehouse_account:
- warehouse_account = get_warehouse_account_map()
+ warehouse_account = get_warehouse_account_map(company)
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js
index 84255b29..288ebc4 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.js
@@ -49,7 +49,7 @@
var disable = function(frm){
var doc = frm.doc;
frappe.call({
- method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
+ method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
args: {status: 1, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
callback: function(){
cur_frm.reload_doc();
@@ -60,7 +60,7 @@
var enable = function(frm){
var doc = frm.doc;
frappe.call({
- method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
+ method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
args: {status: 0, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
callback: function(){
cur_frm.reload_doc();
diff --git a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
index 727d035..6504994 100644
--- a/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
+++ b/erpnext/healthcare/doctype/healthcare_service_unit_type/healthcare_service_unit_type.py
@@ -111,7 +111,7 @@
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code)
@frappe.whitelist()
-def disable_enable(status, doc_name, item, is_billable):
+def disable_enable(status, doc_name, item=None, is_billable=None):
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "disabled", status)
if(is_billable == 1):
frappe.db.set_value("Item", item, "disabled", status)
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index b85f38b..b73d0e5 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -399,6 +399,19 @@
return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed))
+def get_total_allocated_leaves(employee, leave_type, date):
+ filters= {
+ 'from_date': ['<=', date],
+ 'to_date': ['>=', date],
+ 'docstatus': 1,
+ 'leave_type': leave_type,
+ 'employee': employee
+ }
+
+ leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated'])
+
+ return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0)
+
def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None):
leave_applications = frappe.db.sql("""
select name, employee, leave_type, from_date, to_date, total_leave_days
@@ -505,8 +518,6 @@
def add_leaves(events, start, end, filter_conditions=None):
conditions = []
- if filter_conditions:
- conditions.append(filter_conditions)
if not cint(frappe.db.get_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar")):
from frappe.desk.reportview import build_match_conditions
@@ -520,11 +531,14 @@
from `tabLeave Application` where
from_date <= %(end)s and to_date >= %(start)s <= to_date
and docstatus < 2
- and status!="Rejected" """
+ and status!='Rejected' """
if conditions:
query += ' and ' + ' and '.join(conditions)
+ if filter_conditions:
+ query += filter_conditions
+
for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True):
e = {
"name": d.name,
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 3fd266b..684f348 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -441,7 +441,7 @@
def calculate_net_pay(self):
if self.salary_structure:
self.calculate_component_amounts()
-
+
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
precision = frappe.defaults.get_global_default("currency_precision")
self.total_deduction = 0
@@ -452,10 +452,10 @@
self.set_loan_repayment()
- self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
+ self.net_pay = (flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))) * flt(self.payment_days / self.total_working_days)
self.rounded_total = rounded(self.net_pay,
self.precision("net_pay") if disable_rounded_total else 0)
-
+
if self.net_pay < 0:
frappe.throw(_("Net Pay cannnot be negative"))
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index ed44d63..95cb30b 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -5,21 +5,21 @@
import frappe
from frappe import _
from erpnext.hr.doctype.leave_application.leave_application \
- import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period
+ import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves
def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
-
+
columns = get_columns(leave_types)
data = get_data(filters, leave_types)
-
+
return columns, data
-
+
def get_columns(leave_types):
columns = [
- _("Employee") + ":Link/Employee:150",
- _("Employee Name") + "::200",
+ _("Employee") + ":Link/Employee:150",
+ _("Employee Name") + "::200",
_("Department") +"::150"
]
@@ -27,18 +27,18 @@
columns.append(_(leave_type) + " " + _("Opening") + ":Float:160")
columns.append(_(leave_type) + " " + _("Taken") + ":Float:160")
columns.append(_(leave_type) + " " + _("Balance") + ":Float:160")
-
+
return columns
-
+
def get_data(filters, leave_types):
user = frappe.session.user
allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date)
- active_employees = frappe.get_all("Employee",
- filters = { "status": "Active", "company": filters.company},
+ active_employees = frappe.get_all("Employee",
+ filters = { "status": "Active", "company": filters.company},
fields = ["name", "employee_name", "department", "user_id"])
-
+
data = []
for employee in active_employees:
leave_approvers = get_approvers(employee.department)
@@ -51,8 +51,7 @@
filters.from_date, filters.to_date)
# opening balance
- opening = get_leave_balance_on(employee.name, leave_type, filters.from_date,
- allocation_records_based_on_from_date.get(employee.name, frappe._dict()))
+ opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date)
# closing balance
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date,
@@ -61,7 +60,7 @@
row += [opening, leaves_taken, closing]
data.append(row)
-
+
return data
def get_approvers(department):
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index ea6b7ed..db94350 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -580,7 +580,7 @@
context.title = _("Bill of Materials")
# context.introduction = _('Boms')
-def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False):
+def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False, fetch_qty_in_stock_uom=True):
item_dict = {}
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
@@ -588,7 +588,7 @@
bom_item.item_code,
bom_item.idx,
item.item_name,
- sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(qty)s as qty,
+ sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty,
item.description,
item.image,
item.stock_uom,
@@ -616,16 +616,18 @@
query = query.format(table="BOM Explosion Item",
where_conditions="",
is_stock_item=is_stock_item,
+ qty_field="stock_qty",
select_columns = """, bom_item.source_warehouse, bom_item.operation, bom_item.include_item_in_manufacturing,
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx""")
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
elif fetch_scrap_items:
- query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item)
+ query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item, qty_field="stock_qty")
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
else:
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
- select_columns = ", bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing")
+ qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
+ select_columns = ", bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing")
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
for item in items:
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 7d49ad5..9d1e7b1 100755
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -587,5 +587,5 @@
execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
-erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019
-erpnext.patches.v11_1.make_job_card_time_logs
\ No newline at end of file
+erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019
+erpnext.patches.v11_1.make_job_card_time_logs
diff --git a/erpnext/patches/v11_0/make_italian_localization_fields.py b/erpnext/patches/v11_0/make_italian_localization_fields.py
index 44a281f..79958b9 100644
--- a/erpnext/patches/v11_0/make_italian_localization_fields.py
+++ b/erpnext/patches/v11_0/make_italian_localization_fields.py
@@ -6,7 +6,6 @@
from erpnext.regional.italy import state_codes
import frappe
-
def execute():
company = frappe.get_all('Company', filters = {'country': 'Italy'})
if not company:
@@ -27,4 +26,12 @@
frappe.db.sql("""
UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code
from `tabCountry` where name = `tabAddress`.country), ''))
+ where country_code is null and state_code is null
""".format(condition=condition))
+
+ frappe.db.sql("""
+ UPDATE `tabSales Invoice Item` si, `tabSales Order` so
+ set si.customer_po_no = so.po_no, si.customer_po_date = so.po_date
+ WHERE
+ si.sales_order = so.name and so.po_no is not null
+ """)
diff --git a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
index 22f9db6..9e21fb6 100644
--- a/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
+++ b/erpnext/patches/v7_0/repost_future_gle_for_purchase_invoice.py
@@ -10,14 +10,15 @@
def execute():
company_list = frappe.db.sql_list("""Select name from tabCompany where enable_perpetual_inventory = 1""")
frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
-
- frappe.reload_doctype("Purchase Invoice")
+
+ frappe.reload_doctype("Purchase Invoice")
wh_account = get_warehouse_account_map()
-
+
for pi in frappe.get_all("Purchase Invoice", fields=["name", "company"], filters={"docstatus": 1, "update_stock": 1}):
if pi.company in company_list:
pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
items, warehouses = pi_doc.get_items_and_warehouses()
- update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time, warehouses, items, wh_account)
-
+ update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time,
+ warehouses, items, wh_account, company = pi.company)
+
frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index fffa9c1..1230278 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -159,6 +159,13 @@
self.update_nsm_model()
+ def update_status(self):
+ if self.status not in ('Cancelled', 'Closed') and self.exp_end_date:
+ from datetime import datetime
+ if self.exp_end_date < datetime.now().date():
+ self.db_set('status', 'Overdue')
+ self.update_project()
+
@frappe.whitelist()
def check_if_child_exists(name):
child_tasks = frappe.get_all("Task", filters={"parent_task": name})
@@ -186,10 +193,9 @@
task.save()
def set_tasks_as_overdue():
- frappe.db.sql("""update tabTask set `status`='Overdue'
- where exp_end_date is not null
- and exp_end_date < CURDATE()
- and `status` not in ('Closed', 'Cancelled')""")
+ tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Closed']]})
+ for task in tasks:
+ frappe.get_doc("Task", task.name).update_status()
@frappe.whitelist()
def get_children(doctype, parent, task=None, project=None, is_root=False):
diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py
index 9971946..b733f67 100644
--- a/erpnext/projects/doctype/task/test_task.py
+++ b/erpnext/projects/doctype/task/test_task.py
@@ -117,4 +117,4 @@
if save:
task.save()
- return task
\ No newline at end of file
+ return task
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 8811ab9..8ffc10e 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -10,8 +10,8 @@
filters:{
'status': 'Active'
}
- }
- }
+ };
+ };
frm.fields_dict['time_logs'].grid.get_field('task').get_query = function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
@@ -20,33 +20,37 @@
'project': child.project,
'status': ["!=", "Cancelled"]
}
- }
- }
+ };
+ };
frm.fields_dict['time_logs'].grid.get_field('project').get_query = function() {
return{
filters: {
'company': frm.doc.company
}
- }
- }
+ };
+ };
},
onload: function(frm){
if (frm.doc.__islocal && frm.doc.time_logs) {
calculate_time_and_amount(frm);
}
+
+ if (frm.is_new()) {
+ set_employee_and_company(frm);
+ }
},
refresh: function(frm) {
if(frm.doc.docstatus==1) {
if(frm.doc.per_billed < 100 && frm.doc.total_billable_hours && frm.doc.total_billable_hours > frm.doc.total_billed_hours){
- frm.add_custom_button(__("Make Sales Invoice"), function() { frm.trigger("make_invoice") },
+ frm.add_custom_button(__("Make Sales Invoice"), function() { frm.trigger("make_invoice"); },
"fa fa-file-alt");
}
if(!frm.doc.salary_slip && frm.doc.employee){
- frm.add_custom_button(__("Make Salary Slip"), function() { frm.trigger("make_salary_slip") },
+ frm.add_custom_button(__("Make Salary Slip"), function() { frm.trigger("make_salary_slip"); },
"fa fa-file-alt");
}
}
@@ -58,7 +62,7 @@
if ((row.from_time <= frappe.datetime.now_datetime()) && !row.completed) {
button = 'Resume Timer';
}
- })
+ });
frm.add_custom_button(__(button), function() {
var flag = true;
@@ -77,7 +81,7 @@
erpnext.timesheet.timer(frm, row, timestamp);
flag = false;
}
- })
+ });
// If no activities found to start a timer, create new
if (flag) {
erpnext.timesheet.timer(frm);
@@ -94,7 +98,7 @@
frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours')
.then(({ message }) => {
(frappe.working_hours = message.standard_working_hours || 0);
- });
+ });
},
make_invoice: function(frm) {
@@ -125,8 +129,8 @@
frappe.set_route("Form", r.message.doctype, r.message.name);
}
}
- })
- })
+ });
+ });
dialog.show();
},
@@ -136,7 +140,7 @@
frm: frm
});
},
-})
+});
frappe.ui.form.on("Timesheet Detail", {
time_logs_remove: function(frm) {
@@ -171,22 +175,22 @@
.find('[data-fieldname="timer"]')
.append(frappe.render_template("timesheet"));
frm.trigger("control_timer");
- })
+ });
},
hours: function(frm, cdt, cdn) {
- calculate_end_time(frm, cdt, cdn)
+ calculate_end_time(frm, cdt, cdn);
},
billing_hours: function(frm, cdt, cdn) {
- calculate_billing_costing_amount(frm, cdt, cdn)
+ calculate_billing_costing_amount(frm, cdt, cdn);
},
billing_rate: function(frm, cdt, cdn) {
- calculate_billing_costing_amount(frm, cdt, cdn)
+ calculate_billing_costing_amount(frm, cdt, cdn);
},
costing_rate: function(frm, cdt, cdn) {
- calculate_billing_costing_amount(frm, cdt, cdn)
+ calculate_billing_costing_amount(frm, cdt, cdn);
},
billable: function(frm, cdt, cdn) {
@@ -212,7 +216,7 @@
calculate_billing_costing_amount(frm, cdt, cdn);
}
}
- })
+ });
}
});
@@ -240,23 +244,23 @@
frm._setting_hours = true;
frappe.model.set_value(cdt, cdn, "to_time",
d.format(frappe.defaultDatetimeFormat)).then(() => {
- frm._setting_hours = false;
- });
+ frm._setting_hours = false;
+ });
}
}
-}
+};
var update_billing_hours = function(frm, cdt, cdn){
var child = locals[cdt][cdn];
if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0);
-}
+};
var update_time_rates = function(frm, cdt, cdn){
var child = locals[cdt][cdn];
if(!child.billable){
frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0);
}
-}
+};
var calculate_billing_costing_amount = function(frm, cdt, cdn){
var child = locals[cdt][cdn];
@@ -270,7 +274,7 @@
frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
calculate_time_and_amount(frm);
-}
+};
var calculate_time_and_amount = function(frm) {
var tl = frm.doc.time_logs || [];
@@ -294,4 +298,17 @@
frm.set_value("total_hours", total_working_hr);
frm.set_value("total_billable_amount", total_billable_amount);
frm.set_value("total_costing_amount", total_costing_amount);
-}
\ No newline at end of file
+};
+
+// set employee (and company) to the one that's currently logged in
+const set_employee_and_company = function(frm) {
+ const options = { user_id: frappe.session.user };
+ const fields = ['name', 'company'];
+ frappe.db.get_value('Employee', options, fields).then(({ message }) => {
+ if (message) {
+ // there is an employee with the currently logged in user_id
+ frm.set_value("employee", message.name);
+ frm.set_value("company", message.company);
+ }
+ });
+};
diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json
index 5ad2ab3..c29c11b 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.json
+++ b/erpnext/projects/doctype/timesheet/timesheet.json
@@ -739,7 +739,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "total_costing_amount",
- "fieldtype": "Float",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -805,7 +805,7 @@
"depends_on": "",
"description": "",
"fieldname": "total_billable_amount",
- "fieldtype": "Float",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -837,7 +837,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "total_billed_amount",
- "fieldtype": "Float",
+ "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1000,7 +1000,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-01-30 11:28:18.518590",
+ "modified": "2019-03-05 21:54:02.654690",
"modified_by": "Administrator",
"module": "Projects",
"name": "Timesheet",
diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js
index 56e6bdb..477781b 100644
--- a/erpnext/public/js/conf.js
+++ b/erpnext/public/js/conf.js
@@ -27,8 +27,6 @@
target="_blank">'+__('Documentation')+'</a></li>').insertBefore($help_menu);
$('<li><a data-link-type="forum" href="https://discuss.erpnext.com" \
target="_blank">'+__('User Forum')+'</a></li>').insertBefore($help_menu);
- $('<li class="gitter-chat-link"><a href="https://gitter.im/frappe/erpnext" \
- target="_blank">'+__('Gitter Chat')+'</a></li>').insertBefore($help_menu);
$('<li><a href="https://github.com/frappe/erpnext/issues" \
target="_blank">'+__('Report an Issue')+'</a></li>').insertBefore($help_menu);
diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml
index c886ee9..935077b 100644
--- a/erpnext/regional/italy/e-invoice.xml
+++ b/erpnext/regional/italy/e-invoice.xml
@@ -95,13 +95,12 @@
<Cognome>{{ doc.customer_data.last_name }}</Cognome>
</Anagrafica>
{%- else %}
- {%- if doc.customer_data.is_public_administration %}
- <CodiceFiscale>{{ doc.customer_data.fiscal_code }}</CodiceFiscale>
- {%- else %}
<IdFiscaleIVA>
<IdPaese>{{ doc.customer_address_data.country_code }}</IdPaese>
<IdCodice>{{ doc.tax_id | replace("IT","") }}</IdCodice>
</IdFiscaleIVA>
+ {%- if doc.customer_data.fiscal_code %}
+ <CodiceFiscale>{{ doc.customer_data.fiscal_code }}</CodiceFiscale>
{%- endif %}
<Anagrafica>
<Denominazione>{{ doc.customer_name }}</Denominazione>
@@ -128,22 +127,42 @@
<ImportoBollo>{{ format_float(doc.stamp_duty) }}</ImportoBollo>
</DatiBollo>
{%- endif %}
- <ImportoTotaleDocumento>{{ format_float(doc.grand_total) }}</ImportoTotaleDocumento>
+ {%- if doc.discount_amount %}
+ <ScontoMaggiorazione>
+ {%- if doc.discount_amount > 0.0 %}
+ <Tipo>SC</Tipo>
+ {%- else %}
+ <Tipo>MG</Tipo>
+ {%- endif %}
+ {%- if doc.additional_discount_percentage > 0.0 %}
+ <Percentuale>{{ format_float(doc.additional_discount_percentage) }}</Percentuale>
+ {%- endif %}
+ <Importo>{{ format_float(doc.discount_amount) }}</Importo>
+ </ScontoMaggiorazione>
+ {%- endif %}
+ <ImportoTotaleDocumento>{{ format_float(doc.rounded_total or doc.grand_total) }}</ImportoTotaleDocumento>
<Causale>VENDITA</Causale>
</DatiGeneraliDocumento>
- {%- if doc.po_no %}
- <DatiOrdineAcquisto>
- <IdDocumento>{{ doc.po_no }}</IdDocumento>
- {%- if doc.po_date %}
- <Data>{{ doc.po_date }}</Data>
- {%- endif %}
- </DatiOrdineAcquisto>
- {%- endif %}
+ {%- for po_no, po_date in doc.customer_po_data.items() %}
+ <DatiOrdineAcquisto>
+ <IdDocumento>{{ po_no }}</IdDocumento>
+ <Data>{{ po_date }}</Data>
+ </DatiOrdineAcquisto>
+ {%- endfor %}
{%- if doc.is_return and doc.return_against_unamended %}
<DatiFattureCollegate>
<IdDocumento>{{ doc.return_against_unamended }}</IdDocumento>
</DatiFattureCollegate>
{%- endif %}
+ {%- for row in doc.e_invoice_items %}
+ {%- if row.delivery_note %}
+ <DatiDDT>
+ <NumeroDDT>{{ row.delivery_note }}</NumeroDDT>
+ <DataDDT>{{ frappe.db.get_value('Delivery Note', row.delivery_note, 'posting_date') }}</DataDDT>
+ <RiferimentoNumeroLinea>{{ row.idx }}</RiferimentoNumeroLinea>
+ </DatiDDT>
+ {%- endif %}
+ {%- endfor %}
{%- if doc.shipping_address_data %}
<DatiTrasporto>
<IndirizzoResa>
@@ -165,7 +184,11 @@
<UnitaMisura>{{ item.stock_uom }}</UnitaMisura>
<PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate) }}</PrezzoUnitario>
{{ render_discount_or_margin(item) }}
- <PrezzoTotale>{{ format_float(item.amount) }}</PrezzoTotale>
+ {%- if (item.discount_amount or item.rate_with_margin) %}
+ <PrezzoTotale>{{ format_float(item.net_amount) }}</PrezzoTotale>
+ {%- else %}
+ <PrezzoTotale>{{ format_float(item.amount) }}</PrezzoTotale>
+ {%- endif %}
<AliquotaIVA>{{ format_float(item.tax_rate) }}</AliquotaIVA>
{%- if item.tax_exemption_reason %}
<Natura>{{ item.tax_exemption_reason.split("-")[0] }}</Natura>
@@ -199,7 +222,9 @@
<ModalitaPagamento>{{ payment_term.mode_of_payment_code.split("-")[0] }}</ModalitaPagamento>
<DataScadenzaPagamento>{{ payment_term.due_date }}</DataScadenzaPagamento>
<ImportoPagamento>{{ format_float(payment_term.payment_amount) }}</ImportoPagamento>
- <IstitutoFinanziario>{{ payment_term.bank_account_name }}</IstitutoFinanziario>
+ {%- if payment_term.bank_account_name %}
+ <IstitutoFinanziario>{{ payment_term.bank_account_name }}</IstitutoFinanziario>
+ {%- endif %}
{%- if payment_term.bank_account_iban %}
<IBAN>{{ payment_term.bank_account_iban }}</IBAN>
<ABI>{{ payment_term.bank_account_iban[5:10] }}</ABI>
diff --git a/erpnext/regional/italy/sales_invoice.js b/erpnext/regional/italy/sales_invoice.js
index 3457f71..586a529 100644
--- a/erpnext/regional/italy/sales_invoice.js
+++ b/erpnext/regional/italy/sales_invoice.js
@@ -3,15 +3,26 @@
refresh: (frm) => {
if(frm.doc.docstatus == 1) {
frm.add_custom_button('Generate E-Invoice', () => {
- var w = window.open(
- frappe.urllib.get_full_url(
- "/api/method/erpnext.regional.italy.utils.generate_single_invoice?"
- + "docname=" + frm.doc.name
- )
- )
- if (!w) {
- frappe.msgprint(__("Please enable pop-ups")); return;
- }
+ frm.call({
+ method: "erpnext.regional.italy.utils.generate_single_invoice",
+ args: {
+ docname: frm.doc.name
+ },
+ callback: function(r) {
+ frm.reload_doc();
+ if(r.message) {
+ var w = window.open(
+ frappe.urllib.get_full_url(
+ "/api/method/erpnext.regional.italy.utils.download_e_invoice_file?"
+ + "file_name=" + r.message
+ )
+ )
+ if (!w) {
+ frappe.msgprint(__("Please enable pop-ups")); return;
+ }
+ }
+ }
+ });
});
}
}
diff --git a/erpnext/regional/italy/setup.py b/erpnext/regional/italy/setup.py
index 2b6e3af..1526d6f 100644
--- a/erpnext/regional/italy/setup.py
+++ b/erpnext/regional/italy/setup.py
@@ -26,6 +26,22 @@
print_hide=1, hidden=1, read_only=1, options="currency")
]
+ customer_po_fields = [
+ dict(fieldname='customer_po_details', label='Customer PO',
+ fieldtype='Section Break', insert_after='image'),
+ dict(fieldname='customer_po_no', label='Customer PO No',
+ fieldtype='Data', insert_after='customer_po_details',
+ fetch_from = 'sales_order.po_no',
+ print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1),
+ dict(fieldname='customer_po_clm_brk', label='',
+ fieldtype='Column Break', insert_after='customer_po_no',
+ print_hide=1, read_only=1),
+ dict(fieldname='customer_po_date', label='Customer PO Date',
+ fieldtype='Date', insert_after='customer_po_clm_brk',
+ fetch_from = 'sales_order.po_date',
+ print_hide=1, allow_on_submit=1, fetch_if_empty= 1, read_only=1, no_copy=1)
+ ]
+
custom_fields = {
'Company': [
dict(fieldname='sb_e_invoicing', label='E-Invoicing',
@@ -128,7 +144,7 @@
'Purchase Invoice Item': invoice_item_fields,
'Sales Order Item': invoice_item_fields,
'Delivery Note Item': invoice_item_fields,
- 'Sales Invoice Item': invoice_item_fields,
+ 'Sales Invoice Item': invoice_item_fields + customer_po_fields,
'Quotation Item': invoice_item_fields,
'Purchase Order Item': invoice_item_fields,
'Purchase Receipt Item': invoice_item_fields,
diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py
index f39b144..435faea 100644
--- a/erpnext/regional/italy/utils.py
+++ b/erpnext/regional/italy/utils.py
@@ -82,6 +82,14 @@
if item.tax_rate == 0.0 and item.tax_amount == 0.0:
item.tax_exemption_reason = tax_data["0.0"]["tax_exemption_reason"]
+ customer_po_data = {}
+ for d in invoice.e_invoice_items:
+ if (d.customer_po_no and d.customer_po_date
+ and d.customer_po_no not in customer_po_data):
+ customer_po_data[d.customer_po_no] = d.customer_po_date
+
+ invoice.customer_po_data = customer_po_data
+
return invoice
def get_conditions(filters):
@@ -134,6 +142,7 @@
idx=len(items)+1,
item_code=reference_row.description,
item_name=reference_row.description,
+ description=reference_row.description,
rate=reference_row.tax_amount,
qty=1.0,
amount=reference_row.tax_amount,
@@ -198,19 +207,25 @@
else:
doc.company_fiscal_regime = company_fiscal_regime
+ doc.company_tax_id = frappe.get_cached_value("Company", doc.company, 'tax_id')
+ doc.company_fiscal_code = frappe.get_cached_value("Company", doc.company, 'fiscal_code')
if not doc.company_tax_id and not doc.company_fiscal_code:
frappe.throw(_("Please set either the Tax ID or Fiscal Code on Company '%s'" % doc.company), title=_("E-Invoicing Information Missing"))
#Validate customer details
- customer_type, is_public_administration = frappe.db.get_value("Customer", doc.customer, ["customer_type", "is_public_administration"])
- if customer_type == _("Individual"):
+ customer = frappe.get_doc("Customer", doc.customer)
+
+ if customer.customer_type == _("Individual"):
+ doc.customer_fiscal_code = customer.fiscal_code
if not doc.customer_fiscal_code:
frappe.throw(_("Please set Fiscal Code for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing"))
else:
- if is_public_administration:
+ if customer.is_public_administration:
+ doc.customer_fiscal_code = customer.fiscal_code
if not doc.customer_fiscal_code:
frappe.throw(_("Please set Fiscal Code for the public administration '%s'" % doc.customer), title=_("E-Invoicing Information Missing"))
else:
+ doc.tax_id = customer.tax_id
if not doc.tax_id:
frappe.throw(_("Please set Tax ID for the customer '%s'" % doc.customer), title=_("E-Invoicing Information Missing"))
@@ -266,13 +281,18 @@
def generate_single_invoice(docname):
doc = frappe.get_doc("Sales Invoice", docname)
+
e_invoice = prepare_and_attach_invoice(doc, True)
+ return e_invoice.file_name
+
+@frappe.whitelist()
+def download_e_invoice_file(file_name):
content = None
- with open(frappe.get_site_path('private', 'files', e_invoice.file_name), "r") as f:
+ with open(frappe.get_site_path('private', 'files', file_name), "r") as f:
content = f.read()
- frappe.local.response.filename = e_invoice.file_name
+ frappe.local.response.filename = file_name
frappe.local.response.filecontent = content
frappe.local.response.type = "download"
diff --git "a/erpnext/regional/report/fichier_des_ecritures_comptables_\133fec\135/fichier_des_ecritures_comptables_\133fec\135.py" "b/erpnext/regional/report/fichier_des_ecritures_comptables_\133fec\135/fichier_des_ecritures_comptables_\133fec\135.py"
index 5fbf700..6b8d3f0 100644
--- "a/erpnext/regional/report/fichier_des_ecritures_comptables_\133fec\135/fichier_des_ecritures_comptables_\133fec\135.py"
+++ "b/erpnext/regional/report/fichier_des_ecritures_comptables_\133fec\135/fichier_des_ecritures_comptables_\133fec\135.py"
@@ -87,8 +87,8 @@
left join `tabPurchase Invoice` pur on gl.voucher_no = pur.name
left join `tabJournal Entry` jnl on gl.voucher_no = jnl.name
left join `tabPayment Entry` pay on gl.voucher_no = pay.name
- left join `tabCustomer` cus on gl.party = cus.customer_name
- left join `tabSupplier` sup on gl.party = sup.supplier_name
+ left join `tabCustomer` cus on gl.party = cus.name
+ left join `tabSupplier` sup on gl.party = sup.name
where gl.company=%(company)s and gl.fiscal_year=%(fiscal_year)s
{group_by_condition}
order by GlPostDate, voucher_no"""\
diff --git a/erpnext/setup/doctype/brand/test_records.json b/erpnext/setup/doctype/brand/test_records.json
index d2a4ad4..e4f892e 100644
--- a/erpnext/setup/doctype/brand/test_records.json
+++ b/erpnext/setup/doctype/brand/test_records.json
@@ -1,6 +1,6 @@
[
{
- "brand": "_Test Brand",
+ "brand": "_Test Brand",
"doctype": "Brand"
}
]
\ No newline at end of file
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 77c371e..dbd7c41 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -22,6 +22,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "details",
"fieldtype": "Section Break",
"hidden": 0,
@@ -54,6 +55,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "company_name",
"fieldtype": "Data",
"hidden": 0,
@@ -88,6 +90,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
+ "fetch_if_empty": 0,
"fieldname": "abbr",
"fieldtype": "Data",
"hidden": 0,
@@ -122,6 +125,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal && in_list(frappe.user_roles, \"System Manager\")",
+ "fetch_if_empty": 0,
"fieldname": "change_abbr",
"fieldtype": "Button",
"hidden": 0,
@@ -153,6 +157,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
@@ -185,6 +190,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_finance_book",
"fieldtype": "Link",
"hidden": 0,
@@ -218,6 +224,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "cb0",
"fieldtype": "Column Break",
"hidden": 0,
@@ -248,6 +255,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "domain",
"fieldtype": "Link",
"hidden": 0,
@@ -280,6 +288,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "parent_company",
"fieldtype": "Link",
"hidden": 0,
@@ -313,6 +322,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "sb_about",
"fieldtype": "Section Break",
"hidden": 0,
@@ -345,6 +355,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "company_logo",
"fieldtype": "Attach Image",
"hidden": 0,
@@ -377,6 +388,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "company_description",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -409,6 +421,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "sales_settings",
"fieldtype": "Section Break",
"hidden": 0,
@@ -441,6 +454,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "sales_monthly_history",
"fieldtype": "Small Text",
"hidden": 1,
@@ -473,6 +487,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "transactions_annual_history",
"fieldtype": "Code",
"hidden": 1,
@@ -505,6 +520,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "monthly_sales_target",
"fieldtype": "Currency",
"hidden": 0,
@@ -538,6 +554,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_goals",
"fieldtype": "Column Break",
"hidden": 0,
@@ -569,6 +586,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "total_monthly_sales",
"fieldtype": "Currency",
"hidden": 0,
@@ -602,6 +620,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "charts_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -633,6 +652,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_currency",
"fieldtype": "Link",
"hidden": 0,
@@ -665,6 +685,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_letter_head",
"fieldtype": "Link",
"hidden": 0,
@@ -698,6 +719,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_holiday_list",
"fieldtype": "Link",
"hidden": 0,
@@ -731,6 +753,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "standard_working_hours",
"fieldtype": "Float",
"hidden": 0,
@@ -763,6 +786,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_terms",
"fieldtype": "Link",
"hidden": 0,
@@ -795,6 +819,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_10",
"fieldtype": "Column Break",
"hidden": 0,
@@ -826,6 +851,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "country",
"fieldtype": "Link",
"hidden": 0,
@@ -858,6 +884,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "create_chart_of_accounts_based_on",
"fieldtype": "Select",
"hidden": 0,
@@ -892,6 +919,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"",
+ "fetch_if_empty": 0,
"fieldname": "chart_of_accounts",
"fieldtype": "Select",
"hidden": 0,
@@ -926,6 +954,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"",
+ "fetch_if_empty": 0,
"fieldname": "existing_company",
"fieldtype": "Link",
"hidden": 0,
@@ -959,6 +988,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "tax_id",
"fieldtype": "Data",
"hidden": 0,
@@ -991,6 +1021,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "date_of_establishment",
"fieldtype": "Date",
"hidden": 0,
@@ -1023,6 +1054,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_settings",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1056,6 +1088,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_bank_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1091,6 +1124,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_cash_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1124,6 +1158,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_receivable_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1158,6 +1193,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "round_off_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1191,6 +1227,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "round_off_cost_center",
"fieldtype": "Link",
"hidden": 0,
@@ -1224,6 +1261,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "write_off_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1257,6 +1295,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "discount_allowed_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1290,6 +1329,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "discount_received_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1323,6 +1363,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "exchange_gain_loss_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1356,6 +1397,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "unrealized_exchange_gain_loss_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1389,6 +1431,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1421,7 +1464,42 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "depends_on": "eval:doc.parent_company",
+ "fetch_if_empty": 0,
+ "fieldname": "allow_account_creation_against_child_company",
+ "fieldtype": "Check",
+ "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": "Allow Account Creation Against Child Company",
+ "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,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_payable_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1456,6 +1534,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_employee_advance_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1490,6 +1569,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_expense_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1523,6 +1603,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_income_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1556,6 +1637,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_deferred_revenue_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1590,6 +1672,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_deferred_expense_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1624,6 +1707,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_payroll_payable_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1658,6 +1742,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "default_expense_claim_payable_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1691,6 +1776,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "section_break_22",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1723,6 +1809,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
@@ -1755,6 +1842,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_26",
"fieldtype": "Column Break",
"hidden": 0,
@@ -1787,6 +1875,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "credit_limit",
"fieldtype": "Currency",
"hidden": 0,
@@ -1822,6 +1911,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
+ "fetch_if_empty": 0,
"fieldname": "payment_terms",
"fieldtype": "Link",
"hidden": 0,
@@ -1856,6 +1946,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
+ "fetch_if_empty": 0,
"fieldname": "auto_accounting_for_stock_settings",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1888,6 +1979,7 @@
"collapsible": 0,
"columns": 0,
"default": "1",
+ "fetch_if_empty": 0,
"fieldname": "enable_perpetual_inventory",
"fieldtype": "Check",
"hidden": 0,
@@ -1920,6 +2012,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "default_inventory_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1953,6 +2046,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "stock_adjustment_account",
"fieldtype": "Link",
"hidden": 0,
@@ -1985,6 +2079,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_32",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2016,6 +2111,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "stock_received_but_not_billed",
"fieldtype": "Link",
"hidden": 0,
@@ -2048,6 +2144,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "expenses_included_in_valuation",
"fieldtype": "Link",
"hidden": 0,
@@ -2080,6 +2177,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "fixed_asset_depreciation_settings",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2112,6 +2210,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "accumulated_depreciation_account",
"fieldtype": "Link",
"hidden": 0,
@@ -2145,6 +2244,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "depreciation_expense_account",
"fieldtype": "Link",
"hidden": 0,
@@ -2178,6 +2278,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "series_for_depreciation_entry",
"fieldtype": "Data",
"hidden": 0,
@@ -2210,6 +2311,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "expenses_included_in_asset_valuation",
"fieldtype": "Link",
"hidden": 0,
@@ -2243,6 +2345,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break_40",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2274,6 +2377,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "disposal_account",
"fieldtype": "Link",
"hidden": 0,
@@ -2307,6 +2411,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "depreciation_cost_center",
"fieldtype": "Link",
"hidden": 0,
@@ -2340,6 +2445,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "capital_work_in_progress_account",
"fieldtype": "Link",
"hidden": 0,
@@ -2373,6 +2479,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "asset_received_but_not_billed",
"fieldtype": "Link",
"hidden": 0,
@@ -2406,6 +2513,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "budget_detail",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2438,6 +2546,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "exception_budget_approver_role",
"fieldtype": "Link",
"hidden": 0,
@@ -2472,6 +2581,7 @@
"collapsible": 0,
"columns": 0,
"description": "For reference only.",
+ "fetch_if_empty": 0,
"fieldname": "company_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2503,6 +2613,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "date_of_incorporation",
"fieldtype": "Date",
"hidden": 0,
@@ -2535,6 +2646,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "address_html",
"fieldtype": "HTML",
"hidden": 0,
@@ -2566,6 +2678,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
@@ -2599,6 +2712,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.date_of_incorporation",
+ "fetch_if_empty": 0,
"fieldname": "date_of_commencement",
"fieldtype": "Date",
"hidden": 0,
@@ -2631,6 +2745,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "phone_no",
"fieldtype": "Data",
"hidden": 0,
@@ -2665,6 +2780,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "fax",
"fieldtype": "Data",
"hidden": 0,
@@ -2699,6 +2815,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "email",
"fieldtype": "Data",
"hidden": 0,
@@ -2733,6 +2850,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "website",
"fieldtype": "Data",
"hidden": 0,
@@ -2767,6 +2885,7 @@
"collapsible": 0,
"columns": 0,
"description": "",
+ "fetch_if_empty": 0,
"fieldname": "registration_info",
"fieldtype": "Section Break",
"hidden": 0,
@@ -2801,6 +2920,7 @@
"collapsible": 0,
"columns": 0,
"description": "Company registration numbers for your reference. Tax numbers etc.",
+ "fetch_if_empty": 0,
"fieldname": "registration_details",
"fieldtype": "Code",
"hidden": 0,
@@ -2834,6 +2954,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "delete_company_transactions",
"fieldtype": "Button",
"hidden": 0,
@@ -2866,6 +2987,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
@@ -2898,6 +3020,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
@@ -2930,6 +3053,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fetch_if_empty": 0,
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
@@ -2969,7 +3093,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2019-01-15 13:29:54.510379",
+ "modified": "2019-03-26 17:15:50.390548",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py
index ea3d103..32a03e7 100644
--- a/erpnext/stock/__init__.py
+++ b/erpnext/stock/__init__.py
@@ -8,16 +8,21 @@
{"doctype":"Role", "role_name":"Stock User", "name":"Stock User"},
{"doctype":"Role", "role_name":"Quality Manager", "name":"Quality Manager"},
{"doctype":"Item Group", "item_group_name":"All Item Groups", "is_group": 1},
- {"doctype":"Item Group", "item_group_name":"Default",
+ {"doctype":"Item Group", "item_group_name":"Default",
"parent_item_group":"All Item Groups", "is_group": 0},
]
-def get_warehouse_account_map():
+def get_warehouse_account_map(company=None):
if not frappe.flags.warehouse_account_map or frappe.flags.in_test:
warehouse_account = frappe._dict()
+ filters = {}
+ if company:
+ filters['company'] = company
+
for d in frappe.get_all('Warehouse',
fields = ["name", "account", "parent_warehouse", "company"],
+ filters = filters,
order_by="lft, rgt"):
if not d.account:
d.account = get_warehouse_account(d, warehouse_account)
@@ -57,6 +62,6 @@
frappe.throw(_("Please set Account in Warehouse {0} or Default Inventory Account in Company {1}")
.format(warehouse.name, warehouse.company))
return account
-
+
def get_company_default_inventory_account(company):
return frappe.get_cached_value('Company', company, 'default_inventory_account')
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index bd06688..8321b3e 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -758,6 +758,9 @@
d.conversion_factor = value
def validate_attributes(self):
+ if not self.variant_based_on:
+ self.variant_based_on = 'Item Attribute'
+
if (self.has_variants or self.variant_of) and self.variant_based_on == 'Item Attribute':
attributes = []
if not self.attributes:
@@ -780,7 +783,7 @@
variant = get_variant(self.variant_of, args, self.name)
if variant:
frappe.throw(_("Item variant {0} exists with same attributes")
- .format(variant), ItemVariantExistsError)
+ .format(variant), ItemVariantExistsError)
validate_item_variant_attributes(self, args)
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index d02559e..ac499e0 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -17,7 +17,7 @@
from six import iteritems
test_ignore = ["BOM"]
-test_dependencies = ["Warehouse", "Item Group"]
+test_dependencies = ["Warehouse", "Item Group", "Brand"]
def make_item(item_code, properties=None):
if frappe.db.exists("Item", item_code):
@@ -393,3 +393,6 @@
"company": "_Test Company"
})
item.save()
+ else:
+ item = frappe.get_doc("Item", item_code)
+ return item
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 3a52530..dc9c4fc 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -802,7 +802,7 @@
# item dict = { item_code: {qty, description, stock_uom} }
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty,
- fetch_exploded = self.use_multi_level_bom)
+ fetch_exploded = self.use_multi_level_bom, fetch_qty_in_stock_uom=False)
used_alternative_items = get_used_alternative_items(work_order = self.work_order)
for item in itervalues(item_dict):
@@ -1031,7 +1031,7 @@
se_child.item_code = item_dict[d].get('item_code') or cstr(d)
se_child.item_name = item_dict[d]["item_name"]
se_child.description = item_dict[d]["description"]
- se_child.uom = stock_uom
+ se_child.uom = item_dict[d]["uom"] if item_dict[d].get("uom") else stock_uom
se_child.stock_uom = stock_uom
se_child.qty = flt(item_dict[d]["qty"], se_child.precision("qty"))
se_child.expense_account = item_dict[d].get("expense_account") or expense_account
@@ -1049,8 +1049,9 @@
se_child.t_warehouse = self.to_warehouse
# in stock uom
- se_child.transfer_qty = flt(item_dict[d]["qty"], se_child.precision("qty"))
- se_child.conversion_factor = 1.00
+ se_child.conversion_factor = flt(item_dict[d].get("conversion_factor")) or 1
+ se_child.transfer_qty = flt(item_dict[d]["qty"]*se_child.conversion_factor, se_child.precision("qty"))
+
# to be assigned for finished item
se_child.bom_no = bom_no
diff --git a/erpnext/templates/pages/regional/india/update-gstin.html b/erpnext/templates/pages/regional/india/update-gstin.html
index 3d9ab5d..d738fb4 100644
--- a/erpnext/templates/pages/regional/india/update-gstin.html
+++ b/erpnext/templates/pages/regional/india/update-gstin.html
@@ -32,7 +32,7 @@
<p class='text-muted'>Please update your GSTIN for us to issue correct tax invoice</p>
<form method='GET' action='/regional/india/update-gstin.html'>
<input type='hidden' value='{{ party.name }}' name='party'>
- {% for address in party.__onload.addr_list %}
+ {% for address in party.get_onload('addr_list') %}
<div class='bordered' style='max-width: 300px; margin-bottom: 15px;'>
{{ address.display }}
<p><input type='text' class='form-control'