diff --git a/yuthon_property/models/property_meter_archives.py b/yuthon_property/models/property_meter_archives.py
index 9a7d77243..8746802ed 100644
--- a/yuthon_property/models/property_meter_archives.py
+++ b/yuthon_property/models/property_meter_archives.py
@@ -168,12 +168,12 @@ class MeterArchivesLine(models.Model):
archives_id = fields.Many2one('property.meter.archives', string='电表库', required=True, ondelete='cascade')
name = fields.Char(string='仪表编号')
epitope_values = fields.Char(string='表位置')
- lessee_id = fields.Many2one('property.tenant.information', string='承租方')
+ lessee_id = fields.Many2one('property.tenant.information', string='承租方', compute='_compute_lessee_id')
yuthon_property_ids = fields.Many2many('yuthon.property', string='物业信息')
last_meter = fields.Date(string='上次抄表日期')
- last_dosage = fields.Float(string='上次用量')
+ last_dosage = fields.Float(string='上次用量', compute="_compute_last_dosage")
last_read = fields.Float(string='上次读数', readonly=True)
- current_meter = fields.Float(string='本次用量', readonly=True)
+ current_meter = fields.Float(string='本次用量', readonly=True, compute='_compute_current_meter')
current_read = fields.Float(string='本次读数')
unit_number = fields.Char(string='单元编号/用途')
gauge_magnification = fields.Integer(string='仪表倍率', readonly=True, default=1)
@@ -186,6 +186,39 @@ class MeterArchivesLine(models.Model):
default='use')
maximum_count = fields.Integer(string='最大位数')
+ @api.depends('current_read', 'last_read')
+ def _compute_current_meter(self):
+ for record in self:
+ record.current_meter = record.current_read - record.last_read
+
+ @api.depends('yuthon_property_ids')
+ def _compute_lessee_id(self):
+ for record in self:
+ if record.yuthon_property_ids:
+ record.lessee_id = record.yuthon_property_ids[0].lessee_id
+ else:
+ record.lessee_id = False
+
+ @api.depends('current_read', 'last_read')
+ def _compute_last_dosage(self):
+ """上次用量 = 上个月的本次读数 - 上个月的上次读数"""
+ for line in self:
+ # 获取同仪表的所有明细行并按抄表日期排序
+ lines = self.search([
+ ('archives_id', '=', line.archives_id.id),
+ ('last_meter', '!=', False)
+ ], order='last_meter asc')
+
+ if line in lines:
+ idx = lines.ids.index(line.id)
+ if idx > 0:
+ prev_line = lines[idx - 1]
+ line.last_dosage = (prev_line.current_read or 0) - (prev_line.last_read or 0)
+ else:
+ line.last_dosage = 0.0
+ else:
+ # 当前记录没有抄表日期,无法计算上次用量
+ line.last_dosage = 0.0
class PropertyElectricReading(models.Model):
_name = 'property.electric.reading'
diff --git a/yuthon_property/models/property_meter_water.py b/yuthon_property/models/property_meter_water.py
index 24786f223..f2ecf7bea 100644
--- a/yuthon_property/models/property_meter_water.py
+++ b/yuthon_property/models/property_meter_water.py
@@ -158,12 +158,12 @@ class MeterWaterLine(models.Model):
water_id = fields.Many2one('property.meter.water', string='水表库', required=True, ondelete='cascade')
name = fields.Char(string='仪表编号')
epitope_values = fields.Char(string='表位置')
- lessee_id = fields.Many2one('property.tenant.information', string='承租方')
+ lessee_id = fields.Many2one('property.tenant.information', string='承租方', compute='_compute_lessee_id')
yuthon_property_ids = fields.Many2many('yuthon.property', string='物业信息')
last_meter = fields.Date(string='上次抄表日期')
- last_dosage = fields.Float(string='上次用量')
+ last_dosage = fields.Float(string='上次用量', compute="_compute_last_dosage")
last_read = fields.Float(string='上次读数', readonly=True)
- current_meter = fields.Float(string='本次用量', readonly=True)
+ current_meter = fields.Float(string='本次用量', readonly=True, compute='_compute_current_meter')
current_read = fields.Float(string='本次读数')
unit_number = fields.Char(string='单元编号/用途')
gauge_magnification = fields.Integer(string='仪表倍率', readonly=True, default=1)
@@ -176,6 +176,39 @@ class MeterWaterLine(models.Model):
employee_ids = fields.Many2many('hr.employee', string='抄表人')
maximum_count = fields.Integer(string='最大位数')
+ @api.depends('current_read', 'last_read')
+ def _compute_current_meter(self):
+ for record in self:
+ record.current_meter = record.current_read - record.last_read
+
+ @api.depends('yuthon_property_ids')
+ def _compute_lessee_id(self):
+ for record in self:
+ if record.yuthon_property_ids:
+ record.lessee_id = record.yuthon_property_ids[0].lessee_id
+ else:
+ record.lessee_id = False
+
+ @api.depends('current_read', 'last_read')
+ def _compute_last_dosage(self):
+ """上次用量 = 上个月的本次读数 - 上个月的上次读数"""
+ for line in self:
+ # 获取同仪表的所有明细行并按抄表日期排序
+ lines = self.search([
+ ('archives_id', '=', line.archives_id.id),
+ ('last_meter', '!=', False)
+ ], order='last_meter asc')
+
+ if line in lines:
+ idx = lines.ids.index(line.id)
+ if idx > 0:
+ prev_line = lines[idx - 1]
+ line.last_dosage = (prev_line.current_read or 0) - (prev_line.last_read or 0)
+ else:
+ line.last_dosage = 0.0
+ else:
+ # 当前记录没有抄表日期,无法计算上次用量
+ line.last_dosage = 0.0
class PropertyWaterReading(models.Model):
diff --git a/yuthon_property/views/hydropower_logs_views.xml b/yuthon_property/views/hydropower_logs_views.xml
index 6b1cabdc8..36fe77491 100644
--- a/yuthon_property/views/hydropower_logs_views.xml
+++ b/yuthon_property/views/hydropower_logs_views.xml
@@ -13,7 +13,7 @@
- 水电单价”
+ 水电单价
hydropower.logs
tree
diff --git a/yuthon_property/views/property_meter_archives_views.xml b/yuthon_property/views/property_meter_archives_views.xml
index 9ec6e2b23..5e79eed89 100644
--- a/yuthon_property/views/property_meter_archives_views.xml
+++ b/yuthon_property/views/property_meter_archives_views.xml
@@ -15,14 +15,14 @@
-
-
-
-
-
+
+
+
+
+
-
+
@@ -58,12 +58,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/yuthon_property/views/property_meter_water_views.xml b/yuthon_property/views/property_meter_water_views.xml
index 6c64d296c..72bd34cbb 100644
--- a/yuthon_property/views/property_meter_water_views.xml
+++ b/yuthon_property/views/property_meter_water_views.xml
@@ -16,14 +16,14 @@
-
-
-
-
-
+
+
+
+
+
-
+
@@ -61,12 +61,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/yuthon_property/wizard/property_meter_wizard.py b/yuthon_property/wizard/property_meter_wizard.py
index 094c6daa0..e4ac127fb 100644
--- a/yuthon_property/wizard/property_meter_wizard.py
+++ b/yuthon_property/wizard/property_meter_wizard.py
@@ -16,78 +16,139 @@ class PropertyMeterWizard(models.Model):
def confirm(self):
"""
- 导入excel文件,按行读取数据并处理
+ 导入excel文件,按行读取数据并处理,将1-9月数据写入明细行
"""
if not self.excel_file:
raise ValidationError('请上传文件。')
- book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
- sh = book.sheet_by_index(0)
- for rx in range(1, sh.nrows):
+
+ # 解码并打开Excel文件
+ try:
+ book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
+ sh = book.sheet_by_index(0)
+ except Exception as e:
+ raise ValidationError(f'文件解析错误: {str(e)}')
+
+ # 按行处理数据
+ for rx in range(1, sh.nrows): # 跳过表头行
row = sh.row(rx)
- last_read = 0
+ last_read = 0.0 # 初始读数,第一个月的上次读数为0
+
+ # 处理1-9月份数据
for month in range(1, 10):
last_read = self.property_meter_data(row, last_read, month)
def property_meter_data(self, row, last_read, month):
- epitope_values = row[0].value
- name = row[3].value
- type_dict = {'水表': 'water', '电表': 'electric', '电表(电子表)': 'smart', '': ''}
- unit_number = row[1].value
- installation_location = row[2].value
- if row[5].value:
- gauge_magnification = float(row[5].value)
- else:
- gauge_magnification = None
- maximum_count = float(row[6].value) if row[6].value else None
- type_dict = {'公共': 'public', '收费': 'fees', '': ''}
- type = type_dict.get(row[7].value)
- property_id = None
- if row[2].value:
- property_search = self.env['yuthon.property'].search([('name', '=', row[2].value)])
- if property_search:
- property_id = property_search[0]
+ """
+ 处理单月数据,查找主记录并创建/更新明细行
+ """
+ # 从Excel行获取基础数据
+ epitope_values = row[0].value if len(row) > 0 else ''
+ unit_number = row[1].value if len(row) > 1 else ''
+ installation_location = row[2].value if len(row) > 2 else ''
+ name = row[3].value if len(row) > 3 else '' # 仪表编号(关键标识)
+ # 处理仪表倍率
+ gauge_magnification = None
+ if len(row) > 5 and row[5].value:
+ try:
+ gauge_magnification = float(row[5].value)
+ except ValueError:
+ gauge_magnification = 1 # 默认为1
+
+ # 处理最大位数
+ maximum_count = None
+ if len(row) > 6 and row[6].value:
+ try:
+ maximum_count = float(row[6].value)
+ except ValueError:
+ maximum_count = None
+
+ # 处理类型转换
+ type_dict = {'公共': 'public', '收费': 'fees', '': ''}
+ meter_type = type_dict.get(row[7].value if len(row) > 7 else '', '')
+
+ # 处理物业信息
+ property_id = None
+ if installation_location: # 使用安装位置匹配物业
+ property_search = self.env['yuthon.property'].search(
+ [('name', '=', installation_location)],
+ limit=1
+ )
+ if property_search:
+ property_id = property_search
+
+ # 确定当前读数列索引(1-8月正常,9月特殊处理)
current_read_index = month + 9 if month < 9 else 9
- meter_date = None
+
+ # 处理当月数据
+ meter_date = datetime(2025, month, 15) if month < 9 else None
current_read = None
- # 1-8月份设置正常数据,9月份留空
- if month < 9:
- meter_date = datetime(2025, month, 15)
- current_read = row[current_read_index].value
- is_push = month < 9 # 9月份依然保持is_push为False
- additional_data = {
+ if month < 9 and len(row) > current_read_index and row[current_read_index].value:
+ try:
+ current_read = float(row[current_read_index].value)
+ except ValueError:
+ current_read = None
+
+ # 查找或创建主表记录(按仪表编号)
+ archives = self.env['property.meter.archives'].search([('name', '=', name),
+ ('is_push', '=', False)
+ ], limit=1)
+ if not archives:
+ archives = self.env['property.meter.archives'].create({
+ 'name': name,
+ 'epitope_values': epitope_values,
+ 'unit_number': unit_number,
+ 'installation_location': installation_location,
+ 'type': meter_type,
+ 'gauge_magnification': gauge_magnification,
+ 'maximum_count': maximum_count,
+ 'yuthon_property_ids': [(4, property_id.id)] if property_id else [],
+ })
+ else:
+ # 更新已有记录的部分字段
+ archives.write({
+ 'epitope_values': epitope_values,
+ 'unit_number': unit_number,
+ 'installation_location': installation_location,
+ 'type': meter_type,
+ 'gauge_magnification': gauge_magnification,
+ 'maximum_count': maximum_count,
+ 'yuthon_property_ids': [(4, property_id.id)] if property_id else [],
+ })
+
+ # 准备明细行数据
+ line_vals = {
'name': name,
+ 'archives_id': archives.id,
'epitope_values': epitope_values,
- 'maximum_count': maximum_count,
'unit_number': unit_number,
- 'installation_location': installation_location,
- 'type':type,
- 'gauge_magnification': gauge_magnification,
- 'meter_date': meter_date,
- 'current_read': current_read,
+ 'type': meter_type,
+ 'gauge_magnification': gauge_magnification or 1,
+ 'maximum_count': maximum_count,
'last_read': last_read,
- 'is_push': is_push,
+ 'current_read': current_read,
+ 'last_meter': meter_date,
+ 'last_reading_time': meter_date,
'yuthon_property_ids': [(4, property_id.id)] if property_id else [],
}
+ self.env['meter.archives.line'].sudo().create(line_vals)
+ # 返回当前读数作为下个月的上次读数
+ return current_read if (month < 9 and current_read is not None) else last_read
- # 处理数据逻辑...
- combined_data = {**additional_data}
- meter_id = self.env['property.meter.archives'].create(combined_data)
+ # if property_id:
+ # clear_entries = [(5,)]
+ # new_meter_entry = (0, 0, {
+ # 'property_meter_archives_id': meter_id.id,
+ # })
+ # updated_meters = clear_entries + [new_meter_entry]
+ # property_id.write({
+ # 'is_electricity_meter': True,
+ # 'energy_meter_ids': updated_meters
+ # })
- if property_id:
- clear_entries = [(5,)]
- new_meter_entry = (0, 0, {
- 'property_meter_archives_id': meter_id.id,
- })
- updated_meters = clear_entries + [new_meter_entry]
- property_id.write({
- 'is_electricity_meter': True,
- 'energy_meter_ids': updated_meters
- })
-
- if month < 9 and current_read is not None:
- return current_read
- else:
- return last_read
+ # if month < 9 and current_read is not None:
+ # return current_read
+ # else:
+ # return last_read
diff --git a/yuthon_property/wizard/property_water_wizard.py b/yuthon_property/wizard/property_water_wizard.py
index 7dc981050..2ac40ac5d 100644
--- a/yuthon_property/wizard/property_water_wizard.py
+++ b/yuthon_property/wizard/property_water_wizard.py
@@ -16,79 +16,108 @@ class PropertyWaterWizard(models.Model):
def confirm(self):
"""
- 导入excel文件,按行读取数据并处理
+ 导入excel文件,按行读取数据并处理,将1-9月数据写入明细行
"""
if not self.excel_file:
raise ValidationError('请上传文件。')
- book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
- sh = book.sheet_by_index(0)
+
+ try:
+ book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
+ sh = book.sheet_by_index(0)
+ except Exception as e:
+ raise ValidationError(f'文件解析错误: {str(e)}')
for rx in range(1, sh.nrows):
row = sh.row(rx)
- last_read = 0
+ last_read = 0.0
for month in range(1, 10):
last_read = self.property_water_data(row, last_read, month)
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'message': f'成功导入 {sh.nrows - 1} 条水表数据及明细',
+ 'type': 'success',
+ 'sticky': False,
+ }
+ }
- def property_water_data(self,row, last_read, month):
+ def property_water_data(self, row, last_read, month):
epitope_values = row[0].value
- name = row[3].value
- type_dict = {'水表': 'water', '电表': 'electric', '电表(电子表)': 'smart', '': ''}
- meter_type = type_dict.get(row[4].value)
+ name = row[3].value # 仪表编号
unit_number = row[1].value
installation_location = row[2].value
- if row[5].value:
- gauge_magnification = float(row[5].value)
- else:
- gauge_magnification = None
+
+ # 仪表倍率
+ gauge_magnification = float(row[5].value) if row[5].value else None
+ # 最大位数
maximum_count = float(row[6].value) if row[6].value else None
+
+ # 类型转换
type_dict = {'公共': 'public', '收费': 'fees', '': ''}
- type = type_dict.get(row[7].value)
+ meter_type = type_dict.get(row[7].value)
+
+ # 物业信息
property_id = None
if row[2].value:
- property_search = self.env['yuthon.property'].search([('name', '=', row[2].value)])
+ property_search = self.env['yuthon.property'].search([('name', '=', row[2].value)], limit=1)
if property_search:
property_id = property_search[0]
+ # 读数索引
current_read_index = month + 9 if month < 9 else 9
- meter_date = None
- current_read = None
- # 1-8月份设置正常数据,9月份留空
- if month < 9:
- meter_date = datetime(2025, month, 15)
- current_read = row[current_read_index].value
- is_push = month < 9 # 9月份依然保持is_push为False
- additional_data = {
+
+ # 1-8月正常数据,9月留空
+ meter_date = datetime(2025, month, 15) if month < 9 else None
+ current_read = row[current_read_index].value if (month < 9 and row[current_read_index].value) else None
+ # 查找或创建水表主记录
+ water = self.env['property.meter.water'].search([('name', '=', name),
+ ('is_push', '=', False)
+ ], limit=1)
+ if not water:
+ water = self.env['property.meter.water'].create({
+ 'name': name,
+ 'epitope_values': epitope_values,
+ 'unit_number': unit_number,
+ 'installation_location': installation_location,
+ 'type': meter_type,
+ 'gauge_magnification': gauge_magnification,
+ 'maximum_count': maximum_count,
+ 'yuthon_property_ids': [(4, property_id.id)] if property_id else [],
+ })
+ else:
+ water.write({
+ 'epitope_values': epitope_values,
+ 'unit_number': unit_number,
+ 'installation_location': installation_location,
+ 'type': meter_type,
+ 'gauge_magnification': gauge_magnification,
+ 'maximum_count': maximum_count,
+ 'yuthon_property_ids': [(4, property_id.id)] if property_id else [],
+ })
+
+ # 计算用量
+ last_dosage = None
+ if last_read is not None and current_read is not None:
+ last_dosage = float(current_read) - float(last_read)
+
+ # 准备明细行数据
+ line_vals = {
'name': name,
'epitope_values': epitope_values,
- 'maximum_count': maximum_count,
'unit_number': unit_number,
- 'installation_location': installation_location,
- 'type': type,
+ 'type': meter_type,
'gauge_magnification': gauge_magnification,
- 'meter_date': meter_date,
- 'current_read': current_read,
+ 'maximum_count': maximum_count,
'last_read': last_read,
- 'is_push': is_push,
+ 'current_read': current_read,
+ 'last_dosage': last_dosage,
+ 'last_meter': meter_date,
+ 'last_reading_time': meter_date,
'yuthon_property_ids': [(4, property_id.id)] if property_id else [],
}
+ water.write({'line_ids': [(0, 0, line_vals)]})
- # 处理数据逻辑...
- combined_data = {**additional_data}
- meter_id = self.env['property.meter.water'].create(combined_data)
-
- if property_id:
- clear_entries = [(5,)]
- new_meter_entry = (0, 0, {
- 'property_meter_water_id': meter_id.id,
- })
- updated_meters = clear_entries + [new_meter_entry]
- property_id.write({
- 'is_meter': True,
- 'water_meter_ids': updated_meters
- })
-
- if month < 9 and current_read is not None:
- return current_read
- else:
- return last_read
+ # 返回当前读数作为下月上次读数
+ return float(current_read) if (month < 9 and current_read is not None) else last_read
diff --git a/yuthon_property_approval/views/property_accounting_approval_views.xml b/yuthon_property_approval/views/property_accounting_approval_views.xml
index f62105b84..79f638557 100644
--- a/yuthon_property_approval/views/property_accounting_approval_views.xml
+++ b/yuthon_property_approval/views/property_accounting_approval_views.xml
@@ -66,6 +66,7 @@
force_save="1"/>
+
@@ -74,7 +75,7 @@
-
+