Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
pengyuthon
2026-03-04 10:51:34 +08:00
8 changed files with 93 additions and 37 deletions
@@ -212,17 +212,51 @@ class PropertyAccountsReceivable(models.Model):
receivable_records = self.env['property.accounts.receivable'].browse(receivable_ids)
# 加载新模板文件
template_path = get_module_resource('yuthon_property', 'static', 'tmpl', 'piliangkaipiao (2).xlsx')
template_path = get_module_resource('yuthon_property', 'static', 'tmpl', 'piliangkaipiao (3).xlsx')
workbook = load_workbook(template_path)
# 指定写入"原始数据"sheet
sheet = workbook['原始数据']
# 从第3行开始写入数据(第1-2行是表头)
row = 3
# 统计导出数据中最常见的年月(用于B2单元格)
year_month_list = []
for record in receivable_records:
if record.due_date:
year_month_list.append((record.due_date.year, record.due_date.month))
# 获取模板样式行(使用第3行作为参考)
template_row_idx = 3
if year_month_list:
# 取出现次数最多的年月
from collections import Counter
most_common_ym = Counter(year_month_list).most_common(1)[0][0]
title_year, title_month = most_common_ym
else:
# 如果没有应收日期,使用当前年月
now = datetime.now()
title_year, title_month = now.year, now.month
# 填充B2单元格:年月
sheet['B2'] = f'{title_year}年{title_month}月'
# 统计导出数据中最常见的公司(用于C2单元格)
company_list = []
for record in receivable_records:
if record.contract_id and record.contract_id.company_id:
company_list.append(record.contract_id.company_id.name)
if company_list:
from collections import Counter
most_common_company = Counter(company_list).most_common(1)[0][0]
else:
most_common_company = ''
# 填充C2单元格:所属公司
sheet['C2'] = most_common_company
# 从第4行开始写入数据(第1-2行是标题,第3行是表头)
row = 4
# 获取模板样式行(使用第4行作为参考,因为第3行是表头)
template_row_idx = 4
if sheet.max_row >= template_row_idx:
template_styles = {}
for col in range(1, 11): # A到J列(10列)
@@ -266,10 +300,22 @@ class PropertyAccountsReceivable(models.Model):
date_range = record.due_date.strftime('%Y-%m-%d')
sheet.cell(row=row, column=2, value=date_range)
# C列:承租方名称(lessee_id)
sheet.cell(row=row, column=3, value=record.lessee_id.name if record.lessee_id else '')
# C列:金额(original_amount)
sheet.cell(row=row, column=3, value=record.original_amount or 0)
# D列:统一社会信用代码/纳税人识别号(从invoicing.information.line获取)
# D列:物业名称(property_name)
sheet.cell(row=row, column=4, value=record.property_name or '')
# E列:合同编号(contract_code,从合同获取)
contract_code = ''
if record.contract_id:
contract_code = record.contract_id.contract_code or ''
sheet.cell(row=row, column=5, value=contract_code)
# F列:承租方名称(lessee_id)
sheet.cell(row=row, column=6, value=record.lessee_id.name if record.lessee_id else '')
# G列:统一社会信用代码/纳税人识别号(从invoicing.information.line获取)
tax_number = ''
if record.lessee_id and record.lessee_id.invoicing_ids:
# 取第一条有效记录的税号
@@ -277,21 +323,15 @@ class PropertyAccountsReceivable(models.Model):
if inv_line.tax_number:
tax_number = inv_line.tax_number
break
sheet.cell(row=row, column=4, value=tax_number)
sheet.cell(row=row, column=7, value=tax_number)
# E列:金额(original_amount)
sheet.cell(row=row, column=5, value=record.original_amount or 0)
# F列:物业名称(property_name)
sheet.cell(row=row, column=6, value=record.property_name or '')
# G列:产权证(title_information,从合同获取)
# H列:产权证(title_information,从合同获取)
title_info = ''
if record.contract_id:
title_info = record.contract_id.title_information or ''
sheet.cell(row=row, column=7, value=title_info)
sheet.cell(row=row, column=8, value=title_info)
# H列:发票类型(从invoicing.information.line的invoicing_type_id获取)
# I列:发票类型(从invoicing.information.line的invoicing_type_id获取)
invoicing_type = ''
if record.lessee_id and record.lessee_id.invoicing_ids:
# 取第一条有效记录的发票类型
@@ -299,19 +339,23 @@ class PropertyAccountsReceivable(models.Model):
if inv_line.invoicing_type_id:
invoicing_type = inv_line.invoicing_type_id.name or ''
break
sheet.cell(row=row, column=8, value=invoicing_type)
sheet.cell(row=row, column=9, value=invoicing_type)
# I列:税率(从合同的tax_rate获取)
tax_rate_name = ''
# J列:税率(从合同的tax_rate获取,使用小数格式,如0.05)
tax_rate_value = 0.0
if record.contract_id and record.contract_id.tax_rate:
tax_rate_name = record.contract_id.tax_rate.name or ''
sheet.cell(row=row, column=9, value=tax_rate_name)
# J列:合同编号(contract_code,从合同获取)
contract_code = ''
if record.contract_id:
contract_code = record.contract_id.contract_code or ''
sheet.cell(row=row, column=10, value=contract_code)
# 将税率名称(如"0.05"或"5%")转换为小数
tax_rate_name = record.contract_id.tax_rate.name or '0'
try:
# 如果是百分比格式(如"5%"),转换为小数
if '%' in tax_rate_name:
tax_rate_value = float(tax_rate_name.replace('%', '')) / 100
else:
# 直接是小数格式(如"0.05")
tax_rate_value = float(tax_rate_name)
except (ValueError, TypeError):
tax_rate_value = 0.0
sheet.cell(row=row, column=10, value=tax_rate_value)
# 设置最小行高
if not sheet.row_dimensions[row].height or sheet.row_dimensions[row].height < 30:
Binary file not shown.
Binary file not shown.
+13 -1
View File
@@ -11,7 +11,7 @@ class YuthonMealExpenses(models.Model):
card = fields.Char(string='身份证')
number_breakfasts = fields.Integer(string='早餐次数')
number_lunches = fields.Integer(string='午餐次数')
total_payment = fields.Float(string='合计缴费')
total_payment = fields.Float(string='合计缴费', compute='_compute_total_payment', store=True)
company_id = fields.Many2one(related='employee_id.company_id', string="公司")
select_time = fields.Selection([('1', '一月'), ('2', '二月'), ('3', '三月'), ('4', '四月'),
('5', '五月'), ('6', '六月'), ('7', '七月'), ('8', '八月'),
@@ -24,6 +24,18 @@ class YuthonMealExpenses(models.Model):
toll_state = fields.Selection([('to_do', '未缴'), ('done', '已缴')], string='状态', default='to_do')
@api.depends('number_breakfasts', 'number_lunches')
def _compute_total_payment(self):
for record in self:
record.total_payment = record.number_breakfasts * 1.0 + record.number_lunches * 2.0
@api.model
def _name_search(self, name='', domain=None, operator='ilike', limit=100, order=None):
domain = domain or []
if name:
domain = ['|', ('employee_id.name', operator, name), ('card', operator, name)] + domain
return super(YuthonMealExpenses, self)._name_search(name='', domain=domain, operator=operator, limit=limit, order=order)
def toll_confirm(self):
self.toll_state = 'done'
@@ -5,11 +5,11 @@
<field name="model">yuthon.meal.expenses</field>
<field name="arch" type="xml">
<search>
<field name="employee_id"/>
<field name="card"/>
<field name="employee_id" string="姓名/身份证"
filter_domain="['|', ('employee_id.name', 'ilike', self), ('card', 'ilike', self)]"/>
<field name="card" string="身份证" filter_domain="[('card', 'ilike', self)]"/>
<field name="select_year"/>
<field name="select_time"/>
<field name="company_id"/>
<field name="meal_state"/>
<group expand="0" string="分组">
<filter string="年份" name="group_by_year" context="{'group_by':'select_year'}"/>
@@ -47,7 +47,7 @@
<field name="employee_id"/>
<field name="number_breakfasts"/>
<field name="number_lunches"/>
<field name="total_payment"/>
<field name="total_payment" readonly="1"/>
<field name="company_id" column_invisible="1"/>
<field name="toll_state"/>
<button name="toll_confirm" string="确认已缴费" type="object" class="oe_highlight" confirm="注意:交完费了才点这个确认,是否确认?" invisible="toll_state == 'done'"/>
+2 -2
View File
@@ -24,8 +24,8 @@ class SalaryPartyWizard(models.TransientModel):
self.salary_party_data(row)
def salary_party_data(self, row):
select_year = int(row[0].value)
select_time = int(row[1].value)
select_year = str(int(row[0].value))
select_time = str(int(row[1].value))
employee_id = self.env['hr.employee'].search([('identification_id', '=', row[3].value)], limit=1)
card = row[3].value
fee = row[4].value
@@ -3,7 +3,7 @@
<record id="salary_party_wizard_downloads_action" model="ir.actions.act_url">
<field name="name">模板下载</field>
<field name="target">self</field>
<field name="url">/yuthon_salary/static/others/salary_party.xlsx</field>
<field name="url">/yuthon_salary/static/others/党费-模板v1.0.xlsx</field>
</record>
<record id="salary_party_wizard_form" model="ir.ui.view">
<field name="name">弹窗</field>