@@ -298,6 +298,34 @@
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
|
||||
<record forcecreate="True" id="executive_day_remind_in" model="ir.cron">
|
||||
<field name="name">定时任务:行政班次上班打卡提醒</field>
|
||||
<field name="model_id" ref="model_hr_attendance"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.executive_day_remind_in()</field>
|
||||
<field eval="True" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 17:00:00')"/>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
|
||||
<record forcecreate="True" id="executive_day_remind_out" model="ir.cron">
|
||||
<field name="name">定时任务:行政班次下班打卡提醒</field>
|
||||
<field name="model_id" ref="model_hr_attendance"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.executive_day_remind_out()</field>
|
||||
<field eval="True" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 17:00:00')"/>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<record forcecreate="True" id="card_lc_shift_remind_time_on_administrative" model="ir.cron">
|
||||
<field name="name">定时任务:计划行政上班提醒</field>
|
||||
<field name="name">定时任务:保安部计划行政上班提醒</field>
|
||||
<field name="model_id" ref="model_hr_attendance"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.card_lc_shift_remind_on_administrative()</field>
|
||||
@@ -16,7 +16,7 @@
|
||||
</record>
|
||||
|
||||
<record forcecreate="True" id="card_lc_shift_remind_time_out_administrative" model="ir.cron">
|
||||
<field name="name">定时任务:计划行政下班提醒</field>
|
||||
<field name="name">定时任务:保安部计划行政下班提醒</field>
|
||||
<field name="model_id" ref="model_hr_attendance"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.card_lc_shift_remind_out_administrative()</field>
|
||||
|
||||
@@ -791,7 +791,7 @@ class HrAttendance(models.Model):
|
||||
else:
|
||||
record.week = False
|
||||
|
||||
def _common_card_remind(self, dept_name=None, planning_name=None, is_check_in=True, method_name=None):
|
||||
def _common_card_remind(self, dept_name=None, planning_name=None, is_check_in=True, method_name=None, is_executive=False):
|
||||
"""通用打卡提醒函数"""
|
||||
if not method_name:
|
||||
return
|
||||
@@ -803,24 +803,38 @@ class HrAttendance(models.Model):
|
||||
end_window = next_call + timedelta(minutes=5)
|
||||
if not (start_window <= fields.Datetime.now() + timedelta(hours=8) <= end_window):
|
||||
return
|
||||
slot_start = datetime.combine(current_date, datetime.min.time())
|
||||
slot_end = datetime.combine(current_date + timedelta(days=1), datetime.min.time())
|
||||
domain = [
|
||||
('template_id.planning_name', '=', planning_name),
|
||||
('start_datetime', '>=', slot_start),
|
||||
('start_datetime', '<', slot_end),
|
||||
('role_id.name', '=', dept_name),
|
||||
]
|
||||
planning_slots = self.env['planning.slot'].search(domain)
|
||||
for slot in planning_slots:
|
||||
if is_check_in:
|
||||
is_card = self.env['hr.attendance'].search([('employee_id', '=', slot.employee_id.id), ('check_in', '!=', False), ('current_data', '=', current_date)], limit=1)
|
||||
if not is_card:
|
||||
self.card_in_comment(slot.employee_id, planning_name)
|
||||
else:
|
||||
is_card = self.env['hr.attendance'].search([('employee_id', '=', slot.employee_id.id), ('check_out', '!=', False), ('current_data', '=', current_date)], limit=1)
|
||||
if not is_card:
|
||||
self.card_out_comment(slot.employee_id, planning_name)
|
||||
if is_executive:
|
||||
domain = [('current_data', '=', current_date)]
|
||||
attendances = self.env['hr.attendance'].search(domain)
|
||||
attended_employee_ids = attendances.mapped('employee_id')
|
||||
for employee in attended_employee_ids:
|
||||
if is_check_in:
|
||||
is_card = self.env['hr.attendance'].search([('employee_id', '=', employee.id), ('check_in', '!=', False), ('current_data', '=', current_date)], limit=1)
|
||||
if not is_card:
|
||||
self.card_in_comment(employee, '行政班次')
|
||||
else:
|
||||
is_card = self.env['hr.attendance'].search([('employee_id', '=', employee.id), ('check_out', '!=', False), ('current_data', '=', current_date)], limit=1)
|
||||
if not is_card:
|
||||
self.card_out_comment(employee, '行政班次')
|
||||
else:
|
||||
slot_start = datetime.combine(current_date, datetime.min.time())
|
||||
slot_end = datetime.combine(current_date + timedelta(days=1), datetime.min.time())
|
||||
domain = [
|
||||
('template_id.planning_name', '=', planning_name),
|
||||
('start_datetime', '>=', slot_start),
|
||||
('start_datetime', '<', slot_end),
|
||||
('role_id.name', '=', dept_name),
|
||||
]
|
||||
planning_slots = self.env['planning.slot'].search(domain)
|
||||
for slot in planning_slots:
|
||||
if is_check_in:
|
||||
is_card = self.env['hr.attendance'].search([('employee_id', '=', slot.employee_id.id), ('check_in', '!=', False), ('current_data', '=', current_date)], limit=1)
|
||||
if not is_card:
|
||||
self.card_in_comment(slot.employee_id, planning_name)
|
||||
else:
|
||||
is_card = self.env['hr.attendance'].search([('employee_id', '=', slot.employee_id.id), ('check_out', '!=', False), ('current_data', '=', current_date)], limit=1)
|
||||
if not is_card:
|
||||
self.card_out_comment(slot.employee_id, planning_name)
|
||||
|
||||
# 保安部 - 早班
|
||||
def ba_card_white_up(self):
|
||||
@@ -939,6 +953,15 @@ class HrAttendance(models.Model):
|
||||
self._common_card_remind(dept_name='保安部', planning_name='保安计划行政', is_check_in=False,
|
||||
method_name='card_lc_shift_remind_out_administrative')
|
||||
|
||||
# 行政班次
|
||||
def executive_day_remind_in(self):
|
||||
self._common_card_remind(planning_name='行政班次', is_check_in=True,
|
||||
method_name='executive_day_remind_in', is_executive=True)
|
||||
|
||||
def executive_day_remind_out(self):
|
||||
self._common_card_remind(planning_name='行政班次', is_check_in=False,
|
||||
method_name='executive_day_remind_out', is_executive=True)
|
||||
|
||||
def card_in_comment(self, employee_id, planning_name):
|
||||
data = f"您的班次是{planning_name},还有5分钟上班,记得打卡"
|
||||
url = '#小程序://天投云/XttsPpKg3MEpY7h'
|
||||
|
||||
@@ -17,7 +17,18 @@ class YuthonRunPlanning(models.Model):
|
||||
department_id = fields.Many2one("hr.department", string="部门", required=True)
|
||||
start_date = fields.Date(string='生效日期', default=fields.Datetime.today())
|
||||
end_date = fields.Date(string='失效日期')
|
||||
is_effect = fields.Boolean(string="是否生效", compute="_compute_is_effect")
|
||||
|
||||
@api.depends('start_date', 'end_date')
|
||||
def _compute_is_effect(self):
|
||||
today = fields.Date.today()
|
||||
for record in self:
|
||||
if not record.start_date:
|
||||
record.is_effect = False
|
||||
elif not record.end_date:
|
||||
record.is_effect = record.start_date <= today
|
||||
else:
|
||||
record.is_effect = record.start_date <= today <= record.end_date
|
||||
|
||||
def action_planning_wizard_run(self):
|
||||
return {
|
||||
@@ -48,20 +59,25 @@ class YuthonRunPlanning(models.Model):
|
||||
|
||||
# 运行班
|
||||
def run_confirm(self):
|
||||
selected_month = self.start_date.month
|
||||
year = datetime.now().year
|
||||
first_day_of_month = datetime(year, selected_month, 1)
|
||||
latest_slot = self.env['planning.slot'].search([
|
||||
('department_id.name', '=', '运行班')
|
||||
], order='start_datetime desc', limit=1)
|
||||
# 从最新排班中提取年/月
|
||||
latest_datetime = latest_slot.start_datetime
|
||||
latest_year = latest_datetime.year
|
||||
latest_month = latest_datetime.month
|
||||
|
||||
# 计算下个月的年/月
|
||||
target_month = latest_month + 1
|
||||
target_year = latest_year
|
||||
if target_month > 12:
|
||||
target_month = 1
|
||||
target_year += 1
|
||||
first_day_of_month = datetime(target_year, target_month, 1)
|
||||
# 计算结束日期(当月的最后一天)
|
||||
next_month = (selected_month % 12) + 1
|
||||
next_year = year + (1 if next_month == 1 else 0)
|
||||
next_month = target_month % 12 + 1
|
||||
next_year = target_year + (1 if next_month == 1 else 0)
|
||||
last_day_of_month = datetime(next_year, next_month, 1) - timedelta(days=1)
|
||||
existing_slots = self.env['planning.slot'].search([
|
||||
('department_id.name', '=', '运行班'),
|
||||
('start_datetime', '>=', first_day_of_month),
|
||||
('start_datetime', '<=', last_day_of_month),
|
||||
])
|
||||
if len(existing_slots) > 0:
|
||||
raise UserError(f"该月已经有排程,请选择其他时间。")
|
||||
role_a = self.env['planning.role'].search([('name', '=', '工程部')], limit=1)
|
||||
start_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).start_time)
|
||||
end_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).end_time)
|
||||
@@ -147,20 +163,25 @@ class YuthonRunPlanning(models.Model):
|
||||
}
|
||||
# 高压班
|
||||
def high_confirm(self):
|
||||
selected_month = self.start_date.month
|
||||
year = datetime.now().year
|
||||
first_day_of_month = datetime(year, selected_month, 1)
|
||||
# 计算结束日期(下个月的第一天)
|
||||
next_month = (selected_month % 12) + 1
|
||||
next_year = year + (1 if next_month == 1 else 0) # 如果是12月,年份加1
|
||||
last_day_of_month = datetime(next_year, next_month, 1) - timedelta(days=1)
|
||||
existing_slots = self.env['planning.slot'].search([
|
||||
latest_slot = self.env['planning.slot'].search([
|
||||
('department_id.name', '=', '高压班'),
|
||||
('start_datetime', '>=', first_day_of_month),
|
||||
('start_datetime', '<=', last_day_of_month),
|
||||
])
|
||||
if len(existing_slots) > 0:
|
||||
raise UserError(f"该月已经有排程,请选择其他时间。")
|
||||
], order='start_datetime desc', limit=1)
|
||||
# 从最新排班中提取年/月
|
||||
latest_datetime = latest_slot.start_datetime
|
||||
latest_year = latest_datetime.year
|
||||
latest_month = latest_datetime.month
|
||||
|
||||
# 计算下个月的年/月
|
||||
target_month = latest_month + 1
|
||||
target_year = latest_year
|
||||
if target_month > 12:
|
||||
target_month = 1
|
||||
target_year += 1
|
||||
first_day_of_month = datetime(target_year, target_month, 1)
|
||||
# 计算结束日期(当月的最后一天)
|
||||
next_month = target_month % 12 + 1
|
||||
next_year = target_year + (1 if next_month == 1 else 0)
|
||||
last_day_of_month = datetime(next_year, next_month, 1) - timedelta(days=1)
|
||||
role_a = self.env['planning.role'].search([('name', '=', '工程部')], limit=1)
|
||||
start_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).start_time)
|
||||
end_time = int(self.env['planning.slot.template'].search([('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).end_time)
|
||||
@@ -220,20 +241,25 @@ class YuthonRunPlanning(models.Model):
|
||||
}
|
||||
# 综合班
|
||||
def integrated_confirm(self):
|
||||
selected_month = self.start_date.month
|
||||
year = datetime.now().year
|
||||
first_day_of_month = datetime(year, selected_month, 1)
|
||||
# 计算结束日期(下个月的第一天)
|
||||
next_month = (selected_month % 12) + 1
|
||||
next_year = year + (1 if next_month == 1 else 0) # 如果是12月,年份加1
|
||||
last_day_of_month = datetime(next_year, next_month, 1)- timedelta(days=1)
|
||||
existing_slots = self.env['planning.slot'].search([
|
||||
latest_slot = self.env['planning.slot'].search([
|
||||
('department_id.name', '=', '综合班'),
|
||||
('start_datetime', '>=', first_day_of_month),
|
||||
('start_datetime', '<=', last_day_of_month),
|
||||
])
|
||||
if len(existing_slots) > 0:
|
||||
raise UserError(f"该月已经有排程,请选择其他时间。")
|
||||
], order='start_datetime desc', limit=1)
|
||||
# 从最新排班中提取年/月
|
||||
latest_datetime = latest_slot.start_datetime
|
||||
latest_year = latest_datetime.year
|
||||
latest_month = latest_datetime.month
|
||||
|
||||
# 计算下个月的年/月
|
||||
target_month = latest_month + 1
|
||||
target_year = latest_year
|
||||
if target_month > 12:
|
||||
target_month = 1
|
||||
target_year += 1
|
||||
first_day_of_month = datetime(target_year, target_month, 1)
|
||||
# 计算结束日期(当月的最后一天)
|
||||
next_month = target_month % 12 + 1
|
||||
next_year = target_year + (1 if next_month == 1 else 0)
|
||||
last_day_of_month = datetime(next_year, next_month, 1) - timedelta(days=1)
|
||||
role_a = self.env['planning.role'].search([('name', '=', '工程部')], limit=1)
|
||||
start_time = int(self.env['planning.slot.template'].search(
|
||||
[('role_id', '=', role_a.id), ('planning_name', '=', '白班')]).start_time)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<form string="排版规则" create="0">
|
||||
<sheet>
|
||||
<header>
|
||||
<button name="run_confirm" type="object" string="排班" class="oe_highlight"/>
|
||||
<button name="run_confirm" type="object" string="排班" class="oe_highlight" invisible="not is_effect"/>
|
||||
<button name="action_planning_wizard_run" type="object" string="删除排班" class="oe_highlight"/>
|
||||
</header>
|
||||
<group>
|
||||
@@ -73,7 +73,7 @@
|
||||
<form string="排版规则">
|
||||
<sheet>
|
||||
<header>
|
||||
<button name="integrated_confirm" type="object" string='排班' class="oe_highlight"/>
|
||||
<button name="integrated_confirm" type="object" string='排班' class="oe_highlight" invisible="not is_effect"/>
|
||||
<button name="action_planning_wizard_integrated" type="object" string="删除排班" class="oe_highlight"/>
|
||||
</header>
|
||||
<group>
|
||||
@@ -115,7 +115,7 @@
|
||||
<form string="排版规则">
|
||||
<sheet>
|
||||
<header>
|
||||
<button name="high_confirm" type="object" string="排班" class="oe_highlight"/>
|
||||
<button name="high_confirm" type="object" string="排班" class="oe_highlight" invisible="not is_effect"/>
|
||||
<button name="action_planning_wizard_high" type="object" string="删除排班" class="oe_highlight"/>
|
||||
</header>
|
||||
<group>
|
||||
|
||||
@@ -185,6 +185,20 @@ class PropertyBankStatements(models.Model):
|
||||
lessee_ids = fields.Many2many('property.tenant.information', string='承租方', compute="_compute_property_employee_id", store=True)
|
||||
admin_id = fields.Many2one('res.users', string="片区管理员", compute="_compute_property_employee_id", store=True)
|
||||
|
||||
def write_off_details(self):
|
||||
self.ensure_one()
|
||||
modify_lines = self.env['receivable.modify.line'].search([
|
||||
('bank_id', '=', self.id)
|
||||
])
|
||||
receivable_ids = modify_lines.mapped('receivable_id').filtered(lambda r: r.id)
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'property.accounts.receivable',
|
||||
'view_mode': 'tree',
|
||||
'view_id': self.env.ref('yuthon_property.view_property_accounts_receivable_tree').id,
|
||||
'domain': [('id', 'in', receivable_ids.ids)],
|
||||
}
|
||||
|
||||
@api.depends('name')
|
||||
def _compute_property_employee_id(self):
|
||||
for record in self:
|
||||
|
||||
@@ -668,6 +668,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='bank_state']" position="after">
|
||||
<button name="revocation" type="object" class="btn btn-primary" string="撤销" invisible="bank_state == 'not_reconciled'"/>
|
||||
<button name="write_off_details" type="object" class="btn btn-primary" string="核销详情" invisible="bank_state == 'not_reconciled'"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user