diff --git a/yuthon_catering/__init__.py b/yuthon_catering/__init__.py index 9e5827f90..cec04a5b0 100644 --- a/yuthon_catering/__init__.py +++ b/yuthon_catering/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import controllers from . import models +from . import wizard diff --git a/yuthon_catering/__manifest__.py b/yuthon_catering/__manifest__.py index 7b4de9300..dced2d36e 100644 --- a/yuthon_catering/__manifest__.py +++ b/yuthon_catering/__manifest__.py @@ -13,12 +13,15 @@ 'views/root_menu.xml', 'views/yuthon_catering.xml', 'views/yuthon_catering_conf.xml', + 'views/yuthon_catering_setting_views.xml', + 'wizard/catering_reinstated_wizard_views.xml', 'templates/templates.xml', ], - # 'assets': { - # 'web.assets_backend': [ - # 'base_dynamic_columns/static/src/**/*', - # ], - # }, + 'assets': { + 'web.assets_backend': [ + 'yuthon_catering/static/src/js/catering_create_button.js', + 'yuthon_catering/static/src/xml/catering_create_button_views.xml', + ], + }, } diff --git a/yuthon_catering/data/catering_time.xml b/yuthon_catering/data/catering_time.xml new file mode 100644 index 000000000..69c1d6ecd --- /dev/null +++ b/yuthon_catering/data/catering_time.xml @@ -0,0 +1,18 @@ + + + + + 定时任务:餐饮收集任务 + + code + model.catering_task() + + + 1 + weeks + + -1 + + + + \ No newline at end of file diff --git a/yuthon_catering/models/__init__.py b/yuthon_catering/models/__init__.py index 5b6692f79..4bfbd4d62 100644 --- a/yuthon_catering/models/__init__.py +++ b/yuthon_catering/models/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import yuthon_catering from . import yuthon_catering_conf +from . import yuthon_catering_setting diff --git a/yuthon_catering/models/yuthon_catering.py b/yuthon_catering/models/yuthon_catering.py index 3da727d34..499a6259f 100644 --- a/yuthon_catering/models/yuthon_catering.py +++ b/yuthon_catering/models/yuthon_catering.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from odoo import api, fields, models +from datetime import datetime, timedelta class YuthonCatering(models.Model): @@ -9,9 +10,74 @@ class YuthonCatering(models.Model): employee_id = fields.Many2one(string='员工', comodel_name='hr.employee', required=True) breakfast = fields.Boolean(string='早餐', default=False) lunch = fields.Boolean(string='午餐', default=False) + menu_day_id = fields.Many2one('yuthon.menu.setting', string='菜单') amount = fields.Float(string='结算费用') note = fields.Text(string='备注') + def catering_task(self): + conf_records = self.env['yuthon.catering.conf'].search([]) + employee_ids = conf_records.mapped('employee_ids') + + today = fields.Date.today() + date_list = [today + timedelta(days=i) for i in range(7)] + + create_vals = [] + for employee in employee_ids: + for target_date in date_list: + if not self._process_shift_days(target_date): + continue + existing = self.search([ + ('employee_id', '=', employee.id), + ('date', '=', target_date) + ], limit=1) + + menu_record = self.env['yuthon.menu.setting'].search([ + ('menu_date', '=', target_date) + ], limit=1) + + if not existing: + create_vals.append({ + 'menu_record': menu_record.id if menu_record else False, + 'date': target_date, + 'employee_id': employee.id, + }) + + if create_vals: + self.create(create_vals) + + def _process_shift_days(self, current_data): + """ + 判断是否是工作日 调休日 双休 + """ + calendar_leaves = self.env['resource.calendar.leaves'].search([("calendar_id", "=", "行政考勤工作日")]) + holidays_list = [] + shift_days_list = [] + # 提取节假日和调休日 + for leave in calendar_leaves: + if leave.holidays: + holidays_list.extend(leave.holidays.split(',')) + if leave.alternate_rest_day: + holidays_list.extend(leave.alternate_rest_day.split(',')) + if leave.shift_replacement_day: + shift_days_list.extend(leave.shift_replacement_day.split(',')) + + holidays_list = [self.remove_leading_zero(date) for date in holidays_list] + shift_days_list = [self.remove_leading_zero(date) for date in shift_days_list] + result = f"{current_data.month}月{current_data.day}日" + if result in shift_days_list: + return True + elif (result in holidays_list) or (current_data.weekday() in [5, 6]): + return False + else: + return True + + def remove_leading_zero(self, date_str): + month, day = date_str.split('月') + month = month.lstrip('0') + day = day.rstrip('日') + day = day.lstrip('0') + return f'{month}月{day}日' + def cron_send_message(self): url = f'/catering/portal/' diff --git a/yuthon_catering/models/yuthon_catering_setting.py b/yuthon_catering/models/yuthon_catering_setting.py new file mode 100644 index 000000000..600d8fa90 --- /dev/null +++ b/yuthon_catering/models/yuthon_catering_setting.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models + +class YuthonMenuSetting(models.Model): + _name = 'yuthon.menu.setting' + _description = '菜单配置' + + breakfast_ids = fields.Many2many( + 'yuthon.dishes.setting', + 'yuthon_menu_breakfast_rel', + 'menu_id', + 'dish_id', + string='早餐' + ) + lunch_ids = fields.Many2many( + 'yuthon.dishes.setting', + 'yuthon_menu_lunch_rel', + 'menu_id', + 'dish_id', + string='午餐' + ) + menu_date = fields.Date(string='日期') + + +class YuthonDishesSetting(models.Model): + _name = 'yuthon.dishes.setting' + _description = '菜品配置' + + name = fields.Char(string='菜品名称') + dishes_type = fields.Selection([('breakfast', '早餐'), ('lunch', '午餐')], string='菜品类型') + diff --git a/yuthon_catering/security/ir.model.access.csv b/yuthon_catering/security/ir.model.access.csv index 70698e012..9f46bc0f4 100644 --- a/yuthon_catering/security/ir.model.access.csv +++ b/yuthon_catering/security/ir.model.access.csv @@ -1,6 +1,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_yuthon_catering,yuthon_catering,model_yuthon_catering,,1,1,1,1 access_yuthon_catering_conf,yuthon_catering_conf,model_yuthon_catering_conf,,1,1,1,1 - +access_yuthon_menu_setting,yuthon_menu_setting,model_yuthon_menu_setting,,1,1,1,1 +access_yuthon_dishes_setting,yuthon_dishes_setting,model_yuthon_dishes_setting,,1,1,1,1 diff --git a/yuthon_catering/static/description/catering.png b/yuthon_catering/static/description/catering.png new file mode 100644 index 000000000..df91e0b7a Binary files /dev/null and b/yuthon_catering/static/description/catering.png differ diff --git a/yuthon_catering/static/src/js/catering_create_button.js b/yuthon_catering/static/src/js/catering_create_button.js new file mode 100644 index 000000000..c686e24f8 --- /dev/null +++ b/yuthon_catering/static/src/js/catering_create_button.js @@ -0,0 +1,28 @@ +/** @odoo-module */ +import {ListController} from "@web/views/list/list_controller"; +import {registry} from '@web/core/registry'; +import {listView} from '@web/views/list/list_view'; + +export class CustomCateringController extends ListController { + setup() { + super.setup(); + } + + openCateringWizard() { + this.actionService.doAction({ + type: 'ir.actions.act_window', + res_model: 'catering.reinstated.wizard', + name: '复用弹窗', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', // 以弹窗形式打开 + context: {}, + }); + } +} +registry.category("views").add("custom_catering_button", { + ...listView, + Controller: CustomCateringController, + buttonTemplate: "catering_module.ListView.Buttons" +}); \ No newline at end of file diff --git a/yuthon_catering/static/src/xml/catering_create_button_views.xml b/yuthon_catering/static/src/xml/catering_create_button_views.xml new file mode 100644 index 000000000..1c25e6d6b --- /dev/null +++ b/yuthon_catering/static/src/xml/catering_create_button_views.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/yuthon_catering/views/root_menu.xml b/yuthon_catering/views/root_menu.xml index f8e1397ae..90058bb5d 100644 --- a/yuthon_catering/views/root_menu.xml +++ b/yuthon_catering/views/root_menu.xml @@ -1,7 +1,9 @@ - + diff --git a/yuthon_catering/views/yuthon_catering.xml b/yuthon_catering/views/yuthon_catering.xml index 81414145c..9a008e1ee 100644 --- a/yuthon_catering/views/yuthon_catering.xml +++ b/yuthon_catering/views/yuthon_catering.xml @@ -6,12 +6,13 @@ yuthon.catering.tree yuthon.catering - + + diff --git a/yuthon_catering/views/yuthon_catering_conf.xml b/yuthon_catering/views/yuthon_catering_conf.xml index 51718b2e2..57fdcbe36 100644 --- a/yuthon_catering/views/yuthon_catering_conf.xml +++ b/yuthon_catering/views/yuthon_catering_conf.xml @@ -8,7 +8,7 @@ - + diff --git a/yuthon_catering/views/yuthon_catering_setting_views.xml b/yuthon_catering/views/yuthon_catering_setting_views.xml new file mode 100644 index 000000000..913a424e6 --- /dev/null +++ b/yuthon_catering/views/yuthon_catering_setting_views.xml @@ -0,0 +1,48 @@ + + + + yuthon_menu_setting_tree + yuthon.menu.setting + + + + + + + + + + 菜单配置 + yuthon.menu.setting + tree + + + yuthon_dishes_setting_tree + yuthon.dishes.setting + + + + + + + + + 菜品配置 + yuthon.dishes.setting + tree + + + + + + diff --git a/yuthon_catering/wizard/__init__.py b/yuthon_catering/wizard/__init__.py new file mode 100644 index 000000000..26d2cb010 --- /dev/null +++ b/yuthon_catering/wizard/__init__.py @@ -0,0 +1 @@ +from . import catering_reinstated_wizard \ No newline at end of file diff --git a/yuthon_catering/wizard/catering_reinstated_wizard.py b/yuthon_catering/wizard/catering_reinstated_wizard.py new file mode 100644 index 000000000..e5a4efe18 --- /dev/null +++ b/yuthon_catering/wizard/catering_reinstated_wizard.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models +from datetime import datetime, timedelta, time + + +class CateringReinstatedWizard(models.TransientModel): + _name = 'catering.reinstated.wizard' + _description = '复用弹窗' + + def confirm(self): + today = fields.Date.today() + date_list = [] + for i in range(7): + target_date = today + timedelta(days=i) + if self._process_shift_days(target_date): + date_list.append(target_date) + + for current_date in date_list: + # 上周对应日期 + last_week_date = current_date - timedelta(days=7) + + # 查找上周该日期的所有餐饮记录 + last_week_records = self.env['yuthon.catering'].search([ + ('date', '=', last_week_date) + ]) + if not last_week_records: + continue + + for last_record in last_week_records: + existing = self.env['yuthon.catering'].search([ + ('employee_id', '=', last_record.employee_id.id), + ('date', '=', current_date) + ], limit=1) + if existing: + continue + + self.env['yuthon.catering'].create({ + 'date': current_date, + 'employee_id': last_record.employee_id.id, + 'breakfast': last_record.breakfast, + 'lunch': last_record.lunch, + 'menu_day_id': last_record.menu_day_id.id, + 'amount': last_record.amount, + 'note': last_record.note, + }) + + def _process_shift_days(self, current_data): + """ + 判断是否是工作日 调休日 双休 + """ + calendar_leaves = self.env['resource.calendar.leaves'].search([("calendar_id", "=", "行政考勤工作日")]) + holidays_list = [] + shift_days_list = [] + # 提取节假日和调休日 + for leave in calendar_leaves: + if leave.holidays: + holidays_list.extend(leave.holidays.split(',')) + if leave.alternate_rest_day: + holidays_list.extend(leave.alternate_rest_day.split(',')) + if leave.shift_replacement_day: + shift_days_list.extend(leave.shift_replacement_day.split(',')) + + holidays_list = [self.remove_leading_zero(date) for date in holidays_list] + shift_days_list = [self.remove_leading_zero(date) for date in shift_days_list] + result = f"{current_data.month}月{current_data.day}日" + if result in shift_days_list: + return True + elif (result in holidays_list) or (current_data.weekday() in [5, 6]): + return False + else: + return True + + def remove_leading_zero(self, date_str): + month, day = date_str.split('月') + month = month.lstrip('0') + day = day.rstrip('日') + day = day.lstrip('0') + return f'{month}月{day}日' \ No newline at end of file diff --git a/yuthon_catering/wizard/catering_reinstated_wizard_views.xml b/yuthon_catering/wizard/catering_reinstated_wizard_views.xml new file mode 100644 index 000000000..335a0ce58 --- /dev/null +++ b/yuthon_catering/wizard/catering_reinstated_wizard_views.xml @@ -0,0 +1,20 @@ + + + + catering.reinstated.wizard.form + catering.reinstated.wizard + +
+ +
+ 确定要执行复用逻辑吗? +
+
+ +
+
+
+
\ No newline at end of file