recurring invoice test cases, set period start date and period end date as first and last day of the month if previously so, else just add months
This commit is contained in:
parent
f0a8406d31
commit
407331675f
@ -10,5 +10,15 @@ test_records = [
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2014",
|
||||
"year_start_date": "2014-01-01"
|
||||
}]
|
||||
}],
|
||||
[{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2015",
|
||||
"year_start_date": "2015-01-01"
|
||||
}],
|
||||
[{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2016",
|
||||
"year_start_date": "2016-01-01"
|
||||
}],
|
||||
]
|
@ -17,7 +17,9 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import add_days, cint, cstr, date_diff, flt, getdate, nowdate
|
||||
from webnotes.utils import add_days, cint, cstr, date_diff, flt, getdate, nowdate, \
|
||||
get_first_day, get_last_day
|
||||
|
||||
from webnotes.utils.email_lib import sendmail
|
||||
from webnotes.utils import comma_and
|
||||
from webnotes.model.doc import make_autoname
|
||||
@ -891,25 +893,18 @@ class DocType(SellingController):
|
||||
|
||||
next_date = get_next_date(self.doc.posting_date,
|
||||
month_map[self.doc.recurring_type], cint(self.doc.repeat_on_day_of_month))
|
||||
|
||||
webnotes.conn.set(self.doc, 'next_date', next_date)
|
||||
|
||||
def get_next_date(dt, mcount, day=None):
|
||||
import datetime
|
||||
month = getdate(dt).month + mcount
|
||||
year = getdate(dt).year
|
||||
if not day:
|
||||
day = getdate(dt).day
|
||||
if month > 12:
|
||||
month, year = month-12, year+1
|
||||
try:
|
||||
next_month_date = datetime.date(year, month, day)
|
||||
except:
|
||||
import calendar
|
||||
last_day = calendar.monthrange(year, month)[1]
|
||||
next_month_date = datetime.date(year, month, last_day)
|
||||
return next_month_date.strftime("%Y-%m-%d")
|
||||
|
||||
def manage_recurring_invoices(next_date=None):
|
||||
dt = getdate(dt)
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
dt += relativedelta(months=mcount, day=day)
|
||||
|
||||
return dt
|
||||
|
||||
def manage_recurring_invoices(next_date=None, commit=True):
|
||||
"""
|
||||
Create recurring invoices on specific date by copying the original one
|
||||
and notify the concerned people
|
||||
@ -929,19 +924,22 @@ def manage_recurring_invoices(next_date=None):
|
||||
ref_wrapper = webnotes.bean('Sales Invoice', ref_invoice)
|
||||
new_invoice_wrapper = make_new_invoice(ref_wrapper, next_date)
|
||||
send_notification(new_invoice_wrapper)
|
||||
webnotes.conn.commit()
|
||||
if commit:
|
||||
webnotes.conn.commit()
|
||||
except:
|
||||
webnotes.conn.rollback()
|
||||
if commit:
|
||||
webnotes.conn.rollback()
|
||||
|
||||
webnotes.conn.begin()
|
||||
webnotes.conn.sql("update `tabSales Invoice` set \
|
||||
convert_into_recurring_invoice = 0 where name = %s", ref_invoice)
|
||||
notify_errors(ref_invoice, ref_wrapper.doc.owner)
|
||||
webnotes.conn.commit()
|
||||
webnotes.conn.begin()
|
||||
webnotes.conn.sql("update `tabSales Invoice` set \
|
||||
convert_into_recurring_invoice = 0 where name = %s", ref_invoice)
|
||||
notify_errors(ref_invoice, ref_wrapper.doc.owner)
|
||||
webnotes.conn.commit()
|
||||
|
||||
exception_list.append(webnotes.getTraceback())
|
||||
finally:
|
||||
webnotes.conn.begin()
|
||||
if commit:
|
||||
webnotes.conn.begin()
|
||||
|
||||
if exception_list:
|
||||
exception_message = "\n\n".join([cstr(d) for d in exception_list])
|
||||
@ -953,19 +951,27 @@ def make_new_invoice(ref_wrapper, posting_date):
|
||||
new_invoice = clone(ref_wrapper)
|
||||
|
||||
mcount = month_map[ref_wrapper.doc.recurring_type]
|
||||
|
||||
|
||||
invoice_period_from_date = get_next_date(ref_wrapper.doc.invoice_period_from_date, mcount)
|
||||
|
||||
# get last day of the month to maintain period if the from date is first day of its own month
|
||||
# and to date is the last day of its own month
|
||||
if (cstr(get_first_day(ref_wrapper.doc.invoice_period_from_date)) == \
|
||||
cstr(ref_wrapper.doc.invoice_period_from_date)) and \
|
||||
(cstr(get_last_day(ref_wrapper.doc.invoice_period_to_date)) == \
|
||||
cstr(ref_wrapper.doc.invoice_period_to_date)):
|
||||
invoice_period_to_date = get_last_day(get_next_date(ref_wrapper.doc.invoice_period_to_date,
|
||||
mcount))
|
||||
else:
|
||||
invoice_period_to_date = get_next_date(ref_wrapper.doc.invoice_period_to_date, mcount)
|
||||
|
||||
new_invoice.doc.fields.update({
|
||||
"posting_date": posting_date,
|
||||
"aging_date": posting_date,
|
||||
|
||||
"due_date": add_days(posting_date, cint(date_diff(ref_wrapper.doc.due_date,
|
||||
ref_wrapper.doc.posting_date))),
|
||||
|
||||
"invoice_period_from_date": \
|
||||
get_next_date(ref_wrapper.doc.invoice_period_from_date, mcount),
|
||||
|
||||
"invoice_period_to_date": \
|
||||
get_next_date(ref_wrapper.doc.invoice_period_to_date, mcount),
|
||||
"invoice_period_from_date": invoice_period_from_date,
|
||||
"invoice_period_to_date": invoice_period_to_date,
|
||||
"fiscal_year": get_fiscal_year(posting_date)[0],
|
||||
"owner": ref_wrapper.doc.owner,
|
||||
})
|
||||
|
@ -1,8 +1,8 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-03-12 11:56:25",
|
||||
"creation": "2013-03-20 17:01:58",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-03-12 14:31:24",
|
||||
"modified": "2013-03-20 19:17:38",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -1093,7 +1093,7 @@
|
||||
"description": "The day of the month on which auto invoice will be generated e.g. 05, 28 etc ",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "repeat_on_day_of_month",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Int",
|
||||
"label": "Repeat on Day of Month",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1
|
||||
|
@ -332,7 +332,142 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
self.assertTrue(not webnotes.conn.sql("""select name from `tabJournal Voucher Detail`
|
||||
where against_invoice=%s""", si.doc.name))
|
||||
|
||||
def test_recurring_invoice(self):
|
||||
from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date
|
||||
today = now_datetime().date()
|
||||
|
||||
base_si = webnotes.bean(copy=test_records[0])
|
||||
base_si.doc.fields.update({
|
||||
"convert_into_recurring_invoice": 1,
|
||||
"recurring_type": "Monthly",
|
||||
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
|
||||
"repeat_on_day_of_month": today.day,
|
||||
"posting_date": today,
|
||||
"invoice_period_from_date": get_first_day(today),
|
||||
"invoice_period_to_date": get_last_day(today)
|
||||
})
|
||||
|
||||
# monthly
|
||||
si1 = webnotes.bean(copy=base_si.doclist)
|
||||
si1.insert()
|
||||
si1.submit()
|
||||
self._test_recurring_invoice(si1, True)
|
||||
|
||||
# monthly without a first and last day period
|
||||
si2 = webnotes.bean(copy=base_si.doclist)
|
||||
si2.doc.fields.update({
|
||||
"invoice_period_from_date": today,
|
||||
"invoice_period_to_date": add_to_date(today, days=30)
|
||||
})
|
||||
si2.insert()
|
||||
si2.submit()
|
||||
self._test_recurring_invoice(si2, False)
|
||||
|
||||
# quarterly
|
||||
si3 = webnotes.bean(copy=base_si.doclist)
|
||||
si3.doc.fields.update({
|
||||
"recurring_type": "Quarterly",
|
||||
"invoice_period_from_date": get_first_day(today),
|
||||
"invoice_period_to_date": get_last_day(add_to_date(today, months=3))
|
||||
})
|
||||
si3.insert()
|
||||
si3.submit()
|
||||
self._test_recurring_invoice(si3, True)
|
||||
|
||||
# quarterly without a first and last day period
|
||||
si4 = webnotes.bean(copy=base_si.doclist)
|
||||
si4.doc.fields.update({
|
||||
"recurring_type": "Quarterly",
|
||||
"invoice_period_from_date": today,
|
||||
"invoice_period_to_date": add_to_date(today, months=3)
|
||||
})
|
||||
si4.insert()
|
||||
si4.submit()
|
||||
self._test_recurring_invoice(si4, False)
|
||||
|
||||
# yearly
|
||||
si5 = webnotes.bean(copy=base_si.doclist)
|
||||
si5.doc.fields.update({
|
||||
"recurring_type": "Yearly",
|
||||
"invoice_period_from_date": get_first_day(today),
|
||||
"invoice_period_to_date": get_last_day(add_to_date(today, years=1))
|
||||
})
|
||||
si5.insert()
|
||||
si5.submit()
|
||||
self._test_recurring_invoice(si5, True)
|
||||
|
||||
# yearly without a first and last day period
|
||||
si6 = webnotes.bean(copy=base_si.doclist)
|
||||
si6.doc.fields.update({
|
||||
"recurring_type": "Yearly",
|
||||
"invoice_period_from_date": today,
|
||||
"invoice_period_to_date": add_to_date(today, years=1)
|
||||
})
|
||||
si6.insert()
|
||||
si6.submit()
|
||||
self._test_recurring_invoice(si6, False)
|
||||
|
||||
# change posting date but keep recuring day to be today
|
||||
si7 = webnotes.bean(copy=base_si.doclist)
|
||||
si7.doc.fields.update({
|
||||
"posting_date": add_to_date(today, days=-3)
|
||||
})
|
||||
si7.insert()
|
||||
si7.submit()
|
||||
|
||||
# setting so that _test function works
|
||||
si7.doc.posting_date = today
|
||||
self._test_recurring_invoice(si7, True)
|
||||
|
||||
def _test_recurring_invoice(self, base_si, first_and_last_day):
|
||||
from webnotes.utils import add_months, get_last_day, getdate
|
||||
from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices
|
||||
|
||||
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.doc.recurring_type]
|
||||
|
||||
def _test(i):
|
||||
self.assertEquals(i+1, webnotes.conn.sql("""select count(*) from `tabSales Invoice`
|
||||
where recurring_id=%s and docstatus=1""", base_si.doc.recurring_id)[0][0])
|
||||
|
||||
next_date = add_months(base_si.doc.posting_date, no_of_months)
|
||||
|
||||
manage_recurring_invoices(next_date=next_date, commit=False)
|
||||
|
||||
recurred_invoices = webnotes.conn.sql("""select name from `tabSales Invoice`
|
||||
where recurring_id=%s and docstatus=1 order by name desc""", base_si.doc.recurring_id)
|
||||
|
||||
self.assertEquals(i+2, len(recurred_invoices))
|
||||
|
||||
new_si = webnotes.bean("Sales Invoice", recurred_invoices[0][0])
|
||||
|
||||
for fieldname in ["convert_into_recurring_invoice", "recurring_type",
|
||||
"repeat_on_day_of_month", "notification_email_address"]:
|
||||
self.assertEquals(base_si.doc.fields.get(fieldname),
|
||||
new_si.doc.fields.get(fieldname))
|
||||
|
||||
self.assertEquals(new_si.doc.posting_date, unicode(next_date))
|
||||
|
||||
self.assertEquals(new_si.doc.invoice_period_from_date,
|
||||
unicode(add_months(base_si.doc.invoice_period_from_date, no_of_months)))
|
||||
|
||||
if first_and_last_day:
|
||||
self.assertEquals(new_si.doc.invoice_period_to_date,
|
||||
unicode(get_last_day(add_months(base_si.doc.invoice_period_to_date,
|
||||
no_of_months))))
|
||||
else:
|
||||
self.assertEquals(new_si.doc.invoice_period_to_date,
|
||||
unicode(add_months(base_si.doc.invoice_period_to_date, no_of_months)))
|
||||
|
||||
self.assertEquals(getdate(new_si.doc.posting_date).day,
|
||||
base_si.doc.repeat_on_day_of_month)
|
||||
|
||||
return new_si
|
||||
|
||||
# if yearly, test 3 repetitions, else test 13 repetitions
|
||||
count = no_of_months == 12 and 3 or 13
|
||||
for i in xrange(count):
|
||||
base_si = _test(i)
|
||||
|
||||
test_dependencies = ["Journal Voucher", "POS Setting"]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user