Merge pull request !9188 from 李鹏宇/dev
This commit is contained in:
@@ -623,8 +623,8 @@ class SoongWorkflowRecord(models.Model):
|
||||
local_time = current_utc_time + timedelta(hours=8)
|
||||
h = local_time.hour
|
||||
m = local_time.minute
|
||||
if not (h == 17 and 25 <= m <= 35):
|
||||
return
|
||||
# if not (h == 17 and 25 <= m <= 35):
|
||||
# return
|
||||
menu_id = self.env['ir.ui.menu'].search([('name', '=', '待办流程')])
|
||||
target_url = f'https://oa.thtzjt.com/web#aciton=4299&model=soong.workflow.record&view_type=list&cids=1-2-3-4&menu_id={menu_id.id}'
|
||||
rec_ids = self.env["soong.workflow.record"].search([
|
||||
|
||||
@@ -14,6 +14,7 @@ class PropertyAccountsReceivable(models.Model):
|
||||
_description = '应收账单'
|
||||
|
||||
payout_date = fields.Date(string='收款日期')
|
||||
is_liquidated_damages = fields.Boolean(string='生成违约金', default=True)
|
||||
rent_month = fields.Float(string='当月租金')
|
||||
tax = fields.Float(string='税率')
|
||||
title_certificate = fields.Char(sting="产权证号")
|
||||
@@ -54,6 +55,12 @@ class PropertyAccountsReceivable(models.Model):
|
||||
bank_id = fields.Many2one('property.bank.statements', string='流水记录')
|
||||
receivable_log = fields.Text(string='应收日志')
|
||||
|
||||
def update_is_liquidated_damages(self):
|
||||
rent_ids = self.env["property.accounts.receivable"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id')))
|
||||
for rent in rent_ids:
|
||||
rent.is_liquidated_damages = False
|
||||
|
||||
@api.onchange('contract_id')
|
||||
def _onchange_contract_id(self):
|
||||
"""选择合同时自动填充税率"""
|
||||
@@ -201,13 +208,13 @@ class PropertyAccountsReceivable(models.Model):
|
||||
'sticky': False,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
receivable_records = self.env['property.accounts.receivable'].browse(receivable_ids)
|
||||
|
||||
|
||||
# 加载新模板文件
|
||||
template_path = get_module_resource('yuthon_property', 'static', 'tmpl', 'piliangkaipiao (2).xlsx')
|
||||
workbook = load_workbook(template_path)
|
||||
|
||||
|
||||
# 指定写入"原始数据"sheet
|
||||
sheet = workbook['原始数据']
|
||||
|
||||
@@ -228,7 +235,7 @@ class PropertyAccountsReceivable(models.Model):
|
||||
}
|
||||
else:
|
||||
template_styles = {}
|
||||
|
||||
|
||||
for index, record in enumerate(receivable_records, start=1):
|
||||
# 先解除当前行的合并单元格(如果有)
|
||||
merged_cells_to_unmerge = []
|
||||
@@ -247,7 +254,7 @@ class PropertyAccountsReceivable(models.Model):
|
||||
cell.border = copy(template_styles[col]['border'])
|
||||
# 统一设置居中对齐
|
||||
cell.alignment = Alignment(horizontal='center', vertical='center')
|
||||
|
||||
|
||||
# A列:序号(从1开始)
|
||||
sheet.cell(row=row, column=1, value=index)
|
||||
|
||||
@@ -305,20 +312,20 @@ class PropertyAccountsReceivable(models.Model):
|
||||
if record.contract_id:
|
||||
contract_code = record.contract_id.contract_code or ''
|
||||
sheet.cell(row=row, column=10, value=contract_code)
|
||||
|
||||
|
||||
# 设置最小行高
|
||||
if not sheet.row_dimensions[row].height or sheet.row_dimensions[row].height < 30:
|
||||
sheet.row_dimensions[row].height = 30
|
||||
|
||||
row += 1
|
||||
|
||||
|
||||
# 保存到内存
|
||||
output = io.BytesIO()
|
||||
workbook.save(output)
|
||||
output.seek(0)
|
||||
excel_data = base64.b64encode(output.read())
|
||||
output.close()
|
||||
|
||||
|
||||
# 创建附件
|
||||
filename = f'批量开票_{datetime.now().strftime("%Y%m%d")}.xlsx'
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
@@ -327,7 +334,7 @@ class PropertyAccountsReceivable(models.Model):
|
||||
'datas': excel_data,
|
||||
'mimetype': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
})
|
||||
|
||||
|
||||
# 返回下载链接
|
||||
return {
|
||||
'type': 'ir.actions.act_url',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from email.policy import default
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
@@ -6,6 +8,7 @@ class PropertyRentList(models.Model):
|
||||
_description = '租金列表'
|
||||
|
||||
property_id = fields.Many2one('yuthon.property', string='物业')
|
||||
is_liquidated_damages = fields.Boolean(string='生成违约金', default=True)
|
||||
lessee_id = fields.Many2one('property.tenant.information', string='承租方', store=True)
|
||||
admin_id = fields.Many2one(related='property_id.admin_id', string="片区管理员", store=True)
|
||||
rent_month = fields.Float(string='当月租金')
|
||||
@@ -37,6 +40,12 @@ class PropertyRentList(models.Model):
|
||||
management_type_id = fields.Many2one('yuthon.management.type', string='应收类型')
|
||||
last_update_time = fields.Datetime(string='最后修改时间')
|
||||
|
||||
def update_is_liquidated_damages(self):
|
||||
rent_ids = self.env["property.rent.list"].browse(
|
||||
self._context.get('active_ids', self._context.get('active_id')))
|
||||
for rent in rent_ids:
|
||||
rent.is_liquidated_damages = False
|
||||
|
||||
def get_no_read_count(self):
|
||||
return self.env['property.rent.list'].search_count([('is_push', '=', False)])
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<field name="print_date"/>
|
||||
<field name="discount_date"/>
|
||||
<field name="has_date"/>
|
||||
<field name="is_liquidated_damages"/>
|
||||
<button name="receivable_log_wizard" string="日志" type="object" class="oe_highlight"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<tree editable="bottom" string="租金列表" decoration-danger = "charge_status == 'unpaid'"
|
||||
decoration-success="charge_status == 'fully_paid'" js_class="custom_rent_list_button" delete="false" limit="15">
|
||||
<field name="acc_type" string=" " readonly="1"/>
|
||||
<field name="is_liquidated_damages"/>
|
||||
<field name="property_id" options="{'no_create': True}" column_invisible="1"/>
|
||||
<field name="lessee_id" readonly="1"/>
|
||||
<field name="due_date" readonly="1"/>
|
||||
@@ -25,6 +26,13 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="all_update_is_liquidated_damages" model="ir.actions.server">
|
||||
<field name="name">批量不生成违约金</field>
|
||||
<field name="model_id" ref="yuthon_property.model_property_rent_list"/>
|
||||
<field name="binding_model_id" ref="yuthon_property.model_property_rent_list"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_is_liquidated_damages()</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
|
||||
|
||||
@@ -1050,6 +1050,7 @@ class PropertyRentList(models.Model):
|
||||
'contract_id': contract.id if contract else False,
|
||||
'lessee_id': contract.lessee_id.id if contract and contract.lessee_id else None,
|
||||
'original_amount': rec.original_amount,
|
||||
'is_liquidated_damages': rec.is_liquidated_damages,
|
||||
'due_date': due_date,
|
||||
'acc_type': rec.acc_type,
|
||||
'charging_range': f"{due_date} 到 {due_date_end}",
|
||||
|
||||
@@ -646,6 +646,13 @@
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.all_penalty_date()</field>
|
||||
</record>
|
||||
<record id="all_update_is_liquidated_damages" model="ir.actions.server">
|
||||
<field name="name">批量不生成违约金</field>
|
||||
<field name="model_id" ref="yuthon_property.model_property_accounts_receivable"/>
|
||||
<field name="binding_model_id" ref="yuthon_property.model_property_accounts_receivable"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.update_is_liquidated_damages()</field>
|
||||
</record>
|
||||
<record id="all_action_refuse_all" model="ir.actions.server">
|
||||
<field name="name">批量退回</field>
|
||||
<field name="model_id" ref="yuthon_property.model_property_accounts_receivable"/>
|
||||
|
||||
@@ -177,7 +177,7 @@ class PenaltyLineWizard(models.Model):
|
||||
|
||||
@api.onchange('calculation_date')
|
||||
def _onchange_calculation_date(self):
|
||||
if self.receivable_id.management_type_id.name != '押金':
|
||||
if self.receivable_id.management_type_id.name != '押金' and self.receivable_id.is_liquidated_damages == True:
|
||||
realtime_lines = self.penalty_line_ids.filtered(lambda l: l.is_realtime)
|
||||
non_realtime_lines = self.penalty_line_ids - realtime_lines
|
||||
update_commands = []
|
||||
|
||||
@@ -167,6 +167,8 @@ class PropertyReconciliationWizard(models.Model):
|
||||
])
|
||||
for contract_receivables in contract_receivables_ids:
|
||||
if contract_receivables:
|
||||
if not contract_receivables.is_liquidated_damages:
|
||||
continue
|
||||
# 计算应收日期的下月1号
|
||||
if not contract_receivables.due_date:
|
||||
raise UserError(f'合同{contract_id.name}类型为{contract_receivables.management_type_id.name}的应收日期为空,请先填写应收日期')
|
||||
@@ -204,6 +206,8 @@ class PropertyReconciliationWizard(models.Model):
|
||||
])
|
||||
if unpaid_rent_recs:
|
||||
for rent in unpaid_rent_recs:
|
||||
if not rent.is_liquidated_damages: # 跳过不生成违约金的租金
|
||||
continue
|
||||
if rent.payout_date <= rent.due_date: # 跳过预收的租金
|
||||
continue
|
||||
first_day = (rent.payout_date + timedelta(days=1))
|
||||
@@ -239,116 +243,6 @@ class PropertyReconciliationWizard(models.Model):
|
||||
total = sum(line.rent for line in self.reconciliation_line_ids)
|
||||
self.receivable_total = total
|
||||
|
||||
# all_due_dates = []
|
||||
# for line in self.reconciliation_line_ids:
|
||||
# if line.collection_type == 'rent' and line.due_date:
|
||||
# all_due_dates.append(fields.Date.from_string(line.due_date))
|
||||
# # 2. 找到最早的到期日期
|
||||
# if all_due_dates:
|
||||
# earliest_due_date = min(all_due_dates)
|
||||
# # 获取实际日期(假设actual_date是日期对象,如果是字符串需要先转换)
|
||||
# actual_date = fields.Date.from_string(self.actual_date) if isinstance(self.actual_date,
|
||||
# str) else self.actual_date
|
||||
#
|
||||
# # 计算起始月份(最早到期日的月份)和结束月份(实际日期的月份)
|
||||
# start_month = earliest_due_date + relativedelta(months=1)
|
||||
# end_month = actual_date - relativedelta(months=1)
|
||||
#
|
||||
# temp_rent_set = set()
|
||||
# target_rent_months = []
|
||||
#
|
||||
# # 遍历从起始月到结束月的所有月份
|
||||
# current_month = start_month
|
||||
# while current_month <= end_month:
|
||||
# due_month = current_month.strftime('%Y-%m')
|
||||
# # 为每个租金行添加当前月份的记录(去重)
|
||||
# for line in self.reconciliation_line_ids:
|
||||
# if line.collection_type == 'rent':
|
||||
# unique_key = (
|
||||
# line.contract_id.id if line.contract_id else None,
|
||||
# due_month
|
||||
# )
|
||||
# if unique_key not in temp_rent_set:
|
||||
# temp_rent_set.add(unique_key)
|
||||
# target_rent_months.append({
|
||||
# 'contract_id': line.contract_id,
|
||||
# 'due_month': due_month
|
||||
# })
|
||||
# # 移动到下个月
|
||||
# if current_month.month == 12:
|
||||
# current_month = current_month.replace(year=current_month.year + 1, month=1, day=1)
|
||||
# else:
|
||||
# current_month = current_month.replace(month=current_month.month + 1, day=1)
|
||||
# else:
|
||||
# 没有符合条件的明细行时,返回空列表
|
||||
target_rent_months = []
|
||||
|
||||
# if target_rent_months:
|
||||
# existing_penalty_months = set()
|
||||
# for line in self.reconciliation_line_ids:
|
||||
# if line.collection_type == 'penalty' and line.due_date:
|
||||
# penalty_month = fields.Date.from_string(line.due_date).strftime('%Y-%m')
|
||||
# penalty_key = (
|
||||
# line.contract_id.id if line.contract_id else None,
|
||||
# penalty_month
|
||||
# )
|
||||
# existing_penalty_months.add(penalty_key)
|
||||
#
|
||||
# # # 3. 补全缺失的跨月违约金(按合同+年月匹配,缺失则新增)
|
||||
# # missing_penalty_lines = []
|
||||
# # for rent_info in target_rent_months:
|
||||
# # contract = rent_info['contract_id']
|
||||
# # due_month = rent_info['due_month']
|
||||
# #
|
||||
# # # 构建待检查的违约金key(合同+年月)
|
||||
# # check_key = (
|
||||
# # contract.id if contract else None,
|
||||
# # due_month
|
||||
# # )
|
||||
# #
|
||||
# # if check_key not in existing_penalty_months:
|
||||
# # year, month = map(int, due_month.split('-'))
|
||||
# # first_day = datetime(year, month, 1).date()
|
||||
# # penalty_days = (self.actual_date - first_day).days + 1
|
||||
# #
|
||||
# # # 计算补全违约金的日期范围:当月1号 ~ 当月最后1天
|
||||
# # # 查找上个月的租金明细行
|
||||
# # if month == 1:
|
||||
# # last_month_year = year - 1
|
||||
# # last_month = 12
|
||||
# # else:
|
||||
# # last_month_year = year
|
||||
# # last_month = month - 1
|
||||
# # last_month_str = f"{last_month_year}-{last_month:02d}"
|
||||
# #
|
||||
# # last_month_rent_line = next((
|
||||
# # line for line in self.reconciliation_line_ids
|
||||
# # if line.collection_type == 'rent'
|
||||
# # and line.contract_id == contract
|
||||
# # and line.due_date # 有到期日期
|
||||
# # and fields.Date.from_string(line.due_date).strftime('%Y-%m') == last_month_str
|
||||
# # ), None)
|
||||
# # # 提取上个月租金的rent金额
|
||||
# # last_month_rent = last_month_rent_line.rent if last_month_rent_line else 0.0
|
||||
# # penalty_amount = penalty_days * round(
|
||||
# # last_month_rent * float(contract.percentage_liquidated_damages.name), 2
|
||||
# # ) if (contract and last_month_rent > 0) else 0.0
|
||||
# #
|
||||
# # if penalty_amount > 0:
|
||||
# # missing_penalty_lines.append((0, 0, {
|
||||
# # 'contract_id': contract.id if contract else None,
|
||||
# # 'rent_month': 0,
|
||||
# # 'due_date': fields.Date.to_string(first_day),
|
||||
# # 'rent': penalty_amount,
|
||||
# # 'amount': 0,
|
||||
# # 'collection_type': 'penalty',
|
||||
# # 'remake': f'违约金({fields.Date.to_string(first_day)}至{fields.Date.to_string(self.actual_date)},共{penalty_days}天',
|
||||
# # }))
|
||||
# #
|
||||
# # # 添加缺失的违约金记录
|
||||
# # if missing_penalty_lines:
|
||||
# # self.write({'reconciliation_line_ids': missing_penalty_lines})
|
||||
|
||||
self.create_reconciliation_vals()
|
||||
line_types = []
|
||||
for line in self.reconciliation_line_ids:
|
||||
|
||||
Reference in New Issue
Block a user