Merge pull request #4068 from anandpdoshi/due-date-validation
if no party, don't validate due date based on credit days
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 2a74e29..feb367b 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
from __future__ import unicode_literals
-__version__ = '6.3.1'
+__version__ = '6.3.2'
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/gt_cuentas_plantilla.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/gt_cuentas_plantilla.json
new file mode 100644
index 0000000..f69b0bc
--- /dev/null
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/gt_cuentas_plantilla.json
@@ -0,0 +1,90 @@
+{
+ "country_code": "gt",
+ "name": "Cuentas de Guatemala",
+ "is_active": "Yes",
+ "tree": {
+ "Activos": {
+ "Activo Corriente": {
+ "Caja y Bancos": {},
+ "Cuentas por Cobrar": {},
+ "Impuestos por Cobrar": {
+ "IVA por Cobrar": {},
+ "Retenciones de IVA recibidas": {}
+ },
+ "Inventario": {}
+ },
+ "No Corriente": {
+ "Activos Fijos": {},
+ "Cargos Diferidos": {}
+ },
+ "root_type": "Asset"
+ },
+ "Pasivos": {
+ "Pasivo Corriente": {
+ "Proveedores": {
+ "Inventario Recibido pero No Cobrado": {
+ "account_type": "Stock Received But Not Billed"
+ }
+ },
+ "Impuestos por Pagar": {},
+ "Sueldos por Liquidar": {},
+ "Prestaciones": {},
+ "Cuentas por Pagar": {},
+ "Otras Cuentas por Pagar": {},
+ "Acreedores": {}
+ },
+ "Pasivo No Corriente": {
+ "Provisión para Indemnizaciones": {},
+ "Acreedores": {}
+ },
+ "root_type": "Liability"
+ },
+ "Patrimonio": {
+ "Capital": {},
+ "Utilidades Retenidas": {},
+ "Resultados del Ejercicio": {},
+ "root_type": "Asset"
+ },
+ "Costos": {
+ "Costo de Ventas": {},
+ "Costos Incluidos en la Valuación": {
+ "account_type": "Expenses Included In Valuation"
+ },
+ "Stock Adjustment": {
+ "account_type": "Stock Adjustment"
+ },
+ "root_type": "Expense"
+ },
+ "Gastos": {
+ "Gastos de Personal": {},
+ "Honorarios Profesionales": {},
+ "Servicios Básicos": {},
+ "Alquileres": {},
+ "Seguros": {},
+ "Mantenimiento": {},
+ "Depreciaciones": {},
+ "Gastos Diversos": {},
+ "root_type": "Expense"
+ },
+ "Ingresos": {
+ "Productos": {},
+ "Servicios": {},
+ "root_type": "Income"
+ },
+ "Otros Gastos y Productos Financieros": {
+ "Otros Ingresos": {
+ "Otros Gastos y Productos Financieros": {
+ "Intereses": {},
+ "Otros Gastos Financieros": {}
+ }
+ },
+ "Otros Gastos": {
+ "Otros Gastos y Productos Financieros": {
+ "Intereses": {},
+ "Otros Gastos Financieros": {}
+ }
+ },
+ "root_type": "Expense"
+ }
+ }
+}
\ No newline at end of file
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 21bd570..7cbd4dd 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -209,7 +209,8 @@
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
voucher_type, voucher_no, against_voucher_type, against_voucher, account_currency, remarks, {0}
from `tabGL Entry`
- where docstatus < 2 and party_type=%s {1} order by posting_date, party"""
+ where docstatus < 2 and party_type=%s and ifnull(party, '') != '' {1}
+ order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
return self.gl_entries
diff --git a/erpnext/accounts/report/trial_balance_for_party/__init__.py b/erpnext/accounts/report/trial_balance_for_party/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/report/trial_balance_for_party/__init__.py
diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js
new file mode 100644
index 0000000..45d7bc0
--- /dev/null
+++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.js
@@ -0,0 +1,59 @@
+// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.query_reports["Trial Balance for Party"] = {
+ "filters": [
+ {
+ "fieldname": "company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("company"),
+ "reqd": 1
+ },
+ {
+ "fieldname": "fiscal_year",
+ "label": __("Fiscal Year"),
+ "fieldtype": "Link",
+ "options": "Fiscal Year",
+ "default": frappe.defaults.get_user_default("fiscal_year"),
+ "reqd": 1,
+ "on_change": function(query_report) {
+ var fiscal_year = query_report.get_values().fiscal_year;
+ if (!fiscal_year) {
+ return;
+ }
+ frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
+ var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
+ query_report.filters_by_name.from_date.set_input(fy.year_start_date);
+ query_report.filters_by_name.to_date.set_input(fy.year_end_date);
+ query_report.trigger_refresh();
+ });
+ }
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.defaults.get_user_default("year_start_date"),
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.defaults.get_user_default("year_end_date"),
+ },
+ {
+ "fieldname":"party_type",
+ "label": __("Party Type"),
+ "fieldtype": "Select",
+ "options": ["Customer", "Supplier"],
+ "default": "Customer"
+ },
+ {
+ "fieldname": "show_zero_values",
+ "label": __("Show zero values"),
+ "fieldtype": "Check"
+ }
+ ]
+}
diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.json b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.json
new file mode 100644
index 0000000..630462d
--- /dev/null
+++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.json
@@ -0,0 +1,17 @@
+{
+ "add_total_row": 0,
+ "apply_user_permissions": 1,
+ "creation": "2015-09-22 10:28:45.762272",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "is_standard": "Yes",
+ "modified": "2015-09-22 10:28:45.762272",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Trial Balance for Party",
+ "owner": "Administrator",
+ "ref_doctype": "GL Entry",
+ "report_name": "Trial Balance for Party",
+ "report_type": "Script Report"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
new file mode 100644
index 0000000..2a47ce8
--- /dev/null
+++ b/erpnext/accounts/report/trial_balance_for_party/trial_balance_for_party.py
@@ -0,0 +1,195 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import flt, cint
+from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
+
+
+def execute(filters=None):
+ validate_filters(filters)
+
+ show_party_name = is_party_name_visible(filters)
+
+ columns = get_columns(filters, show_party_name)
+ data = get_data(filters, show_party_name)
+
+ return columns, data
+
+def get_data(filters, show_party_name):
+ party_name_field = "customer_name" if filters.get("party_type")=="Customer" else "supplier_name"
+ parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field], order_by="name")
+
+ opening_balances = get_opening_balances(filters)
+ balances_within_period = get_balances_within_period(filters)
+
+ data = []
+ total_debit, total_credit = 0, 0
+ for party in parties:
+ row = { "party": party.name }
+ if show_party_name:
+ row["party_name"] = party.get(party_name_field)
+
+ # opening
+ opening_debit, opening_credit = opening_balances.get(party.name, [0, 0])
+ row.update({
+ "opening_debit": opening_debit,
+ "opening_credit": opening_credit
+ })
+
+ # within period
+ debit, credit = balances_within_period.get(party.name, [0, 0])
+ row.update({
+ "debit": debit,
+ "credit": credit
+ })
+
+ # totals
+ total_debit += debit
+ total_credit += credit
+
+ # closing
+ closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit)
+ row.update({
+ "closing_debit": closing_debit,
+ "closing_credit": closing_credit
+ })
+
+ has_value = False
+ if (opening_debit or opening_credit or debit or credit or closing_debit or closing_credit):
+ has_value =True
+
+ if cint(filters.show_zero_values) or has_value:
+ data.append(row)
+
+ # Add total row
+ if total_debit or total_credit:
+ data.append({
+ "party": "'" + _("Totals") + "'",
+ "debit": total_debit,
+ "credit": total_credit
+ })
+
+ return data
+
+def get_opening_balances(filters):
+ gle = frappe.db.sql("""
+ select party, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
+ from `tabGL Entry`
+ where company=%(company)s
+ and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
+ and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
+ group by party""", {
+ "company": filters.company,
+ "from_date": filters.from_date,
+ "party_type": filters.party_type
+ }, as_dict=True)
+
+ opening = frappe._dict()
+ for d in gle:
+ opening_debit, opening_credit = toggle_debit_credit(d.opening_debit, d.opening_credit)
+ opening.setdefault(d.party, [opening_debit, opening_credit])
+
+ return opening
+
+def get_balances_within_period(filters):
+ gle = frappe.db.sql("""
+ select party, sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit
+ from `tabGL Entry`
+ where company=%(company)s
+ and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
+ and posting_date >= %(from_date)s and posting_date <= %(to_date)s
+ and ifnull(is_opening, 'No') = 'No'
+ group by party""", {
+ "company": filters.company,
+ "from_date": filters.from_date,
+ "to_date": filters.to_date,
+ "party_type": filters.party_type
+ }, as_dict=True)
+
+ balances_within_period = frappe._dict()
+ for d in gle:
+ balances_within_period.setdefault(d.party, [d.debit, d.credit])
+
+ return balances_within_period
+
+def toggle_debit_credit(debit, credit):
+ if flt(debit) > flt(credit):
+ debit = flt(debit) - flt(credit)
+ credit = 0.0
+ else:
+ credit = flt(credit) - flt(debit)
+ debit = 0.0
+
+ return debit, credit
+
+def get_columns(filters, show_party_name):
+ columns = [
+ {
+ "fieldname": "party",
+ "label": _(filters.party_type),
+ "fieldtype": "Link",
+ "options": filters.party_type,
+ "width": 200
+ },
+ {
+ "fieldname": "opening_debit",
+ "label": _("Opening (Dr)"),
+ "fieldtype": "Currency",
+ "width": 120
+ },
+ {
+ "fieldname": "opening_credit",
+ "label": _("Opening (Cr)"),
+ "fieldtype": "Currency",
+ "width": 120
+ },
+ {
+ "fieldname": "debit",
+ "label": _("Debit"),
+ "fieldtype": "Currency",
+ "width": 120
+ },
+ {
+ "fieldname": "credit",
+ "label": _("Credit"),
+ "fieldtype": "Currency",
+ "width": 120
+ },
+ {
+ "fieldname": "closing_debit",
+ "label": _("Closing (Dr)"),
+ "fieldtype": "Currency",
+ "width": 120
+ },
+ {
+ "fieldname": "closing_credit",
+ "label": _("Closing (Cr)"),
+ "fieldtype": "Currency",
+ "width": 120
+ }
+ ]
+
+ if show_party_name:
+ columns.insert(1, {
+ "fieldname": "party_name",
+ "label": _(filters.party_type) + " Name",
+ "fieldtype": "Data",
+ "width": 200
+ })
+
+ return columns
+
+def is_party_name_visible(filters):
+ show_party_name = False
+ if filters.get("party_type") == "Customer":
+ party_naming_by = frappe.db.get_single_value("Selling Settings", "cust_master_name")
+ else:
+ party_naming_by = frappe.db.get_single_value("Buying Settings", "supp_master_name")
+
+ if party_naming_by == "Naming Series":
+ show_party_name = True
+
+ return show_party_name
\ No newline at end of file
diff --git a/erpnext/change_log/current/trial_balance_for_party.md b/erpnext/change_log/current/trial_balance_for_party.md
new file mode 100644
index 0000000..3d93e25
--- /dev/null
+++ b/erpnext/change_log/current/trial_balance_for_party.md
@@ -0,0 +1 @@
+- Trial Balance for Customer and Supplier
\ No newline at end of file
diff --git a/erpnext/config/accounts.py b/erpnext/config/accounts.py
index 71a2d70..7fca256 100644
--- a/erpnext/config/accounts.py
+++ b/erpnext/config/accounts.py
@@ -189,6 +189,12 @@
},
{
"type": "report",
+ "name": "Trial Balance for Party",
+ "doctype": "GL Entry",
+ "is_query_report": True,
+ },
+ {
+ "type": "report",
"name": "Gross Profit",
"doctype": "Sales Invoice",
"is_query_report": True
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index e5e3903..2053694 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -29,7 +29,7 @@
"""
app_icon = "icon-th"
app_color = "#e74c3c"
-app_version = "6.3.1"
+app_version = "6.3.2"
github_link = "https://github.com/frappe/erpnext"
error_report_email = "support@erpnext.com"
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index b060fba..dcff06d 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -197,27 +197,26 @@
outstanding_based_on_so = flt(outstanding_based_on_so[0][0]) if outstanding_based_on_so else 0.0
# Outstanding based on Delivery Note
- outstanding_based_on_dn = frappe.db.sql("""
- select
- sum(
- (
- (ifnull(dn_item.amount, 0) - ifnull((select sum(ifnull(amount, 0))
- from `tabSales Invoice Item`
- where ifnull(dn_detail, '') = dn_item.name and docstatus = 1), 0)
- )/dn.base_net_total
- )*dn.base_grand_total
- )
+ unmarked_delivery_note_items = frappe.db.sql("""select
+ dn_item.name, dn_item.amount, dn.base_net_total, dn.base_grand_total
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
where
- dn.name = dn_item.parent and dn.customer=%s and dn.company=%s
+ dn.name = dn_item.parent
+ and dn.customer=%s and dn.company=%s
and dn.docstatus = 1 and dn.status != 'Stopped'
and ifnull(dn_item.against_sales_order, '') = ''
- and ifnull(dn_item.against_sales_invoice, '') = ''
- and ifnull(dn_item.amount, 0) > ifnull((select sum(ifnull(amount, 0))
- from `tabSales Invoice Item`
- where ifnull(dn_detail, '') = dn_item.name and docstatus = 1), 0)""", (customer, company))
+ and ifnull(dn_item.against_sales_invoice, '') = ''""", (customer, company), as_dict=True)
- outstanding_based_on_dn = flt(outstanding_based_on_dn[0][0]) if outstanding_based_on_dn else 0.0
+ outstanding_based_on_dn = 0.0
+
+ for dn_item in unmarked_delivery_note_items:
+ si_amount = frappe.db.sql("""select sum(ifnull(amount, 0))
+ from `tabSales Invoice Item`
+ where dn_detail = %s and docstatus = 1""", dn_item.name)[0][0]
+
+ if flt(dn_item.amount) > flt(si_amount):
+ outstanding_based_on_dn += ((flt(dn_item.amount) - flt(si_amount)) \
+ / dn_item.base_net_total) * dn_item.base_grand_total
return outstanding_based_on_gle + outstanding_based_on_so + outstanding_based_on_dn
diff --git a/erpnext/setup/page/setup_wizard/setup_wizard.py b/erpnext/setup/page/setup_wizard/setup_wizard.py
index a137033..764dd78 100644
--- a/erpnext/setup/page/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/page/setup_wizard/setup_wizard.py
@@ -92,8 +92,10 @@
if args.get("add_sample_data"):
try:
make_sample_data()
+ frappe.clear_cache()
except FiscalYearError:
pass
+
except:
if args:
traceback = frappe.get_traceback()
diff --git a/setup.py b/setup.py
index a6c2164..f2827d2 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-version = "6.3.1"
+version = "6.3.2"
with open("requirements.txt", "r") as f:
install_requires = f.readlines()