Merge branch 'develop'
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 64f6e28..0d53216 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1 +1 @@
-__version__ = '4.7.2'
+__version__ = '4.8.0'
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index dab2d82..4cc3d57 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -124,6 +124,10 @@
from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s
and account = %s and ifnull(against_voucher, '') = ''""",
(against_voucher, account))[0][0])
+ if not against_voucher_amount:
+ frappe.throw(_("Against Journal Voucher {0} is already adjusted against some other voucher")
+ .format(against_voucher))
+
bal = against_voucher_amount + bal
if against_voucher_amount < 0:
bal = -bal
diff --git a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py
index 3c67508..f9f6df1 100644
--- a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py
+++ b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py
@@ -88,15 +88,24 @@
def validate_against_jv(self):
for d in self.get('entries'):
if d.against_jv:
+ account_root_type = frappe.db.get_value("Account", d.account, "root_type")
+ if account_root_type == "Asset" and flt(d.debit) > 0:
+ frappe.throw(_("For {0}, only credit entries can be linked against another debit entry")
+ .format(d.account))
+ elif account_root_type == "Liability" and flt(d.credit) > 0:
+ frappe.throw(_("For {0}, only debit entries can be linked against another credit entry")
+ .format(d.account))
+
if d.against_jv == self.name:
frappe.throw(_("You can not enter current voucher in 'Against Journal Voucher' column"))
against_entries = frappe.db.sql("""select * from `tabJournal Voucher Detail`
where account = %s and docstatus = 1 and parent = %s
- and ifnull(against_jv, '') = ''""", (d.account, d.against_jv), as_dict=True)
+ and ifnull(against_jv, '') = '' and ifnull(against_invoice, '') = ''
+ and ifnull(against_voucher, '') = ''""", (d.account, d.against_jv), as_dict=True)
if not against_entries:
- frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched")
+ frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched against other voucher")
.format(d.against_jv, d.account))
else:
dr_or_cr = "debit" if d.credit > 0 else "credit"
@@ -153,7 +162,7 @@
and voucher_account != d.account:
frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} account") \
.format(d.idx, d.account, doctype, field_dict.get(doctype)))
-
+
if against_field in ["against_sales_order", "against_purchase_order"]:
if voucher_account != account_master_name:
frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} Name") \
@@ -165,7 +174,7 @@
def validate_against_invoice_fields(self, doctype, payment_against_voucher):
for voucher_no, payment_list in payment_against_voucher.items():
- voucher_properties = frappe.db.get_value(doctype, voucher_no,
+ voucher_properties = frappe.db.get_value(doctype, voucher_no,
["docstatus", "outstanding_amount"])
if voucher_properties[0] != 1:
@@ -177,7 +186,7 @@
def validate_against_order_fields(self, doctype, payment_against_voucher):
for voucher_no, payment_list in payment_against_voucher.items():
- voucher_properties = frappe.db.get_value(doctype, voucher_no,
+ voucher_properties = frappe.db.get_value(doctype, voucher_no,
["docstatus", "per_billed", "status", "advance_paid", "grand_total"])
if voucher_properties[0] != 1:
@@ -532,9 +541,10 @@
(filters["account"], "%%%s%%" % txt, start, page_len))
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
- return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
- from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail
- where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
+ return frappe.db.sql("""select distinct jv.name, jv.posting_date, jv.user_remark
+ from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jvd
+ where jvd.parent = jv.name and jvd.account = %s and jv.docstatus = 1
+ and (ifnull(jvd.against_invoice, '') = '' and ifnull(jvd.against_voucher, '') = '' and ifnull(jvd.against_jv, '') = '' )
and jv.%s like %s order by jv.name desc limit %s, %s""" %
("%s", searchfield, "%s", "%s", "%s"),
(filters["account"], "%%%s%%" % txt, start, page_len))
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index 97484da..bfcd63e 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -19,9 +19,9 @@
]
};
}
-
+
});
-
+
this.frm.set_query('bank_cash_account', function() {
if(!me.frm.doc.company) {
msgprint(__("Please select company first"));
@@ -35,12 +35,8 @@
};
}
});
-
- var help_content = '<i class="icon-hand-right"></i> ' + __("Note") + ':<br>'+
- '<ul>' + __("If you are unable to match the exact amount, then amend your Journal Voucher and split rows such that payment amount match the invoice amount.") + '</ul>';
- this.frm.set_value("reconcile_help", help_content);
},
-
+
get_unreconciled_entries: function() {
var me = this;
return this.frm.call({
@@ -48,12 +44,12 @@
method: 'get_unreconciled_entries',
callback: function(r, rt) {
var invoices = [];
-
+
$.each(me.frm.doc.payment_reconciliation_invoices || [], function(i, row) {
- if (row.invoice_number && !inList(invoices, row.invoice_number))
+ if (row.invoice_number && !inList(invoices, row.invoice_number))
invoices.push(row.invoice_number);
});
-
+
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
me.frm.doc.name).options = invoices.join("\n");
@@ -79,4 +75,4 @@
$.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
-cur_frm.add_fetch('party_account', 'master_type', 'party_type')
\ No newline at end of file
+cur_frm.add_fetch('party_account', 'master_type', 'party_type')
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
index 51cb306..bb07b46 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
@@ -118,19 +118,12 @@
"options": "Payment Reconciliation Invoice",
"permlevel": 0,
"read_only": 1
- },
- {
- "fieldname": "reconcile_help",
- "fieldtype": "Small Text",
- "label": "",
- "permlevel": 0,
- "read_only": 1
}
],
"hide_toolbar": 1,
"icon": "icon-resize-horizontal",
"issingle": 1,
- "modified": "2014-07-31 05:43:03.410832",
+ "modified": "2014-10-16 17:51:44.367107",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation",
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index a5a56ae..c6a2b05 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -124,7 +124,7 @@
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
lst = []
for e in self.get('payment_reconciliation_payments'):
- if e.invoice_type and e.invoice_number:
+ if e.invoice_type and e.invoice_number and e.allocated_amount:
lst.append({
'voucher_no' : e.journal_voucher,
'voucher_detail_no' : e.voucher_detail_number,
@@ -134,7 +134,7 @@
'is_advance' : e.is_advance,
'dr_or_cr' : dr_or_cr,
'unadjusted_amt' : flt(e.amount),
- 'allocated_amt' : flt(e.amount)
+ 'allocated_amt' : flt(e.allocated_amount)
})
if lst:
@@ -162,18 +162,23 @@
invoices_to_reconcile = []
for p in self.get("payment_reconciliation_payments"):
- if p.invoice_type and p.invoice_number:
+ if p.invoice_type and p.invoice_number and p.allocated_amount:
invoices_to_reconcile.append(p.invoice_number)
if p.invoice_number not in unreconciled_invoices.get(p.invoice_type, {}):
frappe.throw(_("{0}: {1} not found in Invoice Details table")
.format(p.invoice_type, p.invoice_number))
- if p.amount > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
- frappe.throw(_("Row {0}: Payment amount must be less than or equals to invoice outstanding amount. Please refer Note below.").format(p.idx))
+ if flt(p.allocated_amount) > flt(p.amount):
+ frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
+ .format(p.idx, p.allocated_amount, p.amount))
+
+ if flt(p.allocated_amount) > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
+ frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
+ .format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
if not invoices_to_reconcile:
- frappe.throw(_("Please select Invoice Type and Invoice Number in atleast one row"))
+ frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
def check_condition(self, dr_or_cr):
cond = self.from_date and " and posting_date >= '" + self.from_date + "'" or ""
diff --git a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
index 73fd0f5..6f576ca 100644
--- a/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
+++ b/erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
@@ -54,10 +54,19 @@
"permlevel": 0
},
{
+ "fieldname": "allocated_amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Allocated amount",
+ "permlevel": 0,
+ "precision": "",
+ "reqd": 1
+ },
+ {
"default": "Sales Invoice",
"fieldname": "invoice_type",
"fieldtype": "Select",
- "in_list_view": 1,
+ "in_list_view": 0,
"label": "Invoice Type",
"options": "\nSales Invoice\nPurchase Invoice\nJournal Voucher",
"permlevel": 0,
@@ -95,7 +104,7 @@
}
],
"istable": 1,
- "modified": "2014-07-21 16:53:56.206169",
+ "modified": "2014-10-16 17:40:54.040194",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Payment",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index fe989d8..febf4b0 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -4,7 +4,7 @@
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
app_icon = "icon-th"
app_color = "#e74c3c"
-app_version = "4.7.2"
+app_version = "4.8.0"
error_report_email = "support@erpnext.com"
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 864329d..079b7fc 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -245,7 +245,7 @@
sl_entries = []
for d in self.get_item_list():
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
- and d.warehouse:
+ and d.warehouse and flt(d['qty']):
self.update_reserved_qty(d)
sl_entries.append(self.get_sl_entries(d, {
diff --git a/erpnext/utilities/repost_stock.py b/erpnext/utilities/repost_stock.py
index 643bec9..f1ba179 100644
--- a/erpnext/utilities/repost_stock.py
+++ b/erpnext/utilities/repost_stock.py
@@ -73,7 +73,7 @@
from `tabPacked Item` dnpi_in
where item_code = %s and warehouse = %s
and parenttype="Sales Order"
- and item_code != parent_item
+ and item_code != parent_item
and exists (select * from `tabSales Order` so
where name = dnpi_in.parent and docstatus = 1 and status != 'Stopped')
) dnpi)
diff --git a/setup.py b/setup.py
index e567ea2..5c7fe9a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
from setuptools import setup, find_packages
import os
-version = "4.7.2"
+version = "4.8.0"
with open("requirements.txt", "r") as f:
install_requires = f.readlines()
diff --git a/test_sites/test_site/site_config.json b/test_sites/test_site/site_config.json
index 05bf562..12007b8 100644
--- a/test_sites/test_site/site_config.json
+++ b/test_sites/test_site/site_config.json
@@ -1,5 +1,6 @@
{
"db_name": "test_frappe",
"db_password": "test_frappe",
+ "admin_password": "admin",
"mute_emails": 1
}