Merge pull request #2212 from nabinhait/hotfix

Fetch and validate advance entries in sales/purchase invoice
This commit is contained in:
Nabin Hait 2014-09-19 14:41:20 +05:30
commit 6a92d51383
5 changed files with 64 additions and 36 deletions

View File

@ -49,6 +49,7 @@ class PurchaseInvoice(BuyingController):
self.check_conversion_rate() self.check_conversion_rate()
self.validate_credit_acc() self.validate_credit_acc()
self.clear_unallocated_advances("Purchase Invoice Advance", "advance_allocation_details") self.clear_unallocated_advances("Purchase Invoice Advance", "advance_allocation_details")
self.validate_advance_jv("advance_allocation_details", "purchase_order")
self.check_for_acc_head_of_supplier() self.check_for_acc_head_of_supplier()
self.check_for_stopped_status() self.check_for_stopped_status()
self.validate_with_previous_doc() self.validate_with_previous_doc()
@ -80,7 +81,7 @@ class PurchaseInvoice(BuyingController):
def get_advances(self): def get_advances(self):
super(PurchaseInvoice, self).get_advances(self.credit_to, super(PurchaseInvoice, self).get_advances(self.credit_to,
"Purchase Invoice Advance", "advance_allocation_details", "debit") "Purchase Invoice Advance", "advance_allocation_details", "debit", "purchase_order")
def check_active_purchase_items(self): def check_active_purchase_items(self):
for d in self.get('entries'): for d in self.get('entries'):

View File

@ -56,6 +56,7 @@ class SalesInvoice(SellingController):
self.validate_debit_acc() self.validate_debit_acc()
self.validate_fixed_asset_account() self.validate_fixed_asset_account()
self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details") self.clear_unallocated_advances("Sales Invoice Advance", "advance_adjustment_details")
self.validate_advance_jv("advance_adjustment_details", "sales_order")
self.add_remarks() self.add_remarks()
if cint(self.is_pos): if cint(self.is_pos):
@ -222,7 +223,7 @@ class SalesInvoice(SellingController):
def get_advances(self): def get_advances(self):
super(SalesInvoice, self).get_advances(self.debit_to, super(SalesInvoice, self).get_advances(self.debit_to,
"Sales Invoice Advance", "advance_adjustment_details", "credit") "Sales Invoice Advance", "advance_adjustment_details", "credit", "sales_order")
def get_company_abbr(self): def get_company_abbr(self):
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0] return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]

View File

@ -4,9 +4,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe import _, throw from frappe import _, throw
from frappe.utils import add_days, cint, cstr, today, date_diff, flt, getdate, nowdate, \ from frappe.utils import cint, today, flt
get_first_day, get_last_day
from frappe.model.naming import make_autoname
from erpnext.setup.utils import get_company_currency, get_exchange_rate from erpnext.setup.utils import get_company_currency, get_exchange_rate
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
@ -362,30 +360,32 @@ class AccountsController(TransactionBase):
frappe.db.sql("""delete from `tab%s` where parentfield=%s and parent = %s frappe.db.sql("""delete from `tab%s` where parentfield=%s and parent = %s
and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name)) and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
def get_advances(self, account_head, child_doctype, parentfield, dr_or_cr): def get_advances(self, account_head, child_doctype, parentfield, dr_or_cr, against_order_field):
against_order_list = [] so_list = list(set([d.get(against_order_field) for d in self.get("entries") if d.get(against_order_field)]))
cond = ""
if so_list:
cond = "or (ifnull(t2.%s, '') in (%s))" % ("against_" + against_order_field, ', '.join(['%s']*len(so_list)))
res = frappe.db.sql(""" res = frappe.db.sql("""
select select
t1.name as jv_no, t1.remark, t2.%s as amount, t2.name as jv_detail_no, t2.%s as order_no t1.name as jv_no, t1.remark, t2.%s as amount, t2.name as jv_detail_no
from from
`tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2
where where
t1.name = t2.parent and t2.account = %s and t2.is_advance = 'Yes' and t1.docstatus = 1 t1.name = t2.parent and t2.account = %s and t2.is_advance = 'Yes' and t1.docstatus = 1
and ifnull(t2.against_voucher, '') = '' and ((
ifnull(t2.against_voucher, '') = ''
and ifnull(t2.against_invoice, '') = '' and ifnull(t2.against_invoice, '') = ''
and ifnull(t2.against_jv, '') = '' and ifnull(t2.against_jv, '') = ''
and ifnull(t2.against_sales_order, '') = ''
and ifnull(t2.against_purchase_order, '') = ''
) %s)
order by t1.posting_date""" % order by t1.posting_date""" %
(dr_or_cr, "against_sales_order" if dr_or_cr == "credit" \ (dr_or_cr, '%s', cond),
else "against_purchase_order", '%s'), tuple([account_head] + so_list), as_dict= True)
account_head, as_dict= True)
if self.get("entries"):
for i in self.get("entries"):
against_order_list.append(i.sales_order if dr_or_cr == "credit" else i.purchase_order)
self.set(parentfield, []) self.set(parentfield, [])
for d in res: for d in res:
if not against_order_list or d.order_no in against_order_list:
self.append(parentfield, { self.append(parentfield, {
"doctype": child_doctype, "doctype": child_doctype,
"journal_voucher": d.jv_no, "journal_voucher": d.jv_no,
@ -395,6 +395,33 @@ class AccountsController(TransactionBase):
"allocate_amount": 0 "allocate_amount": 0
}) })
def validate_advance_jv(self, advance_table_fieldname, against_order_field):
order_list = list(set([d.get(against_order_field) for d in self.get("entries") if d.get(against_order_field)]))
if order_list:
account = self.get("debit_to" if self.doctype=="Sales Invoice" else "credit_to")
jv_against_order = frappe.db.sql("""select parent, %s as against_order
from `tabJournal Voucher Detail`
where docstatus=1 and account=%s and ifnull(is_advance, 'No') = 'Yes'
and ifnull(against_sales_order, '') in (%s)
group by parent, against_sales_order""" %
("against_" + against_order_field, '%s', ', '.join(['%s']*len(order_list))),
tuple([account] + order_list), as_dict=1)
if jv_against_order:
order_jv_map = {}
for d in jv_against_order:
order_jv_map.setdefault(d.against_order, []).append(d.parent)
advance_jv_against_si = [d.journal_voucher for d in self.get(advance_table_fieldname)]
for order, jv_list in order_jv_map.items():
for jv in jv_list:
if not advance_jv_against_si or jv not in advance_jv_against_si:
frappe.throw(_("Journal Voucher {0} is linked against Order {1}, hence it must be fetched as advance in Invoice as well.")
.format(jv, order))
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from erpnext.controllers.status_updater import get_tolerance_for from erpnext.controllers.status_updater import get_tolerance_for
item_tolerance = {} item_tolerance = {}
@ -421,7 +448,6 @@ class AccountsController(TransactionBase):
max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100) max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100)
if total_billed_amt - max_allowed_amt > 0.01: if total_billed_amt - max_allowed_amt > 0.01:
reduce_by = total_billed_amt - max_allowed_amt
frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt)) frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
def get_company_default(self, fieldname): def get_company_default(self, fieldname):

View File

@ -6,7 +6,7 @@ frappe.views.calendar["Task"] = {
"start": "exp_start_date", "start": "exp_start_date",
"end": "exp_end_date", "end": "exp_end_date",
"id": "name", "id": "name",
"title": __("subject"), "title": "subject",
"allDay": "allDay" "allDay": "allDay"
}, },
gantt: true, gantt: true,

View File

@ -40,7 +40,7 @@ class AuthorizationControl(TransactionBase):
chk = 1 chk = 1
add_cond1,add_cond2 = '','' add_cond1,add_cond2 = '',''
if based_on == 'Itemwise Discount': if based_on == 'Itemwise Discount':
add_cond1 += " and master_name = '"+cstr(item).replace("'", "\'")+"'" add_cond1 += " and master_name = '"+cstr(item).replace("'", "\\'")+"'"
itemwise_exists = frappe.db.sql("""select value from `tabAuthorization Rule` itemwise_exists = frappe.db.sql("""select value from `tabAuthorization Rule`
where transaction = %s and value <= %s where transaction = %s and value <= %s
and based_on = %s and company = %s and docstatus != 2 %s %s""" % and based_on = %s and company = %s and docstatus != 2 %s %s""" %
@ -76,7 +76,7 @@ class AuthorizationControl(TransactionBase):
add_cond = '' add_cond = ''
auth_value = av_dis auth_value = av_dis
if val == 1: add_cond += " and system_user = '"+session['user'].replace("'", "\'")+"'" if val == 1: add_cond += " and system_user = '"+session['user'].replace("'", "\\'")+"'"
elif val == 2: add_cond += " and system_role IN %s" % ("('"+"','".join(frappe.user.get_roles())+"')") elif val == 2: add_cond += " and system_role IN %s" % ("('"+"','".join(frappe.user.get_roles())+"')")
else: add_cond += " and ifnull(system_user,'') = '' and ifnull(system_role,'') = ''" else: add_cond += " and ifnull(system_user,'') = '' and ifnull(system_role,'') = ''"
@ -85,7 +85,7 @@ class AuthorizationControl(TransactionBase):
if doc_obj: if doc_obj:
if doc_obj.doctype == 'Sales Invoice': customer = doc_obj.customer if doc_obj.doctype == 'Sales Invoice': customer = doc_obj.customer
else: customer = doc_obj.customer_name else: customer = doc_obj.customer_name
add_cond = " and master_name = '"+cstr(customer).replace("'", "\'")+"'" add_cond = " and master_name = '"+cstr(customer).replace("'", "\\'")+"'"
if based_on == 'Itemwise Discount': if based_on == 'Itemwise Discount':
if doc_obj: if doc_obj:
for t in doc_obj.get(doc_obj.fname): for t in doc_obj.get(doc_obj.fname):