diff --git a/yuthon_hr_attendance/models/yuthon_vacation_reports.py b/yuthon_hr_attendance/models/yuthon_vacation_reports.py index fabd6e68b..fd10ec1b5 100644 --- a/yuthon_hr_attendance/models/yuthon_vacation_reports.py +++ b/yuthon_hr_attendance/models/yuthon_vacation_reports.py @@ -219,7 +219,7 @@ class YuthonVacationReports(models.Model): rec.update_line() def update_line(self): - if self.vacation_date == fields.Date.from_string('2026-01-01'): + if self.vacation_date == fields.Date.from_string('2026-01-01') or (self.vacation_date == fields.Date.from_string('2026-03-01') and self.employee_id.name == '天河物管'): return self.manage_reject() # ========== 第一步:处理年假逻辑 ========== diff --git a/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py b/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py index 71aaaf89a..fe0681f6e 100644 --- a/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py +++ b/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard.py @@ -14,6 +14,7 @@ class YuthonVacationImportWizard(models.TransientModel): excel_file = fields.Binary(string="上传Excel表") excel_name = fields.Char(string="文件名") + company_id = fields.Many2one('res.company', string='公司') def confirm(self): """ @@ -24,14 +25,18 @@ class YuthonVacationImportWizard(models.TransientModel): 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): - row = sh.row(rx) - self.leave_import(row) + if self.company_id.name in ['集团本部', '天河粮储']: + for rx in range(1, sh.nrows): + row = sh.row(rx) + self.leave_import(row) + else: + for rx in range(1, sh.nrows): + row = sh.row(rx) + self.leave_import1(row) def leave_import(self, row): employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)], limit=1) if not employee_id: - self.env.user.notify_warning(f"员工 {row[0].value} 不存在,跳过处理") return date = datetime(2026, 1, 1) @@ -39,24 +44,97 @@ class YuthonVacationImportWizard(models.TransientModel): [('employee_id', '=', employee_id.id), ('vacation_date', '=', date)], limit=1 ) + if vacation_id: - target_leaves = vacation_id.leave_ids.filtered(lambda l: l.text == '上月额度继承') - for leave in target_leaves: - update_value = int(row[1].value) * 8 - if update_value == 0: - leave.unlink() - else: - leave.write({'update_lines': update_value}) + if employee_id.company_id.name == '天河粮储': + target_leaves = vacation_id.leave_ids.filtered(lambda l: l.text == '年假分配') + for leave in target_leaves: + update_value = float(row[1].value) * 8 + if update_value == 0: + leave.unlink() + else: + leave.write({'update_lines': update_value}) + target_leaves1 = vacation_id.leave_ids.filtered(lambda l: l.text == '上月额度继承') + for leave in target_leaves1: + update_value = float(row[2].value) * 8 + if update_value == 0: + leave.unlink() + else: + leave.write({'update_lines': update_value}) + target_overtimes = vacation_id.overtime_ids.filtered(lambda o: o.text == '上月额度继承') for overtime in target_overtimes: - workday_value = int(row[2].value) * 8 - if workday_value == 0: + if employee_id.company_id.name == '集团本部': + workday_value = float(row[3].value) + public_holidays = float(row[4].value) + else: + workday_value = float(row[3].value) * 8 + public_holidays = 0 + if workday_value == 0 and public_holidays == 0: overtime.unlink() else: - overtime.write({'workday': workday_value}) + overtime.write({'workday': workday_value, + 'public_holidays': public_holidays}) vacation_id.update_vacation1() + vacation_id._compute_leave() + vacation_id._compute_working_overtime() + def leave_import1(self, row): + employee_id = self.env['hr.employee'].search([('name', '=', row[0].value)], limit=1) + if not employee_id: + self.env.user.notify_warning(f"员工 {row[0].value} 不存在,跳过处理") + return + date = datetime(2026, 3, 1) + vacation_id = self.env['yuthon.vacation.reports'].search( + [('employee_id', '=', employee_id.id), ('vacation_date', '=', date)], + limit=1 + ) + if vacation_id: + target_leaves = vacation_id.leave_ids.filtered(lambda l: l.text == '上月额度继承') + update_value = float(row[1].value) * 8 + if target_leaves: + for leave in target_leaves: + if update_value == 0: + leave.unlink() + else: + leave.write({ + 'update_lines': update_value, + }) + vacation_id.dynamic_previous_year = update_value / 8 + else: + if update_value != 0: + self.env[vacation_id.leave_ids._name].create({ + 'text': '上月额度继承', + 'update_type': 'add', + 'update_date': date, + 'valid_date': datetime(2027, 2, 28), + 'update_lines': update_value, + 'vacation_id': vacation_id.id, + }) + vacation_id.dynamic_previous_year = update_value / 8 - + target_overtimes = vacation_id.overtime_ids.filtered(lambda o: o.text == '上月额度继承') + workday_value = float(row[2].value) * 8 + if target_overtimes: + for overtime in target_overtimes: + if workday_value == 0: + overtime.unlink() + else: + overtime.write({'workday': workday_value}) + vacation_id.dynamic_previous_year1 = workday_value / 8 + else: + if workday_value != 0: + self.env[vacation_id.overtime_ids._name].create({ + 'text': '上月额度继承', + 'update_type': 'add', + 'update_date': date, + 'overtime_methods': 'leave', + 'valid_date': datetime(2027, 2, 28), + 'workday': workday_value, + 'vacation_id': vacation_id.id, + }) + vacation_id.dynamic_previous_year1 = workday_value / 8 + vacation_id._compute_leave() + vacation_id._compute_working_overtime() diff --git a/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard_views.xml b/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard_views.xml index 9cfcd3eba..f4bd990c1 100644 --- a/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard_views.xml +++ b/yuthon_hr_attendance/wizard/yuthon_vacation_import_wizard_views.xml @@ -8,6 +8,7 @@ + diff --git a/yuthon_report/models/current_receivable_property_fee_report.py b/yuthon_report/models/current_receivable_property_fee_report.py index 6dbe31589..adebda322 100644 --- a/yuthon_report/models/current_receivable_property_fee_report.py +++ b/yuthon_report/models/current_receivable_property_fee_report.py @@ -79,7 +79,11 @@ class CurrentReceivablePropertyFeeReport(models.Model): for idx, rec in enumerate(receivables, start=1): amt = rec.original_amount or 0.0 # 从合同获取税率 - tax_rate = float(rec.contract_id.tax_rate.name) * 100 if rec.contract_id and rec.contract_id.tax_rate else 0.0 + try: + tax_rate_str = str(rec.contract_id.tax_rate.name) if rec.contract_id and rec.contract_id.tax_rate else "0" + tax_rate = float(tax_rate_str.replace('%', '').strip()) if tax_rate_str else 0.0 + except (ValueError, TypeError): + tax_rate = 0.0 amt_nt = amt / (1 + tax_rate / 100) if tax_rate else amt total_amount += amt total_amount_nt += amt_nt diff --git a/yuthon_report/models/current_receivable_rent_report.py b/yuthon_report/models/current_receivable_rent_report.py index 71b6d2ff0..ea94a6661 100644 --- a/yuthon_report/models/current_receivable_rent_report.py +++ b/yuthon_report/models/current_receivable_rent_report.py @@ -64,7 +64,11 @@ class CurrentReceivableRentReport(models.Model): # 实际应收 = 原始金额 - 减免金额 actual_amt = amt - discount # 从合同获取税率 - tax_rate = float(rec.contract_id.tax_rate.name) * 100 if rec.contract_id and rec.contract_id.tax_rate else 0.0 + try: + tax_rate_str = str(rec.contract_id.tax_rate.name) if rec.contract_id and rec.contract_id.tax_rate else "0" + tax_rate = float(tax_rate_str.replace('%', '').strip()) if tax_rate_str else 0.0 + except (ValueError, TypeError): + tax_rate = 0.0 actual_amt_nt = actual_amt / (1 + tax_rate / 100) if tax_rate else actual_amt # 统计每个管理类型的合计 diff --git a/yuthon_report/models/receivable_report.py b/yuthon_report/models/receivable_report.py index b8792c727..c23970f27 100644 --- a/yuthon_report/models/receivable_report.py +++ b/yuthon_report/models/receivable_report.py @@ -65,6 +65,11 @@ class YuthonProperty(models.Model): "应收开始": rec.due_date.strftime("%Y-%m-%d") if rec.due_date else "", "应收结束": rec.due_date_end.strftime("%Y-%m-%d") if rec.due_date_end else "", "当期金额": round(amount, 2), + "合同编号": { + 'model': 'property.lease.contract', + 'id': rec.contract_id.id, + 'display_name': rec.contract_id.contract_code, + } if rec.contract_id else "", "承租方": { 'model': 'property.tenant.information', 'id': rec.lessee_id.id, @@ -72,13 +77,16 @@ class YuthonProperty(models.Model): } if rec.lessee_id else "", "物业名称": rec.property_name or "", "产权证号": rec.title_deed or "", - "合同编号": { - 'model': 'property.lease.contract', - 'id': rec.contract_id.id, - 'display_name': rec.contract_id.contract_code, - } if rec.contract_id else "", - "发票类型": invoice_type_map.get(rec.invoice_type, ""), - "税率": f"{float(rec.contract_id.tax_rate.name) * 100:.1f}%" if rec.contract_id and rec.contract_id.tax_rate else "0.0%" + "发票类型": rec.lessee_id.invoicing_ids[0].invoicing_type_id.name if rec.lessee_id and rec.lessee_id.invoicing_ids else "", + "税率": ( + lambda tr: ( + lambda v: f"{v:.1f}%" if v is not None else "0.0%" + )( + float(str(tr).replace('%', '').strip()) + if tr and str(tr).replace('%', '').strip() + else None + ) + )(rec.contract_id.tax_rate.name if rec.contract_id and rec.contract_id.tax_rate else None) }) summary_stats = [] diff --git a/yuthon_report/views/receivable_report_views.xml b/yuthon_report/views/receivable_report_views.xml index 55f2fe90b..132782f32 100644 --- a/yuthon_report/views/receivable_report_views.xml +++ b/yuthon_report/views/receivable_report_views.xml @@ -15,10 +15,10 @@ {"headerName": "应收开始", "field": "应收开始", "flex": 1}, {"headerName": "应收结束", "field": "应收结束", "flex": 1}, {"headerName": "当期金额", "field": "当期金额", "flex": 1, "type": "number"}, + {"headerName": "合同编号", "field": "合同编号", "flex": 1}, {"headerName": "承租方", "field": "承租方", "flex": 1}, {"headerName": "物业名称", "field": "物业名称", "flex": 1}, {"headerName": "产权证号", "field": "产权证号", "flex": 1}, - {"headerName": "合同编号", "field": "合同编号", "flex": 1}, {"headerName": "发票类型", "field": "发票类型", "flex": 1}, {"headerName": "税率", "field": "税率", "flex": 1} ]