pengyuthon wechat

This commit is contained in:
李鹏宇
2024-12-21 10:20:22 +08:00
parent 42a487cc0a
commit 4679db2d18
6 changed files with 475 additions and 500 deletions
@@ -10,77 +10,75 @@ import { useService } from "@web/core/utils/hooks";
import { session } from "@web/session";
export class CalculaterSh extends Component {
static template = "CalculatorTemplate";
static template = "CalculatorTemplate";
setup() {
this.orm = useService("orm");
this.search_sh_enable_calculator_mode()
setup() {
this.orm = useService("orm");
this.search_sh_enable_calculator_mode()
}
search_sh_enable_calculator_mode() {
this.sh_enable_calculator_mode = session.sh_enable_calculator_mode
}
onClickCalculator() {
if($('.calculator').length > 0){
$(".sh_calc_results").html("");
}else{
// render template
var qweb_data = `
<script type="text/javascript" src="/sh_backmate_theme_adv_enterprise/static/src/js/calculate.js"></script>
<div class="calculator" align="center">
<div class="row displayBox">
<p class="displayText" id="display">0</p>
</div>
<div class="row numberPad">
<div class="col-md-12">
<div class="row">
<button class="btn clear hvr-back-pulse" id="clear">C</button>
<button class="btn btn-calc hvr-radial-out" id="sqrt">√</button>
<button class="btn btn-calc hvr-radial-out" id="square">x<sup>2</sup></button>
<button id="divide" class="btn btn-operation hvr-fade">÷</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="seven">7</button>
<button class="btn btn-calc hvr-radial-out" id="eight">8</button>
<button class="btn btn-calc hvr-radial-out" id="nine">9</button>
<button id="multiply" class="btn btn-operation hvr-fade">×</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="four">4</button>
<button class="btn btn-calc hvr-radial-out" id="five">5</button>
<button class="btn btn-calc hvr-radial-out" id="six">6</button>
<button id="subtract" class="btn btn-operation hvr-fade">−</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="one">1</button>
<button class="btn btn-calc hvr-radial-out" id="two">2</button>
<button class="btn btn-calc hvr-radial-out" id="three">3</button>
<button id="add" class="btn btn-operation hvr-fade">+</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="plus_minus">&#177;</button>
<button class="btn btn-calc hvr-radial-out" id="zero">0</button>
<button class="btn btn-calc hvr-radial-out" id="decimal">.</button>
<button id="equals" class="btn btn-operation equals hvr-back-pulse">=</button>
</div>
</div>
</div>
</div>`
$(".sh_calc_results").html(qweb_data);
}
search_sh_enable_calculator_mode() {
this.sh_enable_calculator_mode = session.sh_enable_calculator_mode
if($('.sh_calc_util').hasClass('active')){
$('.sh_calc_util').removeClass('active')
}else{
$('.sh_calc_util').addClass('active')
}
// close other popup
$('.sh_user_language_list_cls').css("display","none")
$('.sh_wqm_quick_menu_submenu_list_cls').css("display","none")
$('.todo_layout').removeClass("sh_theme_model");
}
onClickCalculator() {
if($('.calculator').length > 0){
$(".sh_calc_results").html("");
}else{
// render template
var qweb_data = '<script type="text/javascript" src="/sh_backmate_theme_adv_enterprise/static/src/js/calculate.js"></script>
<div class="calculator" align="center">
<div class="row displayBox">
<p class="displayText" id="display">0</p>
</div>
<div class="row numberPad">
<div class="col-md-12">
<div class="row">
<button class="btn clear hvr-back-pulse" id="clear">C</button>
<button class="btn btn-calc hvr-radial-out" id="sqrt">√</button>
<button class="btn btn-calc hvr-radial-out hvr-radial-out" id="square">x<sup>2</sup></button>
<button id="divide" class="btn btn-operation hvr-fade">÷</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="seven">7</button>
<button class="btn btn-calc hvr-radial-out" id="eight">8</button>
<button class="btn btn-calc hvr-radial-out" id="nine">9</button>
<button id="multiply" class="btn btn-operation hvr-fade">×</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="four">4</button>
<button class="btn btn-calc hvr-radial-out" id="five">5</button>
<button class="btn btn-calc hvr-radial-out" id="six">6</button>
<button id="subtract" class="btn btn-operation hvr-fade">−</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="one">1</button>
<button class="btn btn-calc hvr-radial-out" id="two">2</button>
<button class="btn btn-calc hvr-radial-out" id="three">3</button>
<button id="add" class="btn btn-operation hvr-fade">+</button>
</div>
<div class="row">
<button class="btn btn-calc hvr-radial-out" id="plus_minus">&#177;</button>
<button class="btn btn-calc hvr-radial-out" id="zero">0</button>
<button class="btn btn-calc hvr-radial-out" id="decimal">.</button>
<button id="equals" class="btn btn-operation equals hvr-back-pulse">=</button>
</div>
</div>
</div>
</div>'
$(".sh_calc_results").html(qweb_data);
}
if($('.sh_calc_util').hasClass('active')){
$('.sh_calc_util').removeClass('active')
}else{
$('.sh_calc_util').addClass('active')
}
// close other popup
$('.sh_user_language_list_cls').css("display","none")
$('.sh_wqm_quick_menu_submenu_list_cls').css("display","none")
$('.todo_layout').removeClass("sh_theme_model");
}
}
registry.category("systray").add("sh_entmate_theme.calculater_sh", { Component: CalculaterSh }, { sequence: 25 });
@@ -374,62 +374,76 @@ patch(NavBar.prototype, {
getXmlID(app_id) {
return this.menuService.getMenuAsTree(app_id).xmlid;
},
OnClickDropdown(ev){
/*close pop-ups*/
$('.backmate_theme_layout').removeClass("sh_theme_model");
$('.todo_layout').removeClass("sh_theme_model");
$('.todo').removeClass('todo_active');
$('.sh_calc_util').removeClass("active")
$(".sh_calc_results").html("");
$('.sh_wqm_quick_menu_submenu_list_cls').css("display","none")
$('.o_user_bookmark_menu').removeClass('bookmark_active')
$('.sh_search_results').css("display", "none");
if (!$(ev.currentTarget).next().hasClass('show_ul')) {
$(ev.currentTarget).next('.dropdown-menu-right').first().slideDown('slow');
/**
* 处理点击下拉菜单事件
*
* @param {Event} ev - 触发事件的对象
*/
OnClickDropdown(ev) {
// 1. 关闭弹出窗口
$('.backmate_theme_layout').removeClass("sh_theme_model");
$('.todo_layout').removeClass("sh_theme_model");
$('.todo').removeClass('todo_active');
$('.sh_calc_util').removeClass("active");
$(".sh_calc_results").html(""); // 清空计算结果
$('.sh_wqm_quick_menu_submenu_list_cls').css("display", "none");
$('.o_user_bookmark_menu').removeClass('bookmark_active');
$('.sh_search_results').css("display", "none");
// 2. 切换子菜单显示状态
// 检查当前菜单项的下一个兄弟元素是否有 'show_ul' 类
if (!$(ev.currentTarget).next().hasClass('show_ul')) {
// 如果没有展开子菜单,则展开当前菜单
$(ev.currentTarget).next('.dropdown-menu-right').first().slideDown('slow');
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').slideUp(600)
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').css("display", "none !important")
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').removeClass('show_ul');
// 隐藏其他已经展开的子菜单
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').slideUp(600); // 收起其他子菜单
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').css("display", "none !important"); // 强制隐藏
$(ev.currentTarget).parents('.dropdown-menu').first().find('.show_ul').removeClass('show_ul'); // 移除 'show_ul' 类
// 3. 根据当前父元素的不同,调整子菜单的样式
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length === 1) {
// 如果当前菜单的父元素是 '.dropdown-header',则给它添加样式
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').addClass('sh_sub_dropdown');
} else if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length > 1) {
// 如果当前菜单的父元素是 '.dropdown-header',则给它添加样式
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').addClass('sh_sub_dropdown');
} else {
// 否则,调整其他菜单项的样式
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_dropdown').removeClass('sh_dropdown');
$(ev.currentTarget).parents('.dropdown-menu').first().find('.active').removeClass('active');
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('sh_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('active');
}
}
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length == 1) {
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').addClass('sh_sub_dropdown');
// 4. 如果子菜单已经展开,则隐藏它
if ($(ev.currentTarget).next().hasClass('show_ul')) {
// 如果当前子菜单已经展开,则收起它
$(ev.currentTarget).next('.dropdown-menu-right').first().slideUp(600);
// 移除展开时的样式
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length === 1) {
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').removeClass('sh_sub_dropdown');
} else if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length > 1) {
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').first().children('.dropdown-item').removeClass('sh_sub_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').last().removeClass('sh_sub_dropdown');
} else {
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('sh_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('active');
}
}
} else {
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_dropdown').removeClass('sh_dropdown');
$(ev.currentTarget).parents('.dropdown-menu').first().find('.active').removeClass('active');
$(ev.currentTarget).parents('.dropdown-menu').first().find('.sh_sub_dropdown').removeClass('sh_sub_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('sh_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('.dropdown-item').addClass('active');
}
}
if ($(ev.currentTarget).next().hasClass('show_ul')) {
$(ev.currentTarget).next('.dropdown-menu-right').first().slideUp(600);
if ($(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').length == 1) {
$(ev.currentTarget).next('.dropdown-menu').parents('.dropdown-header').children('.dropdown-item').removeClass('sh_sub_dropdown');
} else {
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('sh_dropdown');
$(ev.currentTarget).next('.dropdown-menu').parents('.sh_dropdown_div').children('span').removeClass('active');
}
}
var $subMenu = $(ev.currentTarget).next('.dropdown-menu');
$subMenu.toggleClass('show_ul');
// 5. 切换当前子菜单的状态
var $subMenu = $(ev.currentTarget).next('.dropdown-menu');
$subMenu.toggleClass('show_ul'); // 切换子菜单的显示状态
},
currentMenuAppSections(app_id) {
return (
(this.menuService.getMenuAsTree(app_id).childrenTree) ||
[]
);
currentMenuAppSections(app_id) {
return ((this.menuService.getMenuAsTree(app_id).childrenTree) || []);
},
getThemeStyle(ev) {
@@ -560,6 +560,7 @@
width: 260px !important;
}
}
.o-dropdown--menu.dropdown-menu.d-block {
width: 70px !important;
min-width: 70px !important;
@@ -1,234 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="ChildLink" owl="1">
<t t-if="!sub2_sections.length">
<t t-set="depth" t-value="1" />
<DropdownItem
href="getMenuItemHref(sub_section)"
dataset="{ menuXmlid: sub_section.xmlid, section: sub_section.id }"
onSelected="() => this.onNavBarDropdownItemSelection(sub_section)"
>
<span>
<t t-esc="sub_section.name"/>
</span>
</DropdownItem>
</t>
<t t-else="">
<a class="sh_dropdown_toggle dropdown-item dropdown-toggle" t-on-click.stop="OnClickDropdown">
<span class="fa fa-circle-thin"></span>
<span>
<t t-esc="sub_section.name" />
<t t-name="AppIcon" owl="1">
<t t-set="app_id" t-value="app.id" />
<a t-att-href="getMenuItemHref(app)" >
<t t-if="icon_style == 'standard'">
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&amp;field=web_icon_data&amp;id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
</t>
<t t-elif="icon_style == 'line_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"/>
</t>
<t t-elif="icon_style == 'three_d'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<img class="img threed_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/3d_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
</t>
<t t-elif="icon_style == 'dual_tone'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}}-dt sh_fa_icon">
<span class="path1"/>
<span class="path2"/>
</span>
</a>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<t t-foreach="sub2_sections" t-as="sub2_section" t-key="sub2_section.id">
<t t-set="sub2_sections" t-value="currentMenuAppSections(sub2_section.id)" />
<t t-if="sub2_section.length">
<t t-call="ChildLink">
<t t-set="sub2_sections" t-value="sub2_sections" /></t>
</t>
<t t-else="">
<div t-attf-class="dropdown-header">
<DropdownItem
href="getMenuItemHref(sub2_section)"
dataset="{ menuXmlid: sub2_section.xmlid, section: sub2_section.id }"
onSelected="() => this.onNavBarDropdownItemSelection(sub2_section)"
>
<span class="fa fa-circle-thin"></span>
<span>
<t t-esc="sub2_section.name"/>
</span>
</DropdownItem>
</div>
</t>
</t>
</ul>
</t>
</t>
<t t-elif="icon_style == 'glass_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<img class="img glass_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/glass_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
</t>
<t t-elif="icon_style == 'light_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}}-l sh_fa_icon"/>
</t>
<span>
<t t-esc="app.name"/>
</span>
</a>
</t>
<!-- 菜单递归模板 -->
<t t-name="AppsTreeMenu" owl="1">
<!-- 子菜单 -->
<t t-set="children_menus" t-value="menu.childrenTree" />
<!-- 不存在子菜单 -->
<t t-if="!children_menus.length">
<div class="dropdown-header dropdown-item o_menu_header_lvl_1">
<DropdownItem
href="getMenuItemHref(menu)"
dataset="{ menu: menu.xmlid, section: menu.id }"
onSelected="() => this.onNavBarDropdownItemSelection(menu)"
>
<span class="fa fa-circle-thin"/>
<span>
<t t-esc="menu.name"/>
</span>
</DropdownItem>
</div>
</t>
<!-- 存在子菜单 -->
<t t-else="">
<div class="dropdown-header o_menu_header_lvl_2" >
<a class="sh_dropdown_toggle dropdown-item dropdown-toggle" t-on-click.stop="OnClickDropdown">
<span class="fa fa-circle-thin"/>
<span>
<t t-esc="menu.name" />
</span>
</a>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<t t-foreach="children_menus" t-as="children" t-key="children.id">
<t t-set="children_sub_menus" t-value="children.childrenTree" />
<t t-if="children_sub_menus.length">
<t t-call="AppsTreeMenu">
<t t-set="menu" t-value="children" />
</t>
</t>
<t t-else="">
<div class="dropdown-header dropdown-item o_menu_header_lvl_1">
<DropdownItem
href="getMenuItemHref(children)"
dataset="{ menu: children.xmlid, section: children.id }"
onSelected="() => this.onNavBarDropdownItemSelection(children)"
>
<span class="fa fa-circle-thin"/>
<span>
<t t-esc="children.name"/>
</span>
</DropdownItem>
</div>
</t>
</t>
</ul>
</div>
</t>
</t>
<t t-name="sh.NavBar.AppsMenu" owl="1">
<a style="z-index:1111;display:none;" id="js_bar_toggle_btn_mobile" t-on-click="_click_js_bar_toggle_btn_mobile" class="">
<i class="fa fa-bars" id="toggle_bar" t-on-click="_click_toggle_bar" />
</a>
<div class="blur_div blur_toggle" t-on-click="_click_blur_div"></div>
<a style="z-index:1111;display:none;" id="js_bar_toggle_btn_mobile" t-on-click="_click_js_bar_toggle_btn_mobile" class="">
<i class="fa fa-bars" id="toggle_bar" t-on-click="_click_toggle_bar" />
</a>
<div class="blur_div blur_toggle" t-on-click="_click_blur_div"/>
<div t-on-mouseenter="onMouseenter_sh_backmate_theme_appmenu_div" t-on-mouseleave="onMouseleave_sh_backmate_theme_appmenu_div">
<Dropdown hotkey="'h'" title="'Home Menu'" class="'o_navbar_apps_menu sh_backmate_theme_appmenu_div'" t-on-mouseenter="onMouseenter_sh_backmate_theme_appmenu_div"
t-on-mouseleave="onMouseleave_sh_backmate_theme_appmenu_div">
<t t-set-slot="toggler">
</t>
<Dropdown
hotkey="'h'"
title="'Home Menu'"
class="'o_navbar_apps_menu sh_backmate_theme_appmenu_div'"
t-on-mouseenter="onMouseenter_sh_backmate_theme_appmenu_div"
t-on-mouseleave="onMouseleave_sh_backmate_theme_appmenu_div"
>
<t t-set-slot="toggler"/>
<!-- LOGO -->
<div class="logo" style="width: 100%;display: flex;max-width: 100%;align-items: center;margin-top: 20px;">
<img t-attf-src="/web/image?model=res.company&amp;field=company_name_logo&amp;id={{get_current_company()}}"
id="company_logo" style="margin-left: 10px;height: 30px;width: 30px;max-width: 30px;margin-right: 19px;" />
<img class="img" t-attf-src="/web/image?model=res.company&amp;field=logo&amp;id={{get_current_company()}}"
style="height: 3rem;padding: 10px 0;width: 55%;padding-left: 0;" id="company_name_logo" />
<img t-attf-src="/web/image?model=res.company&amp;field=company_name_logo&amp;id={{get_current_company()}}" id="company_logo" style="margin-left: 10px;height: 30px;width: 30px;max-width: 30px;margin-right: 19px;" />
<img class="img" t-attf-src="/web/image?model=res.company&amp;field=logo&amp;id={{get_current_company()}}" style="height: 3rem;padding: 10px 0;width: 55%;padding-left: 0;" id="company_name_logo" />
<span class="icon-top_hide fa fa-toggle-on" id="hide_top_bar" t-on-click="_click_hide_top_bar" style="margin-left: 25px;margin-top: 0px; font-size: 20px;"/>
<span class="icon-top_show fa fa-toggle-off" id="show_top_bar" t-on-click="_click_show_top_bar" style="margin-left: 25px;margin-top: 0px;font-size: 20px;"/>
</div>
<!-- 菜单项 -->
<t class="'o_app'" t-foreach="apps" t-as="app" t-key="app.id" t-on-click="_click_o_app">
<t t-set="app_icon" t-value="getXmlID(app.id)"/>
<t t-set="icon_style" t-value="getIconStyle()"/>
<t t-if="currentMenuAppSections(app.id).length" >
<t t-set="sections" t-value="currentMenuAppSections(app.id)" />
<div class="sh_dropdown_div cssmenu">
<span
t-key="app.id"
class="sh_dropdown_toggle dropdown-item child_app o_app2"
payload="app" t-on-click.stop="OnClickDropdown" t-on-mouseenter="onMouseenter_o_app2"
>
<t t-set="app_id" t-value="app.id" />
<a t-att-href="getMenuItemHref(app)" >
<t t-if="icon_style == 'standard'">
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&amp;field=web_icon_data&amp;id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
</t>
<t t-elif="icon_style == 'line_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"></span>
</t>
<t t-elif="icon_style == 'three_d'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<img class="img" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/3d_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
</t>
<t t-elif="icon_style == 'dual_tone'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}}-dt sh_fa_icon">
<span class="path1"></span>
<span class="path2"></span>
</span>
</t>
<t t-elif="icon_style == 'glass_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<img class="img" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/glass_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
</t>
<t t-elif="icon_style == 'light_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}}-l sh_fa_icon"></span>
</t>
<span>
<t t-esc="app.name"/>
</span>
</a>
</span>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<t t-foreach="sections" t-as="section" t-key="section.id">
<t t-set="sub_sections" t-value="currentMenuAppSections(section.id)" />
<t t-if="!sub_sections.length">
<t t-set="depth" t-value="1" />
<div class="dropdown-header dropdown-item o_menu_header_lvl_1">
<DropdownItem
href="getMenuItemHref(section)"
dataset="{ menuXmlid: section.xmlid, section: section.id }"
onSelected="() => this.onNavBarDropdownItemSelection(section)"
>
<span class="fa fa-circle-thin"></span>
<span>
<t t-esc="section.name"/>
</span>
</DropdownItem>
</div>
</t>
<t t-else="">
<div t-attf-class="dropdown-header o_menu_header_lvl_1">
<div class="sh_icon_text">
<span class="fa fa-circle-thin"></span>
<span>
<t t-esc="section.name" />
</span>
</div>
</div>
<t t-foreach="sub_sections" t-as="sub_section" t-key="sub_section.id">
<t t-set="sub2_sections" t-value="currentMenuAppSections(sub_section.id)" />
<div class="dropdown-header o_menu_header_lvl_2" >
<t t-if="sub2_sections.length">
<t t-call="ChildLink">
<t t-set="sub2_sections" t-value="sub2_sections"></t>
</t>
</t>
<t t-else="">
<DropdownItem
href="getMenuItemHref(sub_section)"
dataset="{ menuXmlid: sub_section.xmlid, section: sub_section.id }"
onSelected="() => this.onNavBarDropdownItemSelection(sub_section)"
>
<span class="fa fa-circle-thin"></span>
<span>
<t t-esc="sub_section.name"/>
</span>
</DropdownItem>
</t>
</div>
<t t-set="app_icon" t-value="getXmlID(app.id)"/>
<t t-set="icon_style" t-value="getIconStyle()"/>
<!-- 子菜单 -->
<t t-set="sections" t-value="currentMenuAppSections(app.id)"/>
<!-- 有子菜单 -->
<t t-if="sections.length" >
<div class="sh_dropdown_div cssmenu">
<!-- 菜单图标 -->
<span t-key="app.id"
class="sh_dropdown_toggle dropdown-item child_app o_app2"
payload="app"
t-on-click.stop="OnClickDropdown"
t-on-mouseenter="onMouseenter_o_app2"
>
<t t-call="AppIcon"/>
</span>
<!-- 子菜单项 -->
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<t t-foreach="sections" t-as="section" t-key="section.id">
<t t-call="AppsTreeMenu">
<t t-set="menu" t-value="section" />
</t>
</t>
</t>
</ul>
</div>
</t>
<t t-else="">
<div class="cssmenu">
<t t-set="app_id" t-value="app.id" />
</ul>
</div>
</t>
<t t-else="">
<!-- 没有子菜单,点击直接跳转 -->
<div class="cssmenu">
<span class="dropdown-item o_app direct_menu" t-on-click="_click_o_app" payload="app">
<a t-att-href="getMenuItemHref(app)">
<t t-if="icon_style == 'standard'">
<img class="img" t-attf-src="/web/image?model=ir.ui.menu&amp;field=web_icon_data&amp;id={{app_id}}" t-att-title="app.name" t-att-alt="app.name" />
</t>
<t t-elif="icon_style == 'line_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}} sh_fa_icon"></span>
</t>
<t t-elif="icon_style == 'three_d'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<img class="img threed_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/3d_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
</t>
<t t-elif="icon_style == 'dual_tone'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}}-dt sh_fa_icon">
<span class="path1"></span>
<span class="path2"></span>
</span>
</t>
<t t-elif="icon_style == 'glass_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<img class="img glass_icon" t-attf-src="sh_backmate_theme_adv_enterprise/static/src/app_icon/glass_icons/{{app_cls_name}}.png" t-att-title="app.name" t-att-alt="app.name"/>
</t>
<t t-elif="icon_style == 'light_icon'">
<t t-set="app_cls_name" t-value="getAppClassName(app)"/>
<span t-attf-class="sh-{{app_cls_name}}-l sh_fa_icon"></span>
</t>
<span>
<t t-esc="app.name"/>
</span>
</a>
<t t-call="AppIcon"/>
</span>
<!-- </MenuItem> -->
</div>
</div>
</t>
</t>
</t>
</Dropdown>
</div>
</t>
<t t-name="web.NavBar" t-inherit="web.NavBar" t-inherit-mode="extension" owl="1">
<xpath expr="//nav[hasclass('o_main_navbar')]" position="after">
@@ -259,21 +184,16 @@
<!-- Systray -->
<div class="o_menu_systray d-flex flex-shrink-0 ms-auto" role="menu">
<t t-foreach="systrayItems" t-as="item" t-key="item.key">
<div t-att-data-index="item.index"/>
<ErrorHandler onError="error => this.handleItemError(error, item)">
<t t-component="item.Component" t-props="item.props"/>
</ErrorHandler>
<div t-att-data-index="item.index"/>
<ErrorHandler onError="error => this.handleItemError(error, item)">
<t t-component="item.Component" t-props="item.props"/>
</ErrorHandler>
</t>
</div>
</nav>
</xpath>
</t>
<t t-name="Menu.link">
<t t-set="depth" t-value="(depth || 0) + 1"/>
<t t-if="!menu.childrenTree.length">
@@ -304,7 +224,8 @@
</span>
</div>
<t t-foreach="menu.childrenTree" t-as="menu" t-key="menu.id">
<t t-call="Menu.link"/></t>
<t t-call="Menu.link"/>
</t>
</t>
<li t-else="" class="sh_profile_menu_section">
<a href="#" t-attf-class="o_menu_entry_lvl_#{depth}" data-toggle="dropdown" role="button" aria-expanded="false" t-att-data-menu-xmlid="menu.xmlid" >
@@ -313,11 +234,11 @@
</a>
<ul>
<t t-foreach="menu.childrenTree" t-as="menu" t-key="menu.id">
<t t-call="Menu.link"/></t>
<t t-call="Menu.link"/>
</t>
</ul>
</li>
</t>
</t>
</templates>
@@ -6,9 +6,5 @@
</xpath>
</template>
</odoo>
+205 -160
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import os
import base64
import datetime
from datetime import datetime, timedelta, time
import logging
import traceback
from odoo import api, fields, models, tools, _
@@ -14,7 +14,8 @@ class HrAttendanceDetailImage(models.Model):
_name = "hr.attendance.detail.image"
_description = "打卡原始抓取数据图片"
attendance_detail_id = fields.Many2one('hr.attendance.detail', string="原始打卡记录", ondelete="cascade", readonly=True)
attendance_detail_id = fields.Many2one('hr.attendance.detail', string="原始打卡记录", ondelete="cascade",
readonly=True)
media_url = fields.Char(string='附件地址')
media_file = fields.Binary(string='附件文件', compute="_compute_media_file")
@@ -55,7 +56,8 @@ class HrAttendanceDetail(models.Model):
schedule_id = fields.Char(string='班次id')
timeline_id = fields.Integer(string='时段id')
attendance_detail_image_ids = fields.One2many(string="打卡记录图片", comodel_name='hr.attendance.detail.image', inverse_name='attendance_detail_id')
attendance_detail_image_ids = fields.One2many(string="打卡记录图片", comodel_name='hr.attendance.detail.image',
inverse_name='attendance_detail_id')
hr_attendance_id = fields.Many2one('hr.attendance', string="出勤记录", ondelete="cascade", readonly=True)
def action_show_details(self):
@@ -97,8 +99,8 @@ class HrAttendanceDetail(models.Model):
:return:
"""
# 先按照天抓取,时间戳
now_time = datetime.datetime.now() + datetime.timedelta(hours=8)
start_time = now_time - datetime.timedelta(days=30)
now_time = datetime.now() + timedelta(hours=8)
start_time = now_time - timedelta(days=30)
start_time_stamp = int(start_time.timestamp())
end_time_stamp = int(now_time.timestamp())
# 整理请求信息
@@ -127,7 +129,8 @@ class HrAttendanceDetail(models.Model):
return []
result = response.json()
if result.get('errcode') != 0:
_logger.error('获取外出打卡数据失败,异常:{0},用户列表{1}'.format(str(result.get('errmsg')), str(userid_limit)))
_logger.error(
'获取外出打卡数据失败,异常:{0},用户列表{1}'.format(str(result.get('errmsg')), str(userid_limit)))
return []
checkin_data = result.get('checkindata', [])
if not checkin_data:
@@ -148,8 +151,8 @@ class HrAttendanceDetail(models.Model):
if not userid or not checkin_time_stamp:
_logger.error('没有抓取到用户出勤信息,异常:{0},用户列表{1}'.format(str(data), str(userid_limit)))
return False
checkin_time = datetime.datetime.fromtimestamp(checkin_time_stamp) if checkin_time_stamp else None
sch_checkin_time = datetime.datetime.fromtimestamp(sch_checkin_time_stamp) if sch_checkin_time_stamp else None
checkin_time = datetime.fromtimestamp(checkin_time_stamp) if checkin_time_stamp else None
sch_checkin_time = datetime.fromtimestamp(sch_checkin_time_stamp) if sch_checkin_time_stamp else None
return checkin_time, sch_checkin_time
def _check_wx_attendance_media(self, data):
@@ -172,7 +175,8 @@ class HrAttendanceDetail(models.Model):
try:
result, response = self.sudo().env["wecom.apps"].sync_media_get(data)
if result:
filename = response.headers['Content-Disposition'].split('; ')[2].replace('filename=', '').replace('"', '')
filename = response.headers['Content-Disposition'].split('; ')[2].replace('filename=', '').replace(
'"', '')
wx_work_auth = self.env['auth.oauth.provider'].search([('name', '=', 'Wechat Card')], limit=1)
wx_work_image = os.path.join(wx_work_auth.wx_work_image_path, str(filename))
with open(wx_work_image, 'wb') as f:
@@ -181,9 +185,11 @@ class HrAttendanceDetail(models.Model):
'media_url': filename,
}))
else:
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1}'.format(str(response), str(data)))
_logger.error(
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1}'.format(str(response), str(data)))
except Exception as e:
_logger.error('请求原始图片失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
_logger.error('请求原始图片失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data),
str(traceback.format_exc())))
return media_list
@@ -198,7 +204,8 @@ class HrAttendanceDetail(models.Model):
"""
userid = data.get("userid", "")
# 查询是否存在数据
if userid and checkin_time and self.env['hr.attendance.detail'].sudo().search_count([("userid", "=", userid), ("checkin_time", "=", checkin_time)]) <= 0:
if userid and checkin_time and self.env['hr.attendance.detail'].sudo().search_count(
[("userid", "=", userid), ("checkin_time", "=", checkin_time)]) <= 0:
res_user_obj = self.env['res.users'].sudo().search([("oauth_uid", "=", userid)], limit=1)
hr_employee_obj = self.env['hr.employee'].sudo().search([("user_id", "=", res_user_obj.id)], limit=1)
if not res_user_obj or not hr_employee_obj:
@@ -232,15 +239,18 @@ class HrAttendanceDetail(models.Model):
media_list = self._check_wx_attendance_media(data)
attendance_detail_obj.attendance_detail_image_ids = media_list
except Exception as e:
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
_logger.error(
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data),
str(traceback.format_exc())))
userid = data.get("userid", "")
# 区分当天的上班,下班,中午打卡,合并一个
checkin_time_now = checkin_time + datetime.timedelta(hours=8) if checkin_time else None
sch_checkin_time_now = sch_checkin_time + datetime.timedelta(hours=8) if sch_checkin_time else None
current_data = (sch_checkin_time + datetime.timedelta(hours=8)).strftime("%Y-%m-%d") if sch_checkin_time_now else checkin_time_now.strftime("%Y-%m-%d")
checkin_time_now = checkin_time + timedelta(hours=8) if checkin_time else None
sch_checkin_time_now = sch_checkin_time + timedelta(hours=8) if sch_checkin_time else None
current_data = (sch_checkin_time + timedelta(hours=8)).strftime("%Y-%m-%d") if sch_checkin_time_now else checkin_time_now.strftime("%Y-%m-%d")
# 同步整理当天出勤数据
attendance_obj = self.env['hr.attendance'].search([("userid", "=", userid), ("current_data", "=", current_data)], limit=1)
attendance_obj = self.env['hr.attendance'].search(
[("userid", "=", userid), ("current_data", "=", current_data)], limit=1)
attendance_obj.attendance_type = "wx_work"
checkin_type = data.get("checkin_type", "")
exception_type = data.get("exception_type", "")
@@ -255,10 +265,8 @@ class HrAttendanceDetail(models.Model):
"attendance_type": "wx_work"
})
else:
current_datetime_start = datetime.datetime.combine(
datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.min)
current_datetime_end = datetime.datetime.combine(
datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.max)
current_datetime_start = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.min.time())
current_datetime_end = datetime.combine(datetime.strptime(current_data, '%Y-%m-%d'), datetime.max.time())
planning_slot_id = self.env['planning.slot'].search(
[('resource_id', '=', hr_employee_obj.resource_id.id),
('start_datetime', '>=', current_datetime_start),
@@ -272,7 +280,7 @@ class HrAttendanceDetail(models.Model):
"attendance_type": "wx_work"
})
if not hr_employee_obj.default_planning_role_id:
# 获取考勤日历的上班下班时间
# 获取考勤日历的上班下班时间
min_hour_from = self.env['resource.calendar'].search([])[0].attendance_ids[0].hour_from
min_hour = int(min_hour_from)
min_minute = int(min_hour_from * 10 % min_hour_from)
@@ -327,60 +335,67 @@ class HrAttendanceDetail(models.Model):
else:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
else:
current_datetime_start = datetime.datetime.combine(datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.min)
current_datetime_end = datetime.datetime.combine(datetime.datetime.strptime(current_data, '%Y-%m-%d'), datetime.time.max)
current_data = datetime.strptime(current_data, '%Y-%m-%d')
# 获取当天的起始和结束时间
current_datetime_start = datetime.combine(current_data, datetime.min.time())
current_datetime_end = datetime.combine(current_data, datetime.max.time())
# 获取本人当天的班次
planning_id = self.env['planning.slot'].search([('resource_id', '=', hr_employee_obj.resource_id.id),
('start_datetime', '>=', current_datetime_start),
('start_datetime', '<=', current_datetime_end)])
if planning_id:
planning_start_time = planning_id.start_datetime
planning_end_time = planning_id.end_datetime
if planning_id.department_id.name == '保安部':
planning_start_time = planning_id.start_datetime + timedelta(hours=8)
planning_end_time = planning_id.end_datetime + timedelta(hours=8)
if planning_id.role_id.name == '保安部':
# {'白班': [['8:30', '9.30'], ['8:30', '9.30']]}white
# {'中班': [['8:30', '9.30'], ['8:30', '9.30']]}mid
# {'夜班': [['8:30', '9.30'], ['8:30', '9.30']]}night
# 白班上班区间
start_time = datetime.datetime.combine(current_data, datetime.time(6, 0))+ datetime.timedelta(hours=8)
end_time = datetime.datetime.combine(current_data, datetime.time(9, 0))+ datetime.timedelta(hours=8)
start_time = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
end_time = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
# 白班下班区间
start_time1 = datetime.datetime.combine(current_data, datetime.time(2, 0))+ datetime.timedelta(hours=8)
end_time1 = datetime.datetime.combine(current_data, datetime.time(4, 0))+ datetime.timedelta(hours=8)
start_time1 = datetime.combine(current_data, time(2, 0)) + timedelta(hours=8)
end_time1 = datetime.combine(current_data, time(4, 0)) + timedelta(hours=8)
# 中班上班区间
start_time2 = datetime.datetime.combine(current_data, datetime.time(14, 0))+ datetime.timedelta(hours=8)
end_time2 = datetime.datetime.combine(current_data, datetime.time(17, 0))+ datetime.timedelta(hours=8)
start_time2 = datetime.combine(current_data, time(14, 0)) + timedelta(hours=8)
end_time2 = datetime.combine(current_data, time(17, 0)) + timedelta(hours=8)
# 中班下班区间
start_time3 = datetime.datetime.combine(current_data, datetime.time(22, 0))+ datetime.timedelta(hours=8)
end_time3 = datetime.datetime.combine(current_data, datetime.time(1, 0))+ datetime.timedelta(hours=8)
start_time3 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
end_time3 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# 夜班上班区间
start_time4 = datetime.datetime.combine(current_data, datetime.time(22, 0))+ datetime.timedelta(hours=8)
end_time4 = datetime.datetime.combine(current_data, datetime.time(1, 0))+ datetime.timedelta(hours=8)
start_time4 = datetime.combine(current_data, time(22, 0)) + timedelta(hours=8)
end_time4 = datetime.combine(current_data, time(1, 0)) + timedelta(hours=8)
# 夜班下班区间
start_time5 = datetime.datetime.combine(current_data, datetime.time(6, 0))+ datetime.timedelta(hours=8)
end_time5 = datetime.datetime.combine(current_data, datetime.time(9, 0))+ datetime.timedelta(hours=8)
start_time5 = datetime.combine(current_data, time(6, 0)) + timedelta(hours=8)
end_time5 = datetime.combine(current_data, time(9, 0)) + timedelta(hours=8)
if checkin_time:
if start_time<= checkin_time <=end_time and not attendance_obj.check_in and planning_id.template_id.planning_name == '白班':
planning_name = planning_id.template_id.planning_name
if start_time <= checkin_time <= end_time and planning_name == '白班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time1<= checkin_time <=end_time1 and not attendance_obj.check_out and planning_id.template_id.planning_name == '白班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time> checkin_time,
})
elif start_time2 <= checkin_time <= end_time2 and not attendance_obj.check_in and planning_id.template_id.planning_name == '中班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time3 <= checkin_time <= end_time3 and not attendance_obj.check_out and planning_id.template_id.planning_name == '中班':
elif start_time1 <= checkin_time <= end_time1 and planning_name == '白班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time4 <= checkin_time <= end_time4 and not attendance_obj.check_in and planning_id.template_id.planning_name == '夜班':
elif start_time2 <= checkin_time <= end_time2 and planning_name == '中班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time5 <= checkin_time <= end_time5 and not attendance_obj.check_out and planning_id.template_id.planning_name == '夜班':
elif start_time3 <= checkin_time <= end_time3 and planning_name == '中班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time4 <= checkin_time <= end_time4 and planning_name == '夜班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time5 <= checkin_time <= end_time5 and planning_name == '夜班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
@@ -389,107 +404,129 @@ class HrAttendanceDetail(models.Model):
attendance_obj.sudo().write({"is_abnormal": True})
else:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
elif planning_id.role_id.name == '工程部':
# 白班和白值上班区间
start_time = datetime.datetime.combine(current_data, datetime.time(7, 0))+ datetime.timedelta(hours=8)
end_time = datetime.datetime.combine(current_data, datetime.time(10, 0))+ datetime.timedelta(hours=8)
# 白班和白值下班区间
start_time1 = datetime.datetime.combine(current_data, datetime.time(16, 0))+ datetime.timedelta(hours=8)
end_time1 = datetime.datetime.combine(current_data, datetime.time(19, 0))+ datetime.timedelta(hours=8)
# 白值值班打卡区间
start_time2 = datetime.datetime.combine(current_data, datetime.time(11,30))+ datetime.timedelta(hours=8)
end_time2 = datetime.datetime.combine(current_data, datetime.time(13, 30))+ datetime.timedelta(hours=8)
# 中夜上班区间 中夜下班区间跟白班上班区间一样
start_time3 = datetime.datetime.combine(current_data, datetime.time(13, 0))+ datetime.timedelta(hours=8)
end_time3 = datetime.datetime.combine(current_data, datetime.time(16, 0))+ datetime.timedelta(hours=8)
# 中夜值班打卡区间
start_time4 = datetime.datetime.combine(current_data, datetime.time(20, 0))+ datetime.timedelta(hours=8)
end_time4 = datetime.datetime.combine(current_data, datetime.time(23, 0))+ datetime.timedelta(hours=8)
if planning_id:
if checkin_time:
if start_time<= checkin_time <=end_time and not attendance_obj.check_in and (planning_id.template_id.planning_name in ['白班','白值']):
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif end_time1<= checkin_time <=start_time1 and not attendance_obj.check_out and (planning_id.template_id.planning_name in ['白班','白值']):
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time3<= checkin_time <=end_time3 and not attendance_obj.check_in and planning_id.template_id.planning_name == '中夜':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time<= checkin_time <=end_time and not attendance_obj.check_out and planning_id.template_id.planning_name == '中夜':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card":checkin_time > planning_start_time
})
elif planning_id.template_id.planning == '白值' and start_time2 <= checkin_time <= end_time2:
attendance_obj.sudo().write({
"sch_check_out_time": sch_checkin_time,
"noon_duty": checkin_time,
})
elif planning_id.template_id.planning == '中夜' and start_time4 <= checkin_time <= end_time4:
attendance_obj.sudo().write({
"sch_check_out_time": sch_checkin_time,
"night_duty": checkin_time,
})
# 异常情况处理,移到所有打卡逻辑之后
if (attendance_obj.is_early_card or attendance_obj.is_late_card or
(planning_id.template_id.planning == '白值' and not attendance_obj.noon_duty) or
(planning_id.template_id.planning == '中夜' and not attendance_obj.night_duty)):
attendance_obj.sudo().write({"is_abnormal": True})
else:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
elif planning_id.role_id.name == '联安粮储':
# 白班上班区间
start_time = datetime.datetime.combine(current_data, datetime.time(7, 0))+ datetime.timedelta(hours=8)
end_time = datetime.datetime.combine(current_data, datetime.time(10, 0))+ datetime.timedelta(hours=8)
# 白班下班区间
start_time1 = datetime.datetime.combine(current_data, datetime.time(15, 0))+ datetime.timedelta(hours=8)
end_time1 = datetime.datetime.combine(current_data, datetime.time(18, 0))+ datetime.timedelta(hours=8)
# 白值上班
start_time2 = datetime.datetime.combine(current_data, datetime.time(8,0 ))+ datetime.timedelta(hours=8)
end_time2 = datetime.datetime.combine(current_data, datetime.time(10, 0))+ datetime.timedelta(hours=8)
# 白值下班
start_time4 = datetime.datetime.combine(current_data, datetime.time(4, 0))+ datetime.timedelta(hours=8)
end_time4 = datetime.datetime.combine(current_data, datetime.time(7, 0))+ datetime.timedelta(hours=8)
# 白值打卡区间、
start_time3 = datetime.datetime.combine(current_data, datetime.time(11, 30))+ datetime.timedelta(hours=8)
end_time3 = datetime.datetime.combine(current_data, datetime.time(13, 30))+ datetime.timedelta(hours=8)
if planning_id:
if start_time<= checkin_time <=end_time and not attendance_obj.check_in and planning_id.template_id.planning_name == '白班':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time
})
elif start_time1<= checkin_time <=end_time1 and not attendance_obj.check_out and planning_id.template_id.planning_name == '白班':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time2<= checkin_time <=end_time2 and not attendance_obj.check_in and planning_id.template_id.planning_name == '白值':
attendance_obj.sudo().write({
"check_in": checkin_time,
"is_late_card": checkin_time > planning_start_time,
})
elif start_time4<= checkin_time <=end_time4 and not attendance_obj.check_out and planning_id.template_id.planning_name == '白值':
attendance_obj.sudo().write({
"check_out": checkin_time,
"is_early_card": planning_end_time > checkin_time,
})
elif start_time3<= checkin_time <=end_time3 and planning_id.template_id.planning_name == '白值':
attendance_obj.sudo().write({
"noon_duty": checkin_time,
})
if (attendance_obj.is_early_card or attendance_obj.is_late_card or
(planning_id.template_id.planning == '白值班' and not attendance_obj.noon_duty)):
attendance_obj.sudo().write({"is_abnormal": True})
else:
attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# elif planning_id.role_id.name == '工程部':
# # 白班和白值上班区间
# start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
# hours=8)
# end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
# hours=8)
# # 白班和白值下班区间
# start_time1 = datetime.combine(current_data,
# time(16, 0)) + timedelta(hours=8)
# end_time1 = datetime.combine(current_data, time(19, 0)) + timedelta(
# hours=8)
# # 白值值班打卡区间
# start_time2 = datetime.combine(current_data,
# time(11, 30)) + timedelta(hours=8)
# end_time2 = datetime.combine(current_data, time(13, 30)) + timedelta(
# hours=8)
# # 中夜上班区间 中夜下班区间跟白班上班区间一样
# start_time3 = datetime.combine(current_data,
# time(13, 0)) + timedelta(hours=8)
# end_time3 = datetime.combine(current_data, time(16, 0)) + timedelta(
# hours=8)
# # 中夜值班打卡区间
# start_time4 = datetime.combine(current_data,
# time(20, 0)) + timedelta(hours=8)
# end_time4 = datetime.combine(current_data, time(23, 0)) + timedelta(
# hours=8)
# if planning_id:
# if checkin_time:
# if start_time <= checkin_time <= end_time and not attendance_obj.check_in and (
# planning_name in ['白班', '白值']):
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif end_time1 <= checkin_time <= start_time1 and not attendance_obj.check_out and (
# planning_name in ['白班', '白值']):
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time3 <= checkin_time <= end_time3 and not attendance_obj.check_in and planning_name == '中夜':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time <= checkin_time <= end_time and not attendance_obj.check_out and planning_name == '中夜':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": checkin_time > planning_start_time
# })
# elif planning_id.template_id.planning == '白值' and start_time2 <= checkin_time <= end_time2:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "noon_duty": checkin_time,
# })
# elif planning_id.template_id.planning == '中夜' and start_time4 <= checkin_time <= end_time4:
# attendance_obj.sudo().write({
# "sch_check_out_time": sch_checkin_time,
# "night_duty": checkin_time,
# })
# # 异常情况处理,移到所有打卡逻辑之后
# if (attendance_obj.is_early_card or attendance_obj.is_late_card or
# (planning_id.template_id.planning == '白值' and not attendance_obj.noon_duty) or
# (planning_id.template_id.planning == '中夜' and not attendance_obj.night_duty)):
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# elif planning_id.role_id.name == '联安粮储':
# # 白班上班区间
# start_time = datetime.combine(current_data, time(7, 0)) + timedelta(
# hours=8)
# end_time = datetime.combine(current_data, time(10, 0)) + timedelta(
# hours=8)
# # 白班下班区间
# start_time1 = datetime.combine(current_data,
# time(15, 0)) + timedelta(hours=8)
# end_time1 = datetime.combine(current_data, time(18, 0)) + timedelta(
# hours=8)
# # 白值上班
# start_time2 = datetime.combine(current_data, time(8, 0)) + timedelta(
# hours=8)
# end_time2 = datetime.combine(current_data, time(10, 0)) + timedelta(
# hours=8)
# # 白值下班
# start_time4 = datetime.combine(current_data, time(4, 0)) + timedelta(
# hours=8)
# end_time4 = datetime.combine(current_data, time(7, 0)) + timedelta(
# hours=8)
# # 白值打卡区间、
# start_time3 = datetime.combine(current_data,
# time(11, 30)) + timedelta(hours=8)
# end_time3 = datetime.combine(current_data, time(13, 30)) + timedelta(
# hours=8)
# if planning_id:
# if start_time <= checkin_time <= end_time and not attendance_obj.check_in and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time
# })
# elif start_time1 <= checkin_time <= end_time1 and not attendance_obj.check_out and planning_name == '白班':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time2 <= checkin_time <= end_time2 and not attendance_obj.check_in and planning_name == '白值':
# attendance_obj.sudo().write({
# "check_in": checkin_time,
# "is_late_card": checkin_time > planning_start_time,
# })
# elif start_time4 <= checkin_time <= end_time4 and not attendance_obj.check_out and planning_name == '白值':
# attendance_obj.sudo().write({
# "check_out": checkin_time,
# "is_early_card": planning_end_time > checkin_time,
# })
# elif start_time3 <= checkin_time <= end_time3 and planning_name == '白值':
# attendance_obj.sudo().write({
# "noon_duty": checkin_time,
# })
# if (attendance_obj.is_early_card or attendance_obj.is_late_card or
# (planning_id.template_id.planning == '白值班' and not attendance_obj.noon_duty)):
# attendance_obj.sudo().write({"is_abnormal": True})
# else:
# attendance_obj.sudo().write({"is_no_card": True, "is_abnormal": True})
# 进行关联
attendance_detail_obj.hr_attendance_id = attendance_obj.id
return True
@@ -508,13 +545,17 @@ class HrAttendanceDetail(models.Model):
attendance_data = self._get_wx_attendance_data(userid_limit)
attendance_result, response = self.sudo().env["wecom.apps"].sync_checkin_data(attendance_data)
except Exception as e:
_logger.error('获取企业微信的打卡信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit), str(traceback.format_exc())))
_logger.error(
'获取企业微信的打卡信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit),
str(traceback.format_exc())))
continue
# 检查请求返回的信息是否正确
try:
checkin_data = self._check_wx_attendance_data(response, userid_limit)
except Exception as e:
_logger.error('检查请求返回的信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit), str(traceback.format_exc())))
_logger.error(
'检查请求返回的信息失败,异常:{0},用户列表{1},异常详情:{2}'.format(str(e), str(userid_limit),
str(traceback.format_exc())))
continue
# 将原始数据存储
for data in checkin_data:
@@ -522,13 +563,17 @@ class HrAttendanceDetail(models.Model):
try:
checkin_time, sch_checkin_time = self._check_wx_attendance_time(data, userid_limit)
except Exception as e:
_logger.error('检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
_logger.error(
'检查保存之前的数据分析出想要的数据失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e),
str(data),
str(traceback.format_exc())))
continue
# 保存相关的企业微信的原始打卡信息
try:
self._save_wx_attendance_detail_data(data, checkin_time, sch_checkin_time)
except Exception as e:
_logger.error('保存相关的企业微信的原始打卡信息失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e), str(data), str(traceback.format_exc())))
_logger.error(
'保存相关的企业微信的原始打卡信息失败,异常:{0},数据信息{1},异常详情:{2}'.format(str(e),
str(data),
str(traceback.format_exc())))
return True