From 7d7471a8ccd822eeb0af70a2e5fbcaf81c305dc6 Mon Sep 17 00:00:00 2001 From: ljmwkx <1340053001@qq.com> Date: Mon, 6 Jan 2025 18:56:03 +0800 Subject: [PATCH] 1 --- .../models/property_lease_contract.py | 349 ++++++++++-------- 1 file changed, 187 insertions(+), 162 deletions(-) diff --git a/yuthon_property_approval/models/property_lease_contract.py b/yuthon_property_approval/models/property_lease_contract.py index 0dcc5245d..2e8b01c98 100644 --- a/yuthon_property_approval/models/property_lease_contract.py +++ b/yuthon_property_approval/models/property_lease_contract.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. import pandas as pd +import calendar from dateutil.relativedelta import relativedelta from datetime import datetime, timedelta @@ -186,77 +187,77 @@ class PropertyLeaseContract(models.Model): # start_time = end_of_range # return time_ranges - def my_compute_all_period_rent(self, start_date, end_date): - first_years_begin = self.first_years_begin if self.first_years_begin else 0 - increments_every_few_years = self.increments_every_few_years - monthly_amount = self.total_area * self.unit_price # 月租金 - unit_price = self.unit_price # 单价 - rent_free_period_month = 0 - # 先计算免租期 - # if self.rent_free_period_year: - # rent_free_period_month += self.rent_free_period_year * 12 - if self.rent_free_period_month: - rent_free_period_month += self.rent_free_period_month - free_start = start_date # 免租期开始 - if rent_free_period_month: - free_start = start_date + relativedelta(months=rent_free_period_month) - - all_period_rent = 0 - if not increments_every_few_years: - # 计算剩余日期 - delta = relativedelta(end_date, free_start) - months = delta.years * 12 + delta.months - all_period_rent += monthly_amount * months - else: - # 不递增年份的计算 - increments_start = free_start # 平稳和递增开始 - all_months = 0 # 第几月份 - # 有免递增年份的计算 - if first_years_begin: - first_index = 0 # 第几递增周期年 - divided_year_segments = self.divide_time_range_fixed(start_date, end_date, 12) - for segment_year in divided_year_segments: - first_index += 1 - increments_start = segment_year[1] - if first_years_begin and first_index >= first_years_begin: - # 进入 递增时间 跳出平稳计费极端 - break - delta = relativedelta(segment_year[1], segment_year[0]) - months = delta.years * 12 + delta.months - for month in range(months): - all_months += 1 - # 判断是否是免租期 - if all_months > rent_free_period_month: - all_period_rent += monthly_amount - # 开始递增 - divided_increments_segments = self.divide_time_range_fixed(increments_start, end_date, increments_every_few_years * 12) - index = 0 # 第几递增周期年 - for increments_year in divided_increments_segments: - index += 1 - """ - increment_percentage = fields.Float(string="递增百分比") - increment_price = fields.Float(string="递增单价") - increment_amount = fields.Float(string="递增金额") - """ - increments_month = 0 - if self.increment_method == "increment_price" and self.increment_value: - unit_price = unit_price + self.increment_value - monthly_amount = self.total_area * unit_price - if self.increment_method == "percentage" and self.increment_value: - monthly_amount = monthly_amount * self.increment_value - if self.increment_method == "increment_amount" and self.increment_value: - monthly_amount = monthly_amount + self.increment_value - delta = relativedelta(increments_year[1], increments_year[0]) - months = delta.years * 12 + delta.months - # 判断第几月份进入 付费租期 - for month in range(months): - all_months += 1 - # 判断是否是免租期 - if all_months > rent_free_period_month: - increments_month += 1 - if increments_month: - all_period_rent += monthly_amount * increments_month - return all_period_rent + # def my_compute_all_period_rent(self, start_date, end_date): + # first_years_begin = self.first_years_begin if self.first_years_begin else 0 + # increments_every_few_years = self.increments_every_few_years + # monthly_amount = self.total_area * self.unit_price # 月租金 + # unit_price = self.unit_price # 单价 + # rent_free_period_month = 0 + # # 先计算免租期 + # # if self.rent_free_period_year: + # # rent_free_period_month += self.rent_free_period_year * 12 + # if self.rent_free_period_month: + # rent_free_period_month += self.rent_free_period_month + # free_start = start_date # 免租期开始 + # if rent_free_period_month: + # free_start = start_date + relativedelta(months=rent_free_period_month) + # + # all_period_rent = 0 + # if not increments_every_few_years: + # # 计算剩余日期 + # delta = relativedelta(end_date, free_start) + # months = delta.years * 12 + delta.months + # all_period_rent += monthly_amount * months + # else: + # # 不递增年份的计算 + # increments_start = free_start # 平稳和递增开始 + # all_months = 0 # 第几月份 + # # 有免递增年份的计算 + # if first_years_begin: + # first_index = 0 # 第几递增周期年 + # divided_year_segments = self.divide_time_range_fixed(start_date, end_date, 12) + # for segment_year in divided_year_segments: + # first_index += 1 + # increments_start = segment_year[1] + # if first_years_begin and first_index >= first_years_begin: + # # 进入 递增时间 跳出平稳计费极端 + # break + # delta = relativedelta(segment_year[1], segment_year[0]) + # months = delta.years * 12 + delta.months + # for month in range(months): + # all_months += 1 + # # 判断是否是免租期 + # if all_months > rent_free_period_month: + # all_period_rent += monthly_amount + # # 开始递增 + # divided_increments_segments = self.divide_time_range_fixed(increments_start, end_date, increments_every_few_years * 12) + # index = 0 # 第几递增周期年 + # for increments_year in divided_increments_segments: + # index += 1 + # """ + # increment_percentage = fields.Float(string="递增百分比") + # increment_price = fields.Float(string="递增单价") + # increment_amount = fields.Float(string="递增金额") + # """ + # increments_month = 0 + # if self.increment_method == "increment_price" and self.increment_value: + # unit_price = unit_price + self.increment_value + # monthly_amount = self.total_area * unit_price + # if self.increment_method == "percentage" and self.increment_value: + # monthly_amount = monthly_amount * self.increment_value + # if self.increment_method == "increment_amount" and self.increment_value: + # monthly_amount = monthly_amount + self.increment_value + # delta = relativedelta(increments_year[1], increments_year[0]) + # months = delta.years * 12 + delta.months + # # 判断第几月份进入 付费租期 + # for month in range(months): + # all_months += 1 + # # 判断是否是免租期 + # if all_months > rent_free_period_month: + # increments_month += 1 + # if increments_month: + # all_period_rent += monthly_amount * increments_month + # return all_period_rent def action_generate_rental_charges(self): """ @@ -272,7 +273,7 @@ class PropertyLeaseContract(models.Model): start_date = record.term_start_time end_date = record.term_end_time + relativedelta(days=1) - all_period_rent = record.my_compute_all_period_rent(start_date, end_date) + all_period_rent = record.do_generate_details_core(start_date, end_date) self.sudo().env["property.rent.list"].create({ "contract_id": record.id, @@ -316,31 +317,35 @@ class PropertyLeaseContract(models.Model): # todo 还没有计算递增递减 # todo 还没有计算首月优惠 # todo 还没有计算开始和结束不足月份和季度的计算比例 - record = self - if not record.term_start_time: - raise UserError(_("请填写租期开始时间!")) - if not record.term_end_time: - raise UserError(_("请填写租期结束时间!")) - self.write({'breakdown_ids': [(5, 0, 0)]}) - # self.sudo().env["property.rent.breakdown.line"].search([("breakdown_id", "in", record.ids)]).unlink() + for record in self: + if not record.term_start_time: + raise UserError(_("请填写租期开始时间!")) + if not record.term_end_time: + raise UserError(_("请填写租期结束时间!")) + record.write({'breakdown_ids': [(5, 0, 0)]}) + start_date = record.term_start_time + end_date = record.term_end_time + relativedelta(days=1) + record.do_generate_details_core(start_date, end_date) - start_date = record.term_start_time - end_date = record.term_end_time + relativedelta(days=1) + + def do_generate_details_core(record, start_date, end_date): + """ + 计算核心算法 + :return: + """ + all_period_rent = 0 first_years_begin = record.first_years_begin if record.first_years_begin else 0 increments_every_few_years = record.increments_every_few_years - monthly_amount = record.total_area * record.unit_price # 月租金 unit_price = record.unit_price # 单价 rent_free_period_month = 0 - # 先计算免租期 - # if record.rent_free_period_year: - # rent_free_period_month += record.rent_free_period_year * 12 if record.rent_free_period_month: rent_free_period_month += record.rent_free_period_month free_start = start_date # 免租期开始 if rent_free_period_month: free_start = start_date + relativedelta(months=rent_free_period_month) - self.sudo().write({'breakdown_ids': [(0, 0, { + + record.sudo().write({'breakdown_ids': [(0, 0, { "unit_price": unit_price, "monthly_amount": monthly_amount, "breakdown_id": record.id, @@ -349,91 +354,97 @@ class PropertyLeaseContract(models.Model): "month_number": rent_free_period_month, "period_rent": 0, })]}) - # self.sudo().env["property.rent.breakdown.line"].create({ - # "unit_price": unit_price, - # "monthly_amount": monthly_amount, - # "breakdown_id": record.id, - # "start_data": start_date, - # "end_data": free_start - relativedelta(days=1), - # "month_number": rent_free_period_month, - # "period_rent": 0, - # }) - # 在计算递增平稳年份租期 - - increments_start = free_start # 递增开始 # 如果没有递增 那么计算全部 if not increments_every_few_years: + # 如果免租期有天那么默认增加一个月 + if record.rent_free_period_days: + # 计算这个月的天数 + current_days = calendar.monthrange(free_start.year, free_start.month)[1] + current_no_free = (current_days - record.rent_free_period_days) / current_days + # 计算 免租期天的比值 + record.sudo().write({'breakdown_ids': [(0, 0, { + "unit_price": unit_price, + "monthly_amount": monthly_amount, + "breakdown_id": record.id, + "start_data": free_start, + "end_data": free_start + relativedelta(months=1) - relativedelta(days=1), + "month_number": 1, + "period_rent": monthly_amount * 1 * current_no_free, + })]}) + all_period_rent += monthly_amount * 1 * current_no_free + # 免租期后退一个月 + free_start = free_start + relativedelta(months=1) + + # 计算 免租期天的比值 delta = relativedelta(end_date, free_start) months = delta.years * 12 + delta.months - self.sudo().write({'breakdown_ids': [(0, 0, { + record.sudo().write({'breakdown_ids': [(0, 0, { "unit_price": unit_price, "monthly_amount": monthly_amount, "breakdown_id": record.id, - "start_data": increments_start, + "start_data": free_start, "end_data": end_date - relativedelta(days=1), "month_number": months, "period_rent": monthly_amount * months, })]}) - # self.sudo().env["property.rent.breakdown.line"].create({ - # "unit_price": unit_price, - # "monthly_amount": monthly_amount, - # "breakdown_id": record.id, - # "start_data": increments_start, - # "end_data": end_date - relativedelta(days=1), - # "month_number": months, - # "period_rent": monthly_amount * months, - # }) + all_period_rent += monthly_amount * months # 如果有递增 else: - all_months = 0 # 第几月份 - # 有免递增年份的计算 + first_years_begin_end = start_date + # 免递增年份计算 if first_years_begin: - first_index = 0 # 第几递增周期年 - first_period_rent = 0 # 总收费 - first_months = 0 - divided_year_segments = self.divide_time_range_fixed(start_date, end_date, 12) - for segment_year in divided_year_segments: - first_index += 1 - increments_start = segment_year[1] - if first_years_begin and first_index >= first_years_begin: - # 进入 递增时间 跳出平稳计费极端 - break - delta = relativedelta(segment_year[1], segment_year[0]) - months = delta.years * 12 + delta.months - # 判断第几月份进入 付费租期 - for month in range(months): - all_months += 1 - # 判断是否是免租期 - if all_months > rent_free_period_month: - first_period_rent += monthly_amount - first_months += 1 - - if first_period_rent: - self.sudo().write({'breakdown_ids': [(0, 0, { + # 免递增结束时间 + first_years_begin_end = start_date + relativedelta(months=first_years_begin * 12) + # 免租期结束时间 free_start + # 计算免租期和免增期的差值, 如果免租期超过免增期那么不存在免增期 + if first_years_begin_end > free_start: + # 如果免租期有天那么默认增加一个月 + if record.rent_free_period_days: + # 计算这个月的天数 + current_days = calendar.monthrange(free_start.year, free_start.month)[1] + current_no_free = (current_days - record.rent_free_period_days) / current_days + # 计算 免租期天的比值 + record.sudo().write({'breakdown_ids': [(0, 0, { + "unit_price": unit_price, + "monthly_amount": monthly_amount, + "breakdown_id": record.id, + "start_data": free_start, + "end_data": free_start + relativedelta(months=1) - relativedelta(days=1), + "month_number": 1, + "period_rent": monthly_amount * 1 * current_no_free, + })]}) + all_period_rent += monthly_amount * 1 * current_no_free + # 免租期后退一个月 + free_start = free_start + relativedelta(months=1) + # 计算剩下的免增期 + delta = relativedelta(first_years_begin_end, free_start) + first_months = delta.years * 12 + delta.months + record.sudo().write({'breakdown_ids': [(0, 0, { "unit_price": unit_price, "monthly_amount": monthly_amount, "breakdown_id": record.id, - "start_data": increments_start - relativedelta(months=first_months), - "end_data": increments_start - relativedelta(days=1), + "start_data": free_start, + "end_data": first_years_begin_end, "month_number": first_months, - "period_rent": first_period_rent, + "period_rent": first_months * monthly_amount, })]}) - # self.sudo().env["property.rent.breakdown.line"].create({ - # "unit_price": unit_price, - # "monthly_amount": monthly_amount, - # "breakdown_id": record.id, - # "start_data": increments_start - relativedelta(months=first_months), - # "end_data": increments_start - relativedelta(days=1), - # "month_number": first_months, - # "period_rent": first_period_rent, - # }) - - # 开始递增 - divided_increments_segments = self.divide_time_range_fixed(increments_start, end_date, increments_every_few_years*12) - index = 0 # 第几递增周期年 + all_period_rent += first_months * monthly_amount + # 免增期结束开始递增 + divided_increments_segments = record.divide_time_range_fixed(first_years_begin_end, end_date, increments_every_few_years*12) + year_index = 0 # 第几递增周期年 + all_months = 0 # 递增的第几个月 + # 如果免租期 超过 免增期 那么递增期也需要排除 + if first_years_begin_end < free_start: + delta = relativedelta(first_years_begin_end, free_start) + free_first_months = delta.years * 12 + delta.months + # 如果免租期有天那么默认增加一个月 + if record.rent_free_period_days: + free_first_months = free_first_months + 1 + else: + free_first_months = 0 for increments_year in divided_increments_segments: - index += 1 + year_index += 1 """ increment_percentage = fields.Float(string="递增百分比") increment_price = fields.Float(string="递增单价") @@ -451,17 +462,38 @@ class PropertyLeaseContract(models.Model): if record.increment_method == "increment_amount" and record.increment_value: monthly_amount = monthly_amount + record.increment_value unit_price = monthly_amount / record.total_area + delta = relativedelta(increments_year[1], increments_year[0]) months = delta.years * 12 + delta.months + month_index = 0 # 判断第几月份进入 付费租期 for month in range(months): - # 判断第几月份进入 付费租期 + month_index += 1 # 当前第个月 + # 判断第几月份进入 付费租期 all_months += 1 + if all_months == free_first_months: + # 如果免租期有天那么默认增加一个月 + if record.rent_free_period_days: + current_now = increments_year[0] + relativedelta(months=month_index) + # 计算这个月的天数 + current_days = calendar.monthrange(current_now.year, current_now.month)[1] + current_no_free = (current_days - record.rent_free_period_days) / current_days + # 计算 免租期天的比值 + record.sudo().write({'breakdown_ids': [(0, 0, { + "unit_price": unit_price, + "monthly_amount": monthly_amount, + "breakdown_id": record.id, + "start_data": current_now, + "end_data": current_now + relativedelta(months=1) - relativedelta(days=1), + "month_number": 1, + "period_rent": monthly_amount * 1 * current_no_free, + })]}) + all_period_rent += monthly_amount * 1 * current_no_free # 判断是否是免租期 - if all_months > rent_free_period_month: + if all_months > free_first_months: increments_month += 1 if increments_month: - self.sudo().write({'breakdown_ids': [(0, 0, { + record.sudo().write({'breakdown_ids': [(0, 0, { "unit_price": unit_price, "monthly_amount": monthly_amount, "breakdown_id": record.id, @@ -470,15 +502,8 @@ class PropertyLeaseContract(models.Model): "month_number": increments_month, "period_rent": monthly_amount * increments_month, })]}) - # self.sudo().env["property.rent.breakdown.line"].create({ - # "unit_price": unit_price, - # "monthly_amount": monthly_amount, - # "breakdown_id": record.id, - # "start_data": increments_year[1] - relativedelta(months=increments_month), - # "end_data": increments_year[1] - relativedelta(days=1), - # "month_number": increments_month, - # "period_rent": monthly_amount * increments_month, - # }) + all_period_rent += monthly_amount * increments_month + return all_period_rent # @api.onchange("first_year_rent") # def _onchange_first_year_rent(self):