diff --git a/yuthon_property/wizard/property_statements_wizard.py b/yuthon_property/wizard/property_statements_wizard.py index 1cc8be146..70a696f03 100644 --- a/yuthon_property/wizard/property_statements_wizard.py +++ b/yuthon_property/wizard/property_statements_wizard.py @@ -11,7 +11,7 @@ class PropertyStatementsWizard(models.Model): _name = 'property.statements.wizard' _description = '银行流水向导弹窗' - selection_bank = fields.Selection([('js', '建设银行'), ('gs', '工商银行'), ('sh', '农商'), ('ms', '民生'), ('zc', '广州银行(中城)'), ('dj', '农商行(东进)')], string="选择银行") + selection_bank = fields.Selection([('js', '建设银行'), ('gs', '工商银行'), ('sh', '农商'), ('ms', '民生'), ('zc', '广州银行(中城)'), ('dj', '农商行(东进)'), ('xy', '工商银行(兴源)')], string="选择银行") excel_file = fields.Binary(string="上传Excel表") excel_name = fields.Char(string="文件名") @@ -57,6 +57,8 @@ class PropertyStatementsWizard(models.Model): self.property_bank_statements_ms_data(row) elif self.selection_bank == 'gs': self.property_bank_statements_gc_data(row) + elif self.selection_bank == 'xy': + self.property_bank_statements_xy_data(row) return { 'type': 'ir.actions.client', @@ -344,10 +346,11 @@ class PropertyStatementsWizard(models.Model): existing_record.write(bank_data) - def property_bank_statements_gc_data(self, row): - """工商银行(兴苑)解析:数据从第2行开始,列结构(共34列): - 0:交易时间, 1:对方单位, 2:摘要, 7:借贷标志, 8:发生额, - 9:对方账号, 16:本方账号, 22:对方行名, 31:顺序号 + def property_bank_statements_xy_data(self, row): + """工商银行(兴源)解析:数据从第2行开始,列结构(共34列): + 0:交易时间, 1:对方单位, 2:摘要, 4:转入金额(贷时取), 7:借贷标志, + 8:发生额(借时取), 9:对方账号, 16:本方账号, 22:对方行名, 31:顺序号 + 金额取数规则:H列=贷 取E列(索引4转入金额),H列=借 取I列(索引8发生额) """ serial_number = str(row[31].value).strip() if row[31].value else '' @@ -361,17 +364,17 @@ class PropertyStatementsWizard(models.Model): else: start_time = None - # 借贷方向 + # 借贷方向,并按规则取对应金额列 direction_val = str(row[7].value).strip() if row[7].value else '' if direction_val == '贷': lending_direction = 'loan' + amount_str = str(row[4].value).replace(',', '').strip() if row[4].value else '' # E列:转入金额 elif direction_val == '借': lending_direction = 'borrow' + amount_str = str(row[8].value).replace(',', '').strip() if row[8].value else '' # I列:发生额 else: return - # 金额(去逗号) - amount_str = str(row[8].value).replace(',', '').strip() if row[8].value else '' try: original_amount = float(amount_str) except Exception: @@ -414,6 +417,41 @@ class PropertyStatementsWizard(models.Model): else: existing_record.write(bank_data) + def property_bank_statements_gc_data(self, row): + """工商银行(原始格式)解析""" + if row[0].value: + start_time = datetime.strptime(row[0].value, '%Y-%m-%d %H:%M:%S') + else: + start_time = None + name = row[4].value + name_account = row[1].value + remake = row[2].value + original_amount = row[3].value + your_own_account = row[6].value + cleaned_amount = str(original_amount).replace(',', '') + float_amount = float(cleaned_amount) + your_own_unit = self.classify_by_last_four(your_own_account) + company_id = self._get_company_by_unit(your_own_unit) + if not company_id: + return + sequence_number = row[5].value + bank_data = { + 'name': name, + 'your_own_unit': your_own_unit, + 'original_amount': float_amount, + 'company_id': company_id.id, + 'sequence_number': sequence_number, + 'start_time': start_time - timedelta(hours=8) if start_time else False, + 'your_own_account': your_own_account, + 'name_account': name_account, + 'remake': remake, + } + existing_record = self.env['property.bank.statements'].search( + [('sequence_number', '=', sequence_number)], limit=1 + ) + if not existing_record: + self.env['property.bank.statements'].create(bank_data) + def _get_company_by_unit(self, unit_name): """根据账号单位返回对应公司""" if unit_name in ['天河投资', '天投城建']: diff --git a/yuthon_report/models/receivable_flow_report.py b/yuthon_report/models/receivable_flow_report.py index fa86b68b0..9061399c6 100644 --- a/yuthon_report/models/receivable_flow_report.py +++ b/yuthon_report/models/receivable_flow_report.py @@ -71,25 +71,36 @@ class ReceivableFlowReport(models.Model): for ml in all_modify_lines: modify_map.setdefault(ml.receivable_id.id, []).append(ml) - # 2. 批量查违约金wizard(sudo跳过多公司权限) + # 2. 直接查询所有 penalty.pay.line 记录 + # 先查询所有相关的 penalty.line.wizard all_wizards = self.env['penalty.line.wizard'].sudo().search([ ('receivable_id', 'in', rec_ids), ]) all_wizard_ids = all_wizards.ids - # 批量查所有 penalty.pay.line(不再只查最新wizard) + + # 然后查询所有相关的 penalty.pay.line if all_wizard_ids: all_penalty_pay_lines = self.env['penalty.pay.line'].sudo().search([ ('penalty_id', 'in', all_wizard_ids), ]) else: all_penalty_pay_lines = self.env['penalty.pay.line'] - all_penalty_pay_lines.mapped('management_type_id') # 预加载类型 + + # 调试信息 + import logging + _logger = logging.getLogger(__name__) + _logger.info(f"查询的 rec_ids 数量: {len(rec_ids)}, 示例: {rec_ids[:5] if len(rec_ids) > 5 else rec_ids}") + _logger.info(f"查询到的 all_wizards 数量: {len(all_wizards)}") + _logger.info(f"查询到的 all_penalty_pay_lines 数量: {len(all_penalty_pay_lines)}") + # 按 receivable_id 分组 {receivable_id: [penalty_pay_lines]} penalty_pay_map = {} for ppl in all_penalty_pay_lines: rid = ppl.penalty_id.receivable_id.id if ppl.penalty_id and ppl.penalty_id.receivable_id else None if rid: penalty_pay_map.setdefault(rid, []).append(ppl) + + _logger.info(f"penalty_pay_map 中的 receivable_id 数量: {len(penalty_pay_map)}, 示例: {list(penalty_pay_map.keys())[:5] if len(penalty_pay_map) > 5 else list(penalty_pay_map.keys())}") # ===== 预加载结束 ===== rows = [] @@ -169,35 +180,34 @@ class ReceivableFlowReport(models.Model): if rec.submitted == 0: charge_status = "已收" - # 违约金收款:直接从 penalty.pay.line 取(持久化数据源) - rec_penalty_pay_lines = penalty_pay_map.get(rec.id, []) + # 违约金收款:直接从 penalty.pay.line 计算 + pay_lines = penalty_pay_map.get(rec.id, []) # 调试信息 import logging _logger = logging.getLogger(__name__) _logger.info(f"应收记录ID: {rec.id}, penalty_type: {penalty_type}, penalty_type.id: {penalty_type.id if penalty_type else None}") - _logger.info(f"rec_penalty_pay_lines 数量: {len(rec_penalty_pay_lines)}") - for ppl in rec_penalty_pay_lines: + _logger.info(f"pay_lines 数量: {len(pay_lines)}") + for ppl in pay_lines: _logger.info(f" - penalty.pay.line ID: {ppl.id}, management_type_id: {ppl.management_type_id}, management_type_id.id: {ppl.management_type_id.id if ppl.management_type_id else None}, amount: {ppl.amount}, date: {ppl.date}") - # 违约金收款金额:类型为“违约金”的金额之和 + # 违约金收款金额:使用你提到的方法计算 + if penalty_type: + collected = sum(pay_line.amount for pay_line in pay_lines + if pay_line.management_type_id == penalty_type) + else: + collected = 0.0 + total_penalty_collected = round(collected, 2) + + # 违约金收款时间:类型为“违约金”的最新收款日期 + penalty_payment_date = None if penalty_type: penalty_pay_collected = [ - l for l in rec_penalty_pay_lines - if l.management_type_id and l.management_type_id.id == penalty_type.id + l for l in pay_lines + if l.management_type_id == penalty_type and l.date ] - else: - penalty_pay_collected = [] - - _logger.info(f"penalty_pay_collected 数量: {len(penalty_pay_collected)}") - - total_penalty_collected = sum(l.amount for l in penalty_pay_collected) - # 违约金收款时间:类型为“违约金”的最新收款日期 - latest_penalty_pay = sorted( - [l for l in penalty_pay_collected if l.date], - key=lambda l: l.date, reverse=True - ) - penalty_payment_date = latest_penalty_pay[0].date if latest_penalty_pay else None + latest_penalty_pay = sorted(penalty_pay_collected, key=lambda l: l.date, reverse=True) + penalty_payment_date = latest_penalty_pay[0].date if latest_penalty_pay else None _logger.info(f"total_penalty_collected: {total_penalty_collected}, penalty_payment_date: {penalty_payment_date}")