Merge branch 'dev' of gitee.com:jinan-pengyusen-data/gzth into dev
This commit is contained in:
@@ -57,6 +57,15 @@ class HrAttendance(models.Model):
|
||||
is_month = fields.Boolean(string="是否为本月数据", compute='_compute_month_status', store=True)
|
||||
is_last_month = fields.Boolean(string="是否为上月数据", compute='_compute_month_status', store=True)
|
||||
|
||||
def state_fix(self):
|
||||
for att in self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id'))):
|
||||
att.write({'is_no_card': False,
|
||||
'is_early_card': False,
|
||||
'is_late_card': False,
|
||||
'is_abnormal': False,
|
||||
'is_warning':False,
|
||||
'absenteeism_card': False})
|
||||
|
||||
@api.depends('is_no_card', 'is_early_card', 'is_late_card', 'is_abnormal', 'absenteeism_card')
|
||||
def _compute_is_warning(self):
|
||||
for record in self:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<!-- <button name="compute_company_id" string="公司更新" type="object" class="btn btn-primary"/>-->
|
||||
<!-- <button name="button_all" string="班次更新" type="object" class="btn btn-primary"/>-->
|
||||
<button name="compute_attendance_ids" string="重新计算" type="object" class="btn btn-primary"/>
|
||||
<button name="state_fix" string="状态修正" type="object" class="btn btn-primary" groups="yuthon_hr_attendance.group_he_attendance_sign_manager"/>
|
||||
</header>
|
||||
<field name="employee_id" class="list_current_data" options="{'no_create': True}"/>
|
||||
<field name="current_data" optional="show" class="list_current_data"/>
|
||||
@@ -27,8 +28,8 @@
|
||||
<field name="is_no_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_early_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_late_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_abnormal" optional="show" class="list_ids_width"/>
|
||||
<field name="absenteeism_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_abnormal" optional="show" class="list_ids_width"/>
|
||||
<field name="abnormal" optional="show" column_invisible="1"/>
|
||||
<field name="work_time_type" optional="hidden"/>
|
||||
<field name="is_approval" optional="hidden"/>
|
||||
@@ -68,8 +69,8 @@
|
||||
<field name="is_no_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_early_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_late_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_abnormal" optional="show" class="list_ids_width"/>
|
||||
<field name="absenteeism_card" optional="show" class="list_ids_width"/>
|
||||
<field name="is_abnormal" optional="show" class="list_ids_width"/>
|
||||
<field name="abnormal" optional="show" column_invisible="1"/>
|
||||
<field name="work_time_type" optional="hidden"/>
|
||||
<field name="is_approval" optional="hidden"/>
|
||||
|
||||
@@ -41,9 +41,10 @@ class YuthonLeavingApproval(models.Model):
|
||||
|
||||
def put_leaving(self):
|
||||
for record in self:
|
||||
user_id = record.employee_id.user_id
|
||||
if user_id:
|
||||
user_id.write({'password': '000000'})
|
||||
contract_id = record.employee_id.contract_id
|
||||
if contract_id:
|
||||
contract_id.termination_date = record.expected_departure_date
|
||||
|
||||
|
||||
@api.depends('employee_id')
|
||||
def _compute_name(self):
|
||||
|
||||
@@ -57,6 +57,50 @@ class PropertyBankStatements(models.Model):
|
||||
])
|
||||
if bank_lines:
|
||||
tenant_id = bank_lines[0].tenant_id.id
|
||||
rec.bank_state = 'not_reconciled'
|
||||
rec.registered = 0
|
||||
rec.no_amount = rec.original_amount
|
||||
rec.yes_amount = 0
|
||||
penalty_records = self.env['property.accounts.receivable'].search([('bank_id', '=', self.id)])
|
||||
if not penalty_records:
|
||||
start_date_obj = fields.Date.from_string(start_date)
|
||||
year = start_date_obj.year
|
||||
month = start_date_obj.month
|
||||
month_start = datetime(year, month, 1).date()
|
||||
if month == 12:
|
||||
month_end = datetime(year, 12, 31).date()
|
||||
else:
|
||||
month_end = (datetime(year, month + 1, 1).date() - relativedelta(days=1))
|
||||
month_start_str = fields.Date.to_string(month_start)
|
||||
month_end_str = fields.Date.to_string(month_end)
|
||||
penalty_records = self.env['property.accounts.receivable'].search([
|
||||
('due_date', '>=', month_start_str),
|
||||
('due_date', '<=', month_end_str),
|
||||
('lessee_id', '=', tenant_id),
|
||||
('contract_id', 'in', rec.contract_ids.ids),
|
||||
('property_id', 'in', rec.property_ids.ids),
|
||||
('management_type_id', '=', penalty_type.id)
|
||||
])
|
||||
to_restore = penalty_records.filtered(lambda r: r.is_write)
|
||||
if to_restore:
|
||||
to_restore.write({'is_write': False,
|
||||
'due_date_end': None,
|
||||
'delivered1': None,
|
||||
'is_reconciliation': False,
|
||||
'payout_date': None,
|
||||
})
|
||||
return
|
||||
|
||||
target_year = start_date.year
|
||||
target_month = start_date.month
|
||||
to_delete = penalty_records.filtered(
|
||||
lambda r: not r.is_write
|
||||
and fields.Date.from_string(r.due_date).year == target_year
|
||||
and fields.Date.from_string(r.due_date).month == target_month
|
||||
)
|
||||
if to_delete:
|
||||
to_delete.unlink()
|
||||
|
||||
accounts = self.env['property.accounts.receivable'].search([
|
||||
('payout_date', '=', start_date),
|
||||
('lessee_id', '=', tenant_id),
|
||||
@@ -64,41 +108,15 @@ class PropertyBankStatements(models.Model):
|
||||
('property_id', 'in', rec.property_ids.ids),
|
||||
('management_type_id', '!=', penalty_type.id),
|
||||
])
|
||||
rec.bank_state = 'not_reconciled'
|
||||
rec.registered = 0
|
||||
rec.no_amount = rec.original_amount
|
||||
rec.yes_amount = 0
|
||||
if accounts:
|
||||
for account in accounts:
|
||||
account.write({'is_reconciliation': False,
|
||||
'payout_date': False,
|
||||
'delivered1': 0,
|
||||
'due_date_end' :None,
|
||||
'reconciliation_time': False,
|
||||
'remark':None,
|
||||
'due_date_end': None,
|
||||
'reconciliation_time': False,
|
||||
'remark': None,
|
||||
})
|
||||
penalty_records = self.env['property.accounts.receivable'].search([('bank_id', '=', self.id)])
|
||||
if not penalty_records:
|
||||
penalty_records = self.env['property.accounts.receivable'].search([
|
||||
('due_date', '=', start_date),
|
||||
('lessee_id', '=', tenant_id),
|
||||
('contract_id', 'in', rec.contract_ids.ids),
|
||||
('property_id', 'in', rec.property_ids.ids),
|
||||
('management_type_id', '=', penalty_type.id)
|
||||
])
|
||||
to_restore = penalty_records.filtered(lambda r: r.is_write)
|
||||
if to_restore:
|
||||
to_restore.write({'is_write': False,
|
||||
'due_date_end': None,
|
||||
'delivered1': None,
|
||||
'is_reconciliation': False,
|
||||
'payout_date': None,
|
||||
})
|
||||
return
|
||||
|
||||
to_delete = penalty_records.filtered(lambda r: not r.is_write)
|
||||
if to_delete:
|
||||
to_delete.unlink()
|
||||
|
||||
def binding_information(self):
|
||||
return {
|
||||
|
||||
@@ -2,6 +2,7 @@ from odoo import models, fields, api, _, SUPERUSER_ID
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
import re
|
||||
|
||||
|
||||
class PropertyReconciliationWizard(models.Model):
|
||||
@@ -63,7 +64,6 @@ class PropertyReconciliationWizard(models.Model):
|
||||
'collection_type': 'penalty',
|
||||
'remake': penalty.remark,
|
||||
})
|
||||
|
||||
start_time = self.bank_id.start_time
|
||||
first_day_of_last_month = (start_time.replace(day=1) - relativedelta(months=1))
|
||||
last_day_of_last_month = start_time.replace(day=1) - relativedelta(days=1)
|
||||
@@ -91,9 +91,15 @@ class PropertyReconciliationWizard(models.Model):
|
||||
end_date_str = self.actual_date
|
||||
# 处理新产生的违约金
|
||||
if penalty_amount > 0:
|
||||
exists = any(p['due_date'] == self.actual_date and
|
||||
p['contract_id'] == contract_id.id
|
||||
for p in contract_penalties)
|
||||
actual_date_obj = fields.Date.from_string(self.actual_date)
|
||||
actual_year_month = (actual_date_obj.year, actual_date_obj.month)
|
||||
exists = any(
|
||||
# 提取合同违约金记录的年月并比较
|
||||
(fields.Date.from_string(p['due_date']).year,
|
||||
fields.Date.from_string(p['due_date']).month) == actual_year_month
|
||||
and p['contract_id'] == contract_id.id
|
||||
for p in contract_penalties
|
||||
)
|
||||
if not exists:
|
||||
contract_penalties.append({
|
||||
'property_id': property_id,
|
||||
@@ -109,6 +115,7 @@ class PropertyReconciliationWizard(models.Model):
|
||||
# 3. 添加到总列表
|
||||
for vals in contract_penalties:
|
||||
new_lines.append((0, 0, vals))
|
||||
|
||||
if new_lines:
|
||||
keep_lines = [
|
||||
(4, line.id) for line in self.reconciliation_line_ids
|
||||
@@ -125,6 +132,71 @@ class PropertyReconciliationWizard(models.Model):
|
||||
|
||||
remaining_amount = self.actual_total
|
||||
|
||||
rent_lines_key = set()
|
||||
target_rent_months = []
|
||||
for line in self.reconciliation_line_ids:
|
||||
if line.collection_type == 'rent' and line.amount == 0 and line.due_date:
|
||||
# 提取到期日期的年月(作为分组依据)
|
||||
due_month = fields.Date.from_string(line.due_date).strftime('%Y-%m')
|
||||
line_key = (
|
||||
line.contract_id.id if line.contract_id else None,
|
||||
line.property_id.id if line.property_id else None,
|
||||
due_month
|
||||
)
|
||||
if line_key not in rent_lines_key:
|
||||
rent_lines_key.add(line_key)
|
||||
target_rent_months.append({
|
||||
'contract_id': line.contract_id,
|
||||
'property_id': line.property_id,
|
||||
'due_month': due_month # 待补违约金的年月
|
||||
})
|
||||
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,
|
||||
line.property_id.id if line.property_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']
|
||||
property_rec = rent_info['property_id']
|
||||
due_month = rent_info['due_month']
|
||||
|
||||
# 构建待检查的违约金key(合同+物业+年月)
|
||||
check_key = (
|
||||
contract.id if contract else None,
|
||||
property_rec.id if property_rec else None,
|
||||
due_month
|
||||
)
|
||||
|
||||
# 若该年月的违约金不存在,则补全
|
||||
if check_key not in existing_penalty_months:
|
||||
# 计算补全违约金的日期范围:当月1号 ~ 当月最后1天
|
||||
year, month = map(int, due_month.split('-'))
|
||||
first_day = datetime(year, month, 1).date()
|
||||
penalty_days = (self.actual_date - first_day).days + 1 # 当月总天数
|
||||
penalty_amount = penalty_days * round(contract.rent * float(contract_id.percentage_liquidated_damages.name), 2) if contract else 0.0
|
||||
if penalty_amount > 0:
|
||||
missing_penalty_lines.append((0, 0, {
|
||||
'property_id': property_rec.id if property_rec else None,
|
||||
'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})
|
||||
|
||||
# 检查是否有单行的rent等于实际金额
|
||||
exact_match_line = next((line for line in self.reconciliation_line_ids if line.rent == remaining_amount), None)
|
||||
if exact_match_line:
|
||||
@@ -232,6 +304,11 @@ class PropertyReconciliationWizard(models.Model):
|
||||
# 检查是否已有相同记录
|
||||
existing_record = self.env['property.accounts.receivable'].search(check_domain)
|
||||
is_reconciliation = line.amount == line.rent
|
||||
# 用备注的的开始日期和结束日期
|
||||
date_pattern = r'(\d{4}-\d{2}-\d{2})[至-](\d{4}-\d{2}-\d{2})'
|
||||
date_match = re.search(date_pattern, line.remake or '')
|
||||
extract_start_date = date_match.group(1) if date_match else line.due_date
|
||||
extract_end_date = date_match.group(2) if date_match else None
|
||||
if not existing_record:
|
||||
domain2 = [
|
||||
('due_date', '=', line.due_date),
|
||||
@@ -242,14 +319,13 @@ class PropertyReconciliationWizard(models.Model):
|
||||
reconciliation_id = self.env['property.reconciliation.line'].search(domain2, limit=1)
|
||||
self.env['property.accounts.receivable'].create({
|
||||
'is_reconciliation': is_reconciliation,
|
||||
'due_date': line.due_date,
|
||||
'due_date_end': rec.actual_date if (line.rent == line.amount and line.rent != 0) else None,
|
||||
'due_date': extract_start_date,
|
||||
'due_date_end': extract_end_date,
|
||||
'penalty': reconciliation_id.rent,
|
||||
'management_type_id': management_type_id.id,
|
||||
'lessee_id': first_line.tenant_id.id,
|
||||
'property_id': line.property_id.id,
|
||||
'contract_id': line.contract_id.id,
|
||||
'bank_id': rec.bank_id.id,
|
||||
'delivered1': line.amount,
|
||||
'payout_date': rec.actual_date if (line.rent == line.amount and line.rent != 0) else None,
|
||||
'original_amount': line.rent,
|
||||
@@ -259,12 +335,12 @@ class PropertyReconciliationWizard(models.Model):
|
||||
else:
|
||||
existing_record.write({
|
||||
'delivered1': line.amount,
|
||||
'due_date_end': rec.actual_date if (line.rent == line.amount and line.rent != 0) else None,
|
||||
'due_date_end': extract_end_date,
|
||||
'is_reconciliation': is_reconciliation,
|
||||
'payout_date': rec.actual_date if (line.rent == line.amount and line.rent != 0) else None,
|
||||
'remark': line.remake,
|
||||
'bank_id': rec.bank_id.id,
|
||||
'is_write': True,
|
||||
'bank_id': rec.bank_id.id if line.amount != 0 else None,
|
||||
'is_write': True if line.amount != 0 else None,
|
||||
'reconciliation_time': fields.Datetime.now(),
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user