@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import controllers
|
||||
from . import models
|
||||
from . import wizard
|
||||
|
||||
@@ -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',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record forcecreate="True" id="yuthon_catering_time" model="ir.cron">
|
||||
<field name="name">定时任务:餐饮收集任务</field>
|
||||
<field name="model_id" ref="model_yuthon_catering"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.catering_task()</field>
|
||||
<field eval="True" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">weeks</field>
|
||||
<field name="nextcall" eval="(DateTime.now()).strftime('%Y-%m-%d 00:00:00')"/>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import yuthon_catering
|
||||
from . import yuthon_catering_conf
|
||||
from . import yuthon_catering_setting
|
||||
|
||||
@@ -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/<int:employee_id>'
|
||||
|
||||
|
||||
@@ -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='菜品类型')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@@ -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"
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<t t-name="catering_module.ListView.Buttons" t-inherit="web.ListView.Buttons">
|
||||
<xpath expr="//div[hasclass('o_list_buttons')]" position="after">
|
||||
<button type="button" class="btn btn-primary" style="margin-left: 10px;" t-on-click="openCateringWizard">
|
||||
复用
|
||||
</button>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<menuitem id="yuthon_catering_root_menu" name="餐饮" sequence="1">
|
||||
<menuitem id="yuthon_catering_root_menu" name="餐饮" sequence="1"
|
||||
web_icon="yuthon_catering,static/description/catering.png"
|
||||
>
|
||||
<menuitem id="yuthon_catering_conf_root_menu" name="配置" sequence="99"/>
|
||||
</menuitem>
|
||||
</data>
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
<field name="name">yuthon.catering.tree</field>
|
||||
<field name="model">yuthon.catering</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="餐饮" editable="top">
|
||||
<tree string="餐饮" editable="top" js_class="custom_catering_button">
|
||||
<field name="date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="breakfast"/>
|
||||
<field name="lunch"/>
|
||||
<field name="amount"/>
|
||||
<field name="menu_day_id"/>
|
||||
<field name="note"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<tree string="配置" editable="top">
|
||||
<field name="company_id"/>
|
||||
<field name="employee_ids"/>
|
||||
<field name="employee_ids" widget="many2many_tags" domain="[('company_id', '=', company_id)]"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="yuthon_menu_setting_tree" model="ir.ui.view">
|
||||
<field name="name">yuthon_menu_setting_tree</field>
|
||||
<field name="model">yuthon.menu.setting</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="菜单配置" editable="bottom">
|
||||
<field name="breakfast_ids" widget="many2many_tags" domain="[('dishes_type','=','breakfast')]"/>
|
||||
<field name="lunch_ids" widget="many2many_tags" domain="[('dishes_type','=','lunch')]"/>
|
||||
<field name="menu_date"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="yuthon_menu_setting_action" model="ir.actions.act_window">
|
||||
<field name="name">菜单配置</field>
|
||||
<field name="res_model">yuthon.menu.setting</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
<record id="yuthon_dishes_setting_tree" model="ir.ui.view">
|
||||
<field name="name">yuthon_dishes_setting_tree</field>
|
||||
<field name="model">yuthon.dishes.setting</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="菜品配置" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="dishes_type"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="yuthon_dishes_setting_action" model="ir.actions.act_window">
|
||||
<field name="name">菜品配置</field>
|
||||
<field name="res_model">yuthon.dishes.setting</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="yuthon_menu_setting_menu"
|
||||
name="菜单配置"
|
||||
parent="yuthon_catering_conf_root_menu"
|
||||
sequence="5"
|
||||
action="yuthon_menu_setting_action"/>
|
||||
|
||||
<menuitem
|
||||
id="yuthon_dishes_setting_menu"
|
||||
name="菜品配置"
|
||||
parent="yuthon_catering_conf_root_menu"
|
||||
sequence="10"
|
||||
action="yuthon_dishes_setting_action"/>
|
||||
</odoo>
|
||||
@@ -0,0 +1 @@
|
||||
from . import catering_reinstated_wizard
|
||||
@@ -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}日'
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="catering_reinstated_wizard_form" model="ir.ui.view">
|
||||
<field name="name">catering.reinstated.wizard.form</field>
|
||||
<field name="model">catering.reinstated.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="复用弹窗">
|
||||
<sheet>
|
||||
<div>
|
||||
确定要执行复用逻辑吗?
|
||||
</div>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="confirm" type="object" string="确定" class="btn-primary"/>
|
||||
<button special="cancel" string="取消"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user