oadam / proprio

A free property management software to manage your tenancies
MIT License
20 stars 13 forks source link

Enable calculation of partial month rent for partial month tenancy #28

Closed vectorien closed 8 years ago

vectorien commented 8 years ago

Hi, as mendtioned in the now closed PR https://github.com/oadam/proprio/pull/21, I think it is a good idea to enable the calculation of partial month rents.

In the case that we calculate the rent for a tenancy based on the begin/end of a tenancy (AND independently of the rentrevision dates), I think we need to introduce the parameters tenancy_begin_date, tenancy_end_date into the function revision_to_cashflows

Proposal:

def revision_to_cashflows(rev, end_date, tenancy_begin_date = date(2015, 6, 1), tenancy_end_date = date(2015, 12, 13)):
    """Converts a revision to a list of cashflows
    end_date -- the first month we do not want to take into account
    """
    end_date = rev.end_date or end_date
    if not end_date:
        end_date = next_month(date.today(),1)

    start_date = rev.start_date

    if not tenancy_end_date:
        tenancy_end_date = next_month(date.today(),1)

    delta_t = (tenancy_end_date - tenancy_begin_date).days 
    #list of dates from d1 to d2
    tenancy_date_list = [tenancy_begin_date + timedelta(days=x) for x in range(0, delta_t+1)]

    delta_r = (end_date - start_date).days 
    #list of dates from d1 to d2
    revision_date_list = [start_date + timedelta(days=x) for x in range(0, delta_r+1)]

    intersect_date_list = list(set(revision_date_list).intersection(set(tenancy_date_list)))

    result = []

    month_year_list = [(d.year, d.month) for d in intersect_date_list]

    #generate-list-of-tuples (year,month, days-in-month, full-month) from-list-of-dates

    year_month_ndays_full = [(k[0],k[1],v , True if  monthrange(k[0], k[1])[1] == v else False) for k,v in Counter(month_year_list).iteritems()]

    for d in year_month_ndays_full:

        date_info = date(d[0],d[1],1)
        #if full month
        if d[3] == True:
            result.append(Cashflow(date_info, - rev.rent, _('RENT ') ))
            if rev.provision != 0:
                result.append(Cashflow(date_info, -rev.provision, _('PROVISION ') ))

        #if partial month, divide by days of month rented
        else:
            daysinmonth = monthrange(date_info.year, date_info.month)[1]
            rented_days = d[2]

            result.append(Cashflow(date_info, -(rev.rent/daysinmonth*rented_days),\
             ungettext("RENT for %(day)s day in partial month",\
                "RENT for %(day)s days in in partial month", rented_days) % {'day': str(rented_days)}))
            if rev.provision != 0:
                result.append(Cashflow(date_info, -(rev.provision/daysinmonth*rented_days), \
                    ungettext("PROVISION for %(day)s day in partial month",\
                        "PROVISION for %(day)s days in in partial month", rented_days) % {'day': str(rented_days)}))
    return result

Of course the TenantBalanceTests will have to be widely adapted then.

Happy to learn about a simpler approach ;-)

vectorien commented 8 years ago

An alternative would be to completely remove tenancy_begin/end_date from the admin panel too, because as of now, they dont have any functionality, and can lead to misunderstandings for new users when creating a new tenant..

oadam commented 8 years ago

I agree with you that these fields should not exist ! At first we were using the notes field to store them. But my users insisted to have a dedicated field to store it, even though my opinion is that anything that's not used in calculations should go in notes... Maybe django has an option to add a disclaimer in the admin, so that we can tell users that these dates are not used. Le 19 nov. 2015 7:26 PM, "vectorien" notifications@github.com a écrit :

An alternative would be to completely remove tenancy_begin/end_date from the admin panel too, because as of now, they dont have any functionality, and can lead to misunderstandings for new users when creating a new tenant..

— Reply to this email directly or view it on GitHub https://github.com/oadam/proprio/issues/28#issuecomment-158146829.

vectorien commented 8 years ago

Ok so I remove them in the next PR?

oadam commented 8 years ago

No, unfortunately my users won't accept that. But you can definitely add a help_text on the fields to warn that they are not used at all. Le 20 nov. 2015 9:16 AM, "vectorien" notifications@github.com a écrit :

Ok so I remove them in the next PR?

— Reply to this email directly or view it on GitHub https://github.com/oadam/proprio/issues/28#issuecomment-158318583.

vectorien commented 8 years ago

Ok well I just saw that in models.py , the tenancy_end_date is being used:

def cashflows(self):
        if self.tenancy_end_date:
            last_revision_end_date = next_month(self.tenancy_end_date, -1)
oadam commented 8 years ago

Looks like a hack in case of missing end-date on the last rentrevision. You can remove it if you want Le 20 nov. 2015 12:08 PM, "vectorien" notifications@github.com a écrit :

Ok well I just saw that in models.py , the tenancy_end_date is being used:

def cashflows(self): if self.tenancy_end_date: last_revision_end_date = next_month(self.tenancy_end_date, -1)

— Reply to this email directly or view it on GitHub https://github.com/oadam/proprio/issues/28#issuecomment-158360603.