Merge remote-tracking branch 'origin/madaowen' into madaowen
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
- 快捷筛选(quick_filter)
|
||||
- 自选时间筛选(select_date_filter)(待移植)
|
||||
- 字段搜索(field)(待移植)
|
||||
- 字段搜索(field)(已移植)
|
||||
|
||||
通过这些筛选标签,用户可以更灵活地对列表视图中的数据进行筛选。
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
#### 支持的属性:
|
||||
|
||||
| 属性名 | 类型 | 说明 | 是否可选 |
|
||||
| ------- | ------ | ---------- | ---- |
|
||||
| `class` | String | 自定义 CSS 类名 | ✅ |
|
||||
| 属性名 | 类型 | 说明 | 是否可选 |
|
||||
| ------- | ------ |-------------------------------------------------------------------| ---- |
|
||||
| `class` | String | 自定义 CSS 类名,<br/>可使用class="header-search-inline"使所有筛选在同一行并根据宽度自动换行 | ✅ |
|
||||
|
||||
#### 子标签支持:
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
| ----------- | ------- | ----------- | ------------ |
|
||||
| `class` | String | 自定义 CSS 类名 | ✅ |
|
||||
| `string` | String | 显示的标头名称 | ✅ |
|
||||
| `invisible` | Boolean | 是否默认隐藏 | ✅ |
|
||||
| `invisible` | Boolean | 是否默认隐藏(废弃) | ✅ |
|
||||
| `options` | JSON | 扩展参数,支持以下参数: | ✅ |
|
||||
| | | `radio`: 是否单选 | |
|
||||
| | | `no_label`: 不显示标题 | |
|
||||
@@ -77,16 +77,16 @@
|
||||
|
||||
---
|
||||
|
||||
### 3. 自选时间筛选 (select_date_filter)
|
||||
### 3. 自选时间筛选 (select_date_filter)(废弃)
|
||||
|
||||
**标签名:** `select_date_filter`
|
||||
|
||||
#### 支持的属性:
|
||||
|
||||
| 属性名 | 类型 | 说明 | 是否可选 |
|
||||
| ------------------- | ------- | -------------- | ---- |
|
||||
| ------------------- | ------- |----------------| ---- |
|
||||
| `class` | String | 自定义 CSS 类名 | ✅ |
|
||||
| `invisible` | Boolean | 是否默认隐藏 | ✅ |
|
||||
| `invisible` | Boolean | 是否默认隐藏(废弃) | ✅ |
|
||||
| `allow_date_fields` | String | 允许筛选的时间字段,逗号分隔 | ✅ |
|
||||
|
||||
#### 示例:
|
||||
@@ -109,6 +109,9 @@
|
||||
| `string` | String | 显示的标头名称 | ✅ |
|
||||
| `class` | String | 自定义 CSS | ✅ |
|
||||
| `invisible` | Boolean | 是否默认隐藏 | ✅ |
|
||||
| `options` | JSON | 扩展参数,支持以下参数: | ✅ |
|
||||
| | | `radio`: 是否单选 | |
|
||||
| | | `no_label`: 不显示标题 | |
|
||||
|
||||
#### 示例:
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/** @odoo-module **/
|
||||
//
|
||||
// import {patch} from "@web/core/utils/patch";
|
||||
// import * as backend_utils from "@web/legacy/backend_utils";
|
||||
//
|
||||
// const originalSearchModelStateToLegacy = backend_utils.searchModelStateToLegacy;
|
||||
// const originalGetGlobalState = backend_utils.getGlobalState;
|
||||
//
|
||||
// patch(backend_utils, "header_search_panel.backend_utils", {
|
||||
// searchModelStateToLegacy(state) {
|
||||
// // 原始state
|
||||
// const originalState = JSON.parse(state);
|
||||
// // 获取原始state
|
||||
// let legacyState = JSON.parse(originalSearchModelStateToLegacy(state));
|
||||
// if (originalState.headerSearchInfo) {
|
||||
// legacyState.HeaderSearchInfo = originalState.headerSearchInfo;
|
||||
// }
|
||||
// return JSON.stringify(legacyState)
|
||||
// },
|
||||
//
|
||||
// getGlobalState(legacyControllerState) {
|
||||
// // 原始search model
|
||||
// const originalSearchModel = JSON.parse(legacyControllerState.searchModel)
|
||||
// let globalState = originalGetGlobalState(legacyControllerState);
|
||||
// let searchModel = JSON.parse(globalState?.searchModel || "{}");
|
||||
// if (originalSearchModel.HeaderSearchInfo) {
|
||||
// searchModel.headerSearchInfo = originalSearchModel.HeaderSearchInfo;
|
||||
// globalState.searchModel = JSON.stringify(searchModel)
|
||||
// }
|
||||
// console.log('headerSearchInfo: getGlobalState')
|
||||
// return globalState
|
||||
// },
|
||||
// })
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
import { Domain } from "@web/core/domain";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
import { standardFieldFilterProps } from "../standard_field_filter_props.js"
|
||||
|
||||
|
||||
export class CharFilter extends Component {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.rpc = useService("rpc");
|
||||
this.activeValues = this.env.searchModel.headerSearchInfo.FieldsFilter[this.props.id]?.activeValues || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置筛选字段的值
|
||||
*/
|
||||
setActiveValues(ev) {
|
||||
this.activeValues = ev.target.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取筛选字段的domain
|
||||
*/
|
||||
get domain() {
|
||||
return this.activeValues ? [[this.props.name, "ilike", this.activeValues]]: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击清空筛选时触发
|
||||
*/
|
||||
resetFilter() {
|
||||
// 清空筛选字段的值
|
||||
this.activeValues = undefined;
|
||||
this.props.fieldOnchange({fieldDomainList: this.domain, activeValues: this.activeValues});
|
||||
}
|
||||
|
||||
getDomain() {
|
||||
return new Domain(this.props.domain).toList({});
|
||||
}
|
||||
|
||||
async onInputChange(ev) {
|
||||
this.setActiveValues(ev);
|
||||
this.props.fieldOnchange({fieldDomainList: this.domain, activeValues: this.activeValues});
|
||||
}
|
||||
}
|
||||
|
||||
CharFilter.template = "header_search_panel.CharFilter";
|
||||
CharFilter.components = {};
|
||||
CharFilter.props = {
|
||||
...standardFieldFilterProps,
|
||||
};
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="header_search_panel.CharFilter" owl="1">
|
||||
<div>
|
||||
<input class="o_input"
|
||||
t-att-id="props.id"
|
||||
type="text"
|
||||
t-ref="input"
|
||||
t-att-value="activeValues"
|
||||
t-on-input="onInputChange"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
+27
-10
@@ -1,8 +1,9 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import {Component} from "@odoo/owl";
|
||||
import {Domain} from "@web/core/domain";
|
||||
import {standardFieldFilterProps} from "../standard_field_filter_props.js"
|
||||
import { Component } from "@odoo/owl";
|
||||
import { DateTimeInput } from "@web/core/datetime/datetime_input";
|
||||
import { deserializeDate } from "@web/core/l10n/dates";
|
||||
import { standardFieldFilterProps } from "../standard_field_filter_props.js"
|
||||
|
||||
export class DateFilter extends Component {
|
||||
setup() {
|
||||
@@ -13,13 +14,21 @@ export class DateFilter extends Component {
|
||||
this.endDate = this.env.searchModel.headerSearchInfo.FieldsFilter[this.props.id]?.endDate;
|
||||
}
|
||||
|
||||
get dateFrom() {
|
||||
return this.startDate ? deserializeDate(this.startDate): undefined;
|
||||
}
|
||||
|
||||
get dateTo() {
|
||||
return this.endDate ? deserializeDate(this.endDate): undefined;
|
||||
}
|
||||
|
||||
// 设置筛选字段的值
|
||||
setActiveValues(ev) {
|
||||
const value = ev.target.value;
|
||||
if (ev.target.id === this.props.id + "_start_date") {
|
||||
setActiveValues(dateValue, type) {
|
||||
const value = dateValue ? (this.props.type === "datetime" ? dateValue.toFormat("yyyy-MM-dd HH:mm:ss") : dateValue.toFormat("yyyy-MM-dd")) : undefined;
|
||||
if (type === "startDate") {
|
||||
this.startDate = value
|
||||
}
|
||||
if (ev.target.id === this.props.id + "_end_date") {
|
||||
if (type === "endDate") {
|
||||
this.endDate = value
|
||||
}
|
||||
}
|
||||
@@ -41,9 +50,14 @@ export class DateFilter extends Component {
|
||||
return domain
|
||||
}
|
||||
|
||||
// 点击日期选择器时触发
|
||||
dateOnchange(ev) {
|
||||
this.setActiveValues(ev);
|
||||
startDateOnchange (startDate) {
|
||||
this.setActiveValues(startDate, "startDate");
|
||||
this.props.fieldOnchange({fieldDomainList: this.domain, startDate: this.startDate, endDate: this.endDate});
|
||||
|
||||
}
|
||||
|
||||
endDateOnchange (endDate) {
|
||||
this.setActiveValues(endDate, "endDate");
|
||||
this.props.fieldOnchange({fieldDomainList: this.domain, startDate: this.startDate, endDate: this.endDate});
|
||||
}
|
||||
|
||||
@@ -67,6 +81,9 @@ export class DateFilter extends Component {
|
||||
}
|
||||
|
||||
DateFilter.template = "header_search_panel.DateFilter";
|
||||
DateFilter.components = {
|
||||
DateTimeInput,
|
||||
};
|
||||
DateFilter.props = {
|
||||
...standardFieldFilterProps,
|
||||
};
|
||||
|
||||
+26
-19
@@ -5,26 +5,33 @@
|
||||
<t t-name="header_search_panel.DateFilter" owl="1">
|
||||
<!-- 选择字段选择项 -->
|
||||
<div class="date-filter">
|
||||
<input
|
||||
type="date"
|
||||
t-attf-id="{{ props.id + '_start_date' }}"
|
||||
name="start_date"
|
||||
t-att-value="this.startDate"
|
||||
t-on-change="dateOnchange"/>
|
||||
<input
|
||||
type="date"
|
||||
t-attf-id="{{ props.id + '_end_date' }}"
|
||||
name="end_date"
|
||||
t-att-value="this.endDate"
|
||||
t-on-change="dateOnchange"/>
|
||||
<DateTimeInput value="dateFrom"
|
||||
type="props.type"
|
||||
onChange.bind="startDateOnchange"/>
|
||||
<i class="oi oi-arrow-right"/>
|
||||
<DateTimeInput value="dateTo"
|
||||
type="props.type"
|
||||
onChange.bind="endDateOnchange"/>
|
||||
<!-- <input -->
|
||||
<!-- t-att-type="props.type" -->
|
||||
<!-- t-attf-id="{{ props.id + '_start_date' }}" -->
|
||||
<!-- name="start_date" -->
|
||||
<!-- t-att-value="this.startDate" -->
|
||||
<!-- t-on-change="dateOnchange"/> -->
|
||||
<!-- <input -->
|
||||
<!-- t-att-type="props.type" -->
|
||||
<!-- t-attf-id="{{ props.id + '_end_date' }}" -->
|
||||
<!-- name="end_date" -->
|
||||
<!-- t-att-value="this.endDate" -->
|
||||
<!-- t-on-change="dateOnchange"/> -->
|
||||
</div>
|
||||
<div class="fast-date-filter">
|
||||
<a href="#" id="one-month" t-on-click="() => this.setDateRange(1)">近1个月</a>
|
||||
<a href="#" id="three-months" t-on-click="() => this.setDateRange(3)">近3个月</a>
|
||||
<a href="#" id="half-year" t-on-click="() => this.setDateRange(6)">近半年</a>
|
||||
<a href="#" id="one-year" t-on-click="() => this.setDateRange(12)">近1年</a>
|
||||
<a href="#" id="two-years" t-on-click="() => this.setDateRange(24)">近2年</a>
|
||||
</div>
|
||||
<!-- <div class="fast-date-filter"> -->
|
||||
<!-- <a href="#" id="one-month" t-on-click="() => this.setDateRange(1)">近1个月</a> -->
|
||||
<!-- <a href="#" id="three-months" t-on-click="() => this.setDateRange(3)">近3个月</a> -->
|
||||
<!-- <a href="#" id="half-year" t-on-click="() => this.setDateRange(6)">近半年</a> -->
|
||||
<!-- <a href="#" id="one-year" t-on-click="() => this.setDateRange(12)">近1年</a> -->
|
||||
<!-- <a href="#" id="two-years" t-on-click="() => this.setDateRange(24)">近2年</a> -->
|
||||
<!-- </div> -->
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
+15
@@ -8,6 +8,7 @@ import { BooleanFilter } from "./boolean_filter/boolean_filter";
|
||||
import { DateFilter } from "./date_filter/date_filter";
|
||||
import { Many2oneFilter } from "./many2one_filter/many2one_filter";
|
||||
import { X2ManyFilterFilter } from "./x2many_filter/x2many_filter";
|
||||
import { CharFilter } from "./char_filter/char_filter";
|
||||
|
||||
const fieldRegistry = registry.category("fields");
|
||||
|
||||
@@ -41,6 +42,9 @@ export class FieldsFilter extends Component {
|
||||
case "one2many":
|
||||
this.addX2ManyFieldDependencies(fieldInfo)
|
||||
break;
|
||||
case "char":
|
||||
this.addCharFieldDependencies(fieldInfo)
|
||||
break;
|
||||
}
|
||||
return fieldInfo;
|
||||
}
|
||||
@@ -65,6 +69,9 @@ export class FieldsFilter extends Component {
|
||||
case "many2many":
|
||||
case "one2many":
|
||||
return X2ManyFilterFilter;
|
||||
case "char":
|
||||
return CharFilter;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,6 +135,7 @@ export class FieldsFilter extends Component {
|
||||
domain: field.fieldDomain || "[]",
|
||||
fieldString: field.fieldString,
|
||||
searchLimit: field.fieldOptions?.search_limit || 10,
|
||||
placeholder: field.placeholder,
|
||||
}
|
||||
this._addFieldBaseProps(field.props, field);
|
||||
}
|
||||
@@ -144,6 +152,13 @@ export class FieldsFilter extends Component {
|
||||
this._addFieldBaseProps(field.props, field);
|
||||
}
|
||||
|
||||
addCharFieldDependencies(field) {
|
||||
field.Component = this._getComponent(field);
|
||||
// 组件props
|
||||
field.props = {};
|
||||
this._addFieldBaseProps(field.props, field);
|
||||
}
|
||||
|
||||
// 筛选字段的onChange事件,将筛选字段的id和domain传给searchModel
|
||||
fieldFilterOnchange(fieldsFilterId, fieldsFilterInfo) {
|
||||
if (fieldsFilterInfo?.fieldDomainList){
|
||||
|
||||
+1
@@ -104,6 +104,7 @@ export class Many2oneFilter extends Component {
|
||||
activeActions: {create: false, createEdit: false, write: false},
|
||||
fieldString: this.props.fieldString,
|
||||
searchLimit: this.props.searchLimit,
|
||||
placeholder: this.props.placeholder,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -13,4 +13,6 @@ export const standardFieldFilterProps = {
|
||||
type: {type: String, required: true},
|
||||
// 字段变换监听函数
|
||||
fieldOnchange: { type: Function, required: true },
|
||||
// 提示
|
||||
placeholder: {type: String, optional: true},
|
||||
};
|
||||
|
||||
+2
-2
@@ -2,11 +2,11 @@
|
||||
<templates xml:space="preserve">
|
||||
<!-- 快速筛选组件 -->
|
||||
<t t-name="header_search_panel.QuickFilter" owl="1">
|
||||
<!-- <div t-if="props.showLabel" class="header-filter-label">
|
||||
<div t-if="props.showLabel" class="header-filter-label">
|
||||
<span>
|
||||
<t t-esc="props.string" />
|
||||
</span>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- quick filter 内的筛选循环 -->
|
||||
<div class="header-filter-value">
|
||||
<div class="selection-options">
|
||||
|
||||
@@ -74,10 +74,12 @@
|
||||
.fast-date-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
input[type="date"],
|
||||
.o_datetime_input,
|
||||
.fast-date-filter a {
|
||||
width: auto;
|
||||
margin: 0.2rem;
|
||||
padding: 0.1rem 1rem;
|
||||
border: 0.1rem solid $o-community-color; /* 将边框颜色改为黑色 */
|
||||
@@ -149,6 +151,14 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-search-inline {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: start;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.header_search_toggle {
|
||||
width: 6rem;
|
||||
height: 2rem;
|
||||
@@ -161,4 +171,4 @@
|
||||
line-height: 2rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +165,8 @@ patch(SearchArchParser.prototype, {
|
||||
const fieldString = node.getAttribute("string");
|
||||
// 自定义css类
|
||||
const cssClass = node.getAttribute("class");
|
||||
// placeholder
|
||||
const placeholder = node.getAttribute("placeholder");
|
||||
// 获取字段的options属性,该属性代表字段选项
|
||||
const fieldOptions = evaluateExpr(node.getAttribute("options") || "{}");
|
||||
// 获取widget
|
||||
@@ -173,7 +175,7 @@ patch(SearchArchParser.prototype, {
|
||||
if (fieldName) {
|
||||
const field = this.fields[fieldName];
|
||||
// 如果字段类型为selection或者bool,将字段名和选项添加到headerSearchInfo的fields中
|
||||
if (!["selection", "boolean", "date", "datetime", "many2one", "one2many", "many2many"].includes(field.type)) {
|
||||
if (!["selection", "boolean", "date", "datetime", "many2one", "one2many", "many2many", "char"].includes(field.type)) {
|
||||
return false;
|
||||
}
|
||||
const fieldInfo = {
|
||||
@@ -186,6 +188,7 @@ patch(SearchArchParser.prototype, {
|
||||
fieldOptions: fieldOptions,
|
||||
modifiers: JSON.parse(node.getAttribute("modifiers") || "{}"),
|
||||
class: cssClass,
|
||||
placeholder: placeholder || undefined,
|
||||
}
|
||||
if (["many2one", "many2many"].includes(field.type)) {
|
||||
fieldInfo.fieldDomain = node.getAttribute("domain");
|
||||
@@ -237,17 +240,16 @@ patch(SearchArchParser.prototype, {
|
||||
for (const node of headerSearchNode.children) {
|
||||
switch (node.tagName) {
|
||||
case "field":
|
||||
// // 字段筛选
|
||||
// this.visitHeaderField(node);
|
||||
// 字段筛选
|
||||
this.visitHeaderField(node);
|
||||
break;
|
||||
case "quick_filter":
|
||||
// 快捷筛选
|
||||
this.visitHeaderQuickFilter(node);
|
||||
break;
|
||||
case "select_date_filter":
|
||||
// // 自选日期筛选
|
||||
// this.visitHeaderSelectDateFilter(node);
|
||||
break;
|
||||
// 自选日期筛选
|
||||
this.visitHeaderSelectDateFilter(node);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
+14
-8
@@ -209,14 +209,20 @@
|
||||
</t>
|
||||
<td class="ks_info">
|
||||
<t t-if="ks_show_records">
|
||||
<i id="ks_item_info" t-att-data-model="state.list_view_data['model']"
|
||||
t-att-data-list-type="state.list_view_data['list_view_type']"
|
||||
t-att-data-groupby="state.list_view_data['groupby']"
|
||||
t-att-data-record-id="table_row['id']" t-att-data-item-id="item_id"
|
||||
t-att-data-list-view-type="tmpl_list_type"
|
||||
t-att-data-domain="table_row['domain']"
|
||||
t-on-click="ksOnListItemInfoClick"
|
||||
class="fa fa-pencil"/>
|
||||
<button id="ks_item_info"
|
||||
class="btn btn-secondary"
|
||||
style="padding: 2px 4px!important;white-space: nowrap;"
|
||||
t-att-data-model="state.list_view_data['model']"
|
||||
t-att-data-list-type="state.list_view_data['list_view_type']"
|
||||
t-att-data-groupby="state.list_view_data['groupby']"
|
||||
t-att-data-record-id="table_row['id']"
|
||||
t-att-data-item-id="item_id"
|
||||
t-att-data-list-view-type="tmpl_list_type"
|
||||
t-att-data-domain="table_row['domain']"
|
||||
t-on-click="ksOnListItemInfoClick"
|
||||
>
|
||||
详情
|
||||
</button>
|
||||
</t>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -21,7 +21,7 @@ MENU_BADGE_MODEL_FUNC_ENUM = {
|
||||
'yuthon_property.yuthon_property_rent_list': {'model': 'property.rent.list', 'func': 'get_no_read_count'},
|
||||
'yuthon_property.yuthon_property_management_list': {'model': 'property.management.list', 'func': 'get_no_read_count'},
|
||||
'yuthon_property.yuthon_property_deposit_list': {'model': 'property.deposit.list', 'func': 'get_no_read_count'},
|
||||
'soong_workflow.menu_workflow_approval_request_my_start': {'model': 'soong.workflow.record', 'func': 'get_no_read_count'},
|
||||
'soong_workflow.menu_soong_workflow_todo_record': {'model': 'soong.workflow.record', 'func': 'get_no_read_count'},
|
||||
'soong_workflow.menu_workflow_approval_request_copy': {'model': 'soong.workflow.record.copy', 'func': 'get_no_read_count'},
|
||||
'yuthon_will_task.menu_yuthon_will_task_root': {'model': 'yuthon.will.task', 'func': 'read_number'},
|
||||
'issue_library.yuthon_library_my_menu': {'model': 'issue.library', 'func': 'read_number'},
|
||||
|
||||
@@ -16,7 +16,7 @@ class SoongWorkflowRecord(models.Model):
|
||||
|
||||
def get_no_read_count(self):
|
||||
domain = [
|
||||
('approve_state', '=', 'pending'),
|
||||
('soong_state', '=', 'to_do'),
|
||||
('employee_ids.user_id', '=', self.env.user.id),
|
||||
('users_ids', 'in', self.env.user.id),
|
||||
('reclaim_state', '=', False)
|
||||
@@ -229,19 +229,18 @@ class SoongWorkflowRecord(models.Model):
|
||||
@api.model
|
||||
def get_view(self, view_id=None, view_type='form', **options):
|
||||
"""在视图加载时检查当前用户是否在经办人列表中,并更新状态"""
|
||||
if options.get('action_id') == 3236 or options.get('action_id') == 3996:
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
if current_employee:
|
||||
all_records = self.search([])
|
||||
# 更新当前用户经办的记录为"待办"
|
||||
user_records = all_records.search([
|
||||
('employee_ids', 'in', current_employee.id),
|
||||
])
|
||||
user_records.write({'soong_state': 'to_do'})
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
if current_employee:
|
||||
all_records = self.search([])
|
||||
# 更新当前用户经办的记录为"待办"
|
||||
user_records = all_records.search([
|
||||
('employee_ids', 'in', current_employee.id),
|
||||
])
|
||||
user_records.write({'soong_state': 'to_do'})
|
||||
|
||||
# 更新其他记录为"已办"
|
||||
other_records = all_records - user_records
|
||||
other_records.write({'soong_state': 'done'})
|
||||
# 更新其他记录为"已办"
|
||||
other_records = all_records - user_records
|
||||
other_records.write({'soong_state': 'done'})
|
||||
|
||||
return super(SoongWorkflowRecord, self).get_view(view_id, view_type, **options)
|
||||
|
||||
@@ -353,8 +352,8 @@ class SoongWorkflowRecord(models.Model):
|
||||
for record in record_ids:
|
||||
record_id = record.env[record.res_model].search([('id', '=', record.res_id)])
|
||||
record_list.append(record.id)
|
||||
if record_id.log_ids and self.env.user.name != "Administrator":
|
||||
raise UserError("当前流程不可删除")
|
||||
# if record_id.log_ids and self.env.user.name != "Administrator":
|
||||
# raise UserError("当前流程不可删除")
|
||||
wizard = self.env.ref("soong_workflow.view_soong_workflow_record_delete_wizard")
|
||||
return {
|
||||
"name": _("删除确认"),
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<filter name="is_start" string="草稿" domain="[('approve_state', '=', 'start')]" />
|
||||
<filter name="is_to_do" string="待办" domain="[('soong_state', '=', 'to_do')]"/>
|
||||
<group expand="0" string="审批分组">
|
||||
<filter string="误餐费" name='group_by_workflow_id' context="{'group_by':'meal'}"/>
|
||||
<filter string="误餐费" name='group_by_meal' context="{'group_by':'meal'}"/>
|
||||
<filter string="审批类型分组" name='group_by_approvals_group_id' context="{'group_by':'approvals_group_id'}"/>
|
||||
<filter string="状态" name="group_soong_state" context="{'group_by':'soong_state'}"/>
|
||||
</group>
|
||||
@@ -51,7 +51,9 @@
|
||||
<field name="text" optional="hide"/>
|
||||
<field name="documents_ids" optional="hide"/>
|
||||
<group expand="0" string="审批分组">
|
||||
<filter string="误餐费" name='group_by_workflow_id' context="{'group_by':'meal'}"/>
|
||||
<filter string="审批状态" name='group_by_approve_state' context="{'group_by':'approve_state'}"/>
|
||||
<filter string="审批类型" name='group_by_workflow_id' context="{'group_by':'workflow_id'}"/>
|
||||
<filter string="误餐费" name='group_by_meal' context="{'group_by':'meal'}"/>
|
||||
<filter string="审批类型分组" name='group_by_approvals_group_id' context="{'group_by':'approvals_group_id'}"/>
|
||||
<filter string="状态" name="group_soong_state" context="{'group_by':'soong_state'}"/>
|
||||
</group>
|
||||
@@ -188,17 +190,17 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="soong_workflow_record_my_action" model="ir.actions.act_window">
|
||||
<field name="name">我的流程</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">soong.workflow.record</field>
|
||||
<field name="view_mode">tree,kanban,search</field>
|
||||
<!-- <field name="context">{'check_employee': 1, 'search_default_is_start':1, 'search_default_is_to_do':1}</field>-->
|
||||
<field name="context">{'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}</field>
|
||||
<field name="domain">[('users_ids', 'in', uid), ('reclaim_state', '=', False)]</field>
|
||||
<field name="search_view_id" ref="soong_workflow_record_search"/>
|
||||
<field name="view_id" ref="soong_workflow_record_my_tree"/>
|
||||
</record>
|
||||
<!-- <record id="soong_workflow_record_my_action" model="ir.actions.act_window">-->
|
||||
<!-- <field name="name">我的流程</field>-->
|
||||
<!-- <field name="type">ir.actions.act_window</field>-->
|
||||
<!-- <field name="res_model">soong.workflow.record</field>-->
|
||||
<!-- <field name="view_mode">tree,kanban,search</field>-->
|
||||
<!--<!– <field name="context">{'check_employee': 1, 'search_default_is_start':1, 'search_default_is_to_do':1}</field>–>-->
|
||||
<!-- <field name="context">{'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}</field>-->
|
||||
<!-- <field name="domain">[('users_ids', 'in', uid), ('reclaim_state', '=', False)]</field>-->
|
||||
<!-- <field name="search_view_id" ref="soong_workflow_record_search"/>-->
|
||||
<!-- <field name="view_id" ref="soong_workflow_record_my_tree"/>-->
|
||||
<!-- </record>-->
|
||||
<record id="soong_workflow_record_todo_action" model="ir.actions.act_window">
|
||||
<field name="name">待办</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
|
||||
@@ -145,8 +145,8 @@ class SoongWorkflowCommentWizard(models.TransientModel):
|
||||
for idx, link in enumerate(sorted_all_links):
|
||||
if link.id == current_link.id and link.sequence == current_link.sequence:
|
||||
approvers = self._get_approvers_for_link(link, record_id)
|
||||
if not approvers:
|
||||
invalid_links |= link
|
||||
# if not approvers:
|
||||
# invalid_links |= link
|
||||
|
||||
if record_id.log_ids2:
|
||||
log_records = record_id.log_ids2
|
||||
@@ -425,7 +425,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
|
||||
|
||||
for employee in self.employee_ids:
|
||||
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
|
||||
url = f'https://oa.thtzjt.com/web?login={employee.user_id.login}&oauth_uid={employee.wecom_userid}#id={record_id.id}&cids=2&action={action_id.id}&model={record_id._name}&view_type=form&menu_id=10104'
|
||||
url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&active_id={action_id.id}&model={record_id._name}&view_type=form'
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
|
||||
user_id=employee.wecom_userid,
|
||||
title=record_id._description,
|
||||
@@ -623,7 +623,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
|
||||
employees = self.node_btn_id.workflow_id.employee_ids
|
||||
recipients = [emp for emp in employees]
|
||||
for employee in recipients:
|
||||
url = f'https://oa.thtzjt.com/web?login={employee.user_id.login}&oauth_uid={employee.wecom_userid}#id={record_id.id}&cids=2&action={action_id.id}&model={record_id._name}&view_type=form&menu_id=10104'
|
||||
url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&active_id={action_id.id}&model={record_id._name}&view_type=form'
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
|
||||
user_id=employee.wecom_userid,
|
||||
title=record_id._description,
|
||||
|
||||
@@ -118,32 +118,6 @@ class HrLeave(models.Model):
|
||||
hour_batch_id = fields.Many2one(string='批量', comodel_name='hr.leave.batch', ondelete='cascade')
|
||||
leave_documents_ids = fields.Many2many(related='holiday_status_id.leave_documents_id', string="假期详情说明", readonly=True)
|
||||
details = fields.Text(string="假期流程说明")
|
||||
request_hour_from_real = fields.Selection([
|
||||
('0', '0:00'), ('0.5', '0:30'),
|
||||
('1', '01:00'), ('1.5', '01:30'),
|
||||
('2', '02:00'), ('2.5', '02:30'),
|
||||
('3', '03:00'), ('3.5', '03:30'),
|
||||
('4', '04:00'), ('4.5', '04:30'),
|
||||
('5', '05:00'), ('5.5', '05:30'),
|
||||
('6', '06:00'), ('6.5', '06:30'),
|
||||
('7', '07:00'), ('7.5', '07:30'),
|
||||
('8', '08:00'), ('8.5', '08:30'),
|
||||
('9', '09:00'), ('9.5', '09:30'),
|
||||
('10', '10:00'), ('10.5', '10:30'),
|
||||
('11', '11:00'), ('11.5', '11:30'),
|
||||
('12', '12:00'), ('12.5', '12:30'),
|
||||
('13', '13:00'), ('13.5', '13:30'),
|
||||
('14', '14:00'), ('14.5', '14:30'),
|
||||
('15', '15:00'), ('15.5', '15:30'),
|
||||
('16', '16:00'), ('16.5', '16:30'),
|
||||
('17', '17:00'), ('17.5', '17:30'),
|
||||
('18', '18:00'), ('18.5', '18:30'),
|
||||
('19', '19:00'), ('19.5', '19:30'),
|
||||
('20', '20:00'), ('20.5', '20:30'),
|
||||
('21', '21:00'), ('21.5', '21:30'),
|
||||
('22', '22:00'), ('22.5', '22:30'),
|
||||
('23', '23:00'), ('23.5', '23:30')],
|
||||
string='实际开始时间', compute='_compute_request_hour_from_real')
|
||||
# custom_document_ids = fields.Many2many(
|
||||
# string='文件',
|
||||
# comodel_name='ir.attachment',
|
||||
@@ -209,14 +183,6 @@ class HrLeave(models.Model):
|
||||
for leave in leave_ids:
|
||||
leave.state = 'draft'
|
||||
|
||||
@api.depends('request_hour_from')
|
||||
def _compute_request_hour_from_real(self):
|
||||
for record in self:
|
||||
if record.request_hour_from == '9':
|
||||
record.request_hour_from_real = '8'
|
||||
else:
|
||||
record.request_hour_from_real = record.request_hour_from
|
||||
|
||||
@api.depends('date_from', 'date_to', 'resource_calendar_id', 'holiday_status_id.request_unit')
|
||||
def _compute_duration(self):
|
||||
super()._compute_duration()
|
||||
@@ -229,6 +195,7 @@ class HrLeave(models.Model):
|
||||
else:
|
||||
hours = 0.0
|
||||
holiday.number_of_hours = hours
|
||||
holiday.leave_hours = hours
|
||||
if holiday.holiday_status_id.type_of_work == "0":
|
||||
if holiday.request_hour_from and holiday.request_hour_to:
|
||||
start_hour = float(holiday.request_hour_from)
|
||||
@@ -236,13 +203,17 @@ class HrLeave(models.Model):
|
||||
if start_hour < 12 and end_hour > 12:
|
||||
hour = end_hour - start_hour - 1
|
||||
holiday.number_of_hours = hour
|
||||
holiday.leave_hours = hour
|
||||
elif start_hour == 9 and end_hour == 12:
|
||||
holiday.number_of_hours = 4
|
||||
holiday.leave_hours = 4
|
||||
else:
|
||||
hour = end_hour - start_hour
|
||||
holiday.number_of_hours = hour
|
||||
holiday.leave_hours = hour
|
||||
else:
|
||||
holiday.number_of_hours = 0
|
||||
holiday.leave_hours = 0
|
||||
|
||||
# 按天请假
|
||||
days = holiday.batch_id._compute_duration_day(holiday.holiday_status_id, holiday.request_date_from , holiday.request_date_to)
|
||||
@@ -686,7 +657,6 @@ class HolidaysRequestBatch(models.Model):
|
||||
total_days = 0
|
||||
first_hour_leave = self.hour_leave_ids[0] if self.hour_leave_ids else None
|
||||
holiday_status_names = []
|
||||
# 处理leave_ids:收集假期类型、日期和天数
|
||||
for leave in self.leave_ids:
|
||||
# 收集假期类型名称(去重)
|
||||
if leave.holiday_status_id and leave.holiday_status_id.name:
|
||||
@@ -700,10 +670,8 @@ class HolidaysRequestBatch(models.Model):
|
||||
if leave.request_date_to:
|
||||
all_dates.append(leave.request_date_to)
|
||||
|
||||
# 累加天数
|
||||
total_days += leave.number_of_days_display if hasattr(leave, 'number_of_days_display') else 0
|
||||
|
||||
# 处理hour_leave_ids:收集日期
|
||||
for line in self.hour_leave_ids:
|
||||
if line.request_date_from:
|
||||
all_dates.append(line.request_date_from)
|
||||
@@ -721,17 +689,11 @@ class HolidaysRequestBatch(models.Model):
|
||||
# 生成名称:员工名 + 假期类型 + 日期范围 + 天数/小时
|
||||
if self.employee_id:
|
||||
name_parts = [f"{self.employee_id.name}的"]
|
||||
|
||||
# 拼接假期类型
|
||||
if holiday_status_names:
|
||||
name_parts.append(','.join(holiday_status_names))
|
||||
|
||||
# 拼接日期范围
|
||||
if self.start_date and self.end_date:
|
||||
date_part = f"{self.start_date.strftime('%Y-%m-%d')}~{self.end_date.strftime('%Y-%m-%d')}"
|
||||
name_parts.append(date_part)
|
||||
|
||||
# 拼接整请假天数
|
||||
if self.leave_ids:
|
||||
name_parts.append(f"共计{int(total_days)}天")
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
'default_employee_id': employee_id,
|
||||
}" string=" " style="width: 150%;">
|
||||
<tree editable="bottom">
|
||||
<field name="number_of_days_display" string="天" width="100px"/>
|
||||
<field name="employee_id" readonly="1" force_save="1" column_invisible="1"/>
|
||||
<field name="state" column_invisible="True"/>
|
||||
<field name="employee_company_id" column_invisible="True"/>
|
||||
@@ -116,7 +117,6 @@
|
||||
<!-- />-->
|
||||
<field name="request_date_from" width="100px" string="开始日期"/>
|
||||
<field name="request_date_to" width="100px" string="结束日期"/>
|
||||
<field name="number_of_days_display" string="天" width="100px"/>
|
||||
<field name="leave_documents_ids" widget="preview_many2many" options="{'preview_type': 'button', 'preview_string': ' '}" string=" " width="100px" readonly='true'/>
|
||||
<field name="request_hour_to" column_invisible="True"/>
|
||||
</tree>
|
||||
@@ -230,7 +230,6 @@
|
||||
<field name="request_unit_hours" invisible="True" force_save="1"/>
|
||||
<field name="request_date_from" width="100px" string="请假日期"/>
|
||||
<field name="request_hour_from" width="200px"/>
|
||||
<field name="request_hour_from_real" invisible="True"/>
|
||||
<field name="request_hour_to" width="200px"/>
|
||||
<field name="request_date_to" invisible="True"/>
|
||||
<field name="number_of_hours_text" string="小时" width="100px" invisible="True"/>
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
<field name="end_date" invisible="not is_day"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="start_day_selection" invisible="not is_day" string=" " widget="redio"/>
|
||||
<field name="end_day_selection" invisible="not is_day" string=" " widget="redio"/>
|
||||
<field name="start_day_selection" invisible="not is_day" string=" " widget="radio"/>
|
||||
<field name="end_day_selection" invisible="not is_day" string=" " widget="radio"/>
|
||||
</group>
|
||||
<group/>
|
||||
</group>
|
||||
|
||||
@@ -564,6 +564,16 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="member_view_search" model="ir.ui.view">
|
||||
<field name="name">hr.employee.search</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="工会会员">
|
||||
<field name="name"/>
|
||||
<field name="department_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<!--会员列表-->
|
||||
<record id="view_employee_member_tree" model="ir.ui.view">
|
||||
<field name="name">hr.employee.member</field>
|
||||
@@ -574,7 +584,7 @@
|
||||
<field name="work_phone" readonly="1"/>
|
||||
<field name="department_id" readonly="1" options='{"no_open": True, "no_create": True}'/>
|
||||
<field name="job_id" readonly="1" options='{"no_open": True, "no_create": True}'/>
|
||||
<field name="is_company" optional="hide"/>
|
||||
<field name="is_company" column_invisible="1"/>
|
||||
<field name="company_id" column_invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -591,7 +601,6 @@
|
||||
<xpath expr="//filter[@name='group_manager']" position="after">
|
||||
<filter name="group_is_membership" string="工会会员" context="{'group_by': 'is_membership'}"/>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//search" position="inside">
|
||||
<header_search>
|
||||
<quick_filter string="状态">
|
||||
@@ -659,11 +668,11 @@
|
||||
<field name="name">会员列表</field>
|
||||
<field name="res_model">hr.employee</field>
|
||||
<field name="domain">[('is_membership', '=', True), ('is_company', '=', True)]</field>
|
||||
<field name="context">{'header_search_default_user_state': 1}</field>
|
||||
<field name="view_mode">tree,kanban,form,search</field>
|
||||
<field name="view_ids" eval="[(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'tree', 'view_id': ref('yuthon_hr_employee.view_employee_member_tree')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('hr.view_employee_form')})]"/>
|
||||
<field name="search_view_id" ref="member_view_search"/>
|
||||
</record>
|
||||
<record id="hr.open_view_employee_list_my" model="ir.actions.act_window">
|
||||
<field name="view_mode">tree,kanban,form,activity,graph,pivot,hierarchy</field>
|
||||
|
||||
@@ -43,7 +43,7 @@ class YuthonReassignmentApproval(models.Model):
|
||||
#异动信息
|
||||
change_kind = fields.Selection([('promoted', '晋升'), ('demoted', '降职'), ('leveling', '平级调整'), ('seconded', '借调')], default="promoted", string="异动类型")
|
||||
change_reason = fields.Text(string="异动原因")
|
||||
change_company_id = fields.Many2one('res.company', string="异动公司", default=lambda self: self.env.user.company_id)
|
||||
change_company_id = fields.Many2one('res.company', string="异动公司")
|
||||
change_date = fields.Date(string="调动日期", default=lambda self: fields.Date.today())
|
||||
handover_date = fields.Date(string="移交日期", default=lambda self: fields.Date.today())
|
||||
handover_person_id = fields.Many2one("hr.employee", string="工作交接人")
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
</group>
|
||||
<group>
|
||||
<field name="login_document_id" widget="preview_many2one"/>
|
||||
<field name="login_state" widget="redio"/>
|
||||
<field name="login_state" widget="radio"/>
|
||||
</group>
|
||||
<div class="oe_clear_row" style="margin: 35px 0">
|
||||
</div>
|
||||
|
||||
@@ -34,15 +34,15 @@
|
||||
<group>
|
||||
<field name="urgency_level" readonly="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_this_company"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_issues"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="related_issues_id" invisible="is_issues == False"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_this_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<div class="col-12 text-center">
|
||||
<h1>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
</h1>
|
||||
</div>
|
||||
<group string="审批事项">
|
||||
<field name="is_back" invisible="1"/>
|
||||
<field name="name" required="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="issue_text"/>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<field name="notice_state" class="list_ids_width"/>
|
||||
<button name="on_sequence" string="置顶" invisible="sequence != 0" type="object" class="btn-primary"/>
|
||||
<button name="no_sequence" string="取消置顶" invisible="sequence != 1" type="object" class="btn-primary"/>
|
||||
<!-- <button name="look_up_notice_users" string="查阅情况" type="object" class="btn-primary"/>-->
|
||||
<button name="look_up_notice_users" string="查阅情况" type="object" class="btn-primary"/>
|
||||
<button name="stop_notice" string="终止" type="object" class="btn-primary"/>
|
||||
<field name="sequence" column_invisible="1"/>
|
||||
</tree>
|
||||
|
||||
@@ -23,8 +23,8 @@ class YuthonOfficialIncomingNormal(models.Model):
|
||||
secret_level = fields.Selection([('normal', '一般'), ('urgent', '秘密'), ('secret', '机密'), ('so_secret', '绝密')], string="密级")
|
||||
time_date = fields.Datetime(string="日期", default=fields.Datetime.now)
|
||||
users_id = fields.Many2one('res.users', string="拟办人", default=lambda self: self.env.user.id)
|
||||
department_id = fields.Many2one(related='users_id.employee_id.department_id', string="拟办部门")
|
||||
company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
|
||||
department_id = fields.Many2one(related='users_id.employee_ids.department_id', string="拟办部门")
|
||||
company_id = fields.Many2one(related='users_id.employee_ids.company_id', string="公司")
|
||||
department_data = fields.Html(string="拟办意见")
|
||||
red_suit = fields.Char(string="套红")
|
||||
official_statu = fields.Selection([('done', '办结'), ('approval', '审核')], string="公文环节")
|
||||
|
||||
@@ -37,6 +37,44 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- 押金对账列表-->
|
||||
<record id="view_property_accounts_receivable_tree1" model="ir.ui.view">
|
||||
<field name="name">property.accounts.receivable.tree</field>
|
||||
<field name="model">property.accounts.receivable</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree editable="bottom" string="应收账单" decoration-success="is_reconciliation == True" limit="15" delete="false">
|
||||
<field name="acc_type" string=" "/>
|
||||
<field name="management_type_id" readonly="0"/>
|
||||
<field name="due_date" readonly="0" width="300px" required="1"/>
|
||||
<field name="due_date_end" readonly="0"/>
|
||||
<field name="payout_date" readonly="0"/>
|
||||
<field name="original_amount" readonly="0"/>
|
||||
<field name="discount_amount" readonly="0"/>
|
||||
<field name="delivered1" readonly="0"/>
|
||||
<field name="submitted" options='{"fg_color": "red: submitted != false;" }'/>
|
||||
<field name="number_of_payments"/>
|
||||
<field name="remark"/>
|
||||
<field name="multiplier" column_invisible="1"/>
|
||||
<field name="is_push" optional="hide" readonly="0"/>
|
||||
<field name="reconciliation_time" optional="hide" readonly="0"/>
|
||||
<field name="create_time" readonly="0"/>
|
||||
<field name="last_update_time" optional="hide" readonly="0"/>
|
||||
<field name="is_invalid" column_invisible="1"/>
|
||||
<field name="void_date" column_invisible="1"/>
|
||||
<field name="is_red" column_invisible="1"/>
|
||||
<field name="is_reconciliation" optional="hide"/>
|
||||
<field name="difference_amount" readonly="0"/>
|
||||
<field name="receivable_log" column_invisible="1"/>
|
||||
<field name="is_suspend" optional="hide"/>
|
||||
<field name="is_write" column_invisible="1"/>
|
||||
<field name="bank_id" column_invisible="1"/>
|
||||
<field name="print_number"/>
|
||||
<field name="print_date"/>
|
||||
<field name="discount_date"/>
|
||||
<field name="has_date"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="all_property_accounts_receivable_contract" model="ir.actions.server">
|
||||
<field name="name">导入应收初始化数据</field>
|
||||
<field name="model_id" ref="yuthon_property.model_property_accounts_receivable"/>
|
||||
|
||||
@@ -57,9 +57,9 @@ class MeterPriceWizard(models.TransientModel):
|
||||
if valid.archives_id.type == 'fees':
|
||||
if valid.contract_id.id:
|
||||
electric_id = self.env['property.electric.fee.line'].search([
|
||||
('property_meter_archives_id.name', '=', '950404861125'),
|
||||
('property_meter_archives_id', '=', valid.archives_id.id),
|
||||
('contract_id', '=', valid.contract_id.id),
|
||||
])
|
||||
], limit=1)
|
||||
if electric_id:
|
||||
if electric_id.unit_price > 0:
|
||||
unit = electric_id.unit_price
|
||||
|
||||
@@ -59,7 +59,8 @@ class WaterPriceWizard(models.TransientModel):
|
||||
if valid.contract_id.id:
|
||||
water_id = self.env['property.water.fee.line'].search([
|
||||
('property_meter_water_id', '=', valid.water_id.id),
|
||||
])
|
||||
('contract_id', '=', valid.contract_id.id)
|
||||
], limit=1)
|
||||
if water_id:
|
||||
if water_id.unit_price > 0:
|
||||
unit = water_id.unit_price
|
||||
|
||||
@@ -94,8 +94,10 @@
|
||||
'wizard/contract_signature_wizard_viwes.xml',
|
||||
'wizard/penalty_line_wizard_viwes.xml',
|
||||
'wizard/build_pop_wizard_viwes.xml',
|
||||
'wizard/action_refuse_wizard_views.xml',
|
||||
'wizard/property_bills_wizard_views.xml',
|
||||
'wizard/property_meeting_wizard_views.xml',
|
||||
'wizard/property_deposit_wizard_views.xml',
|
||||
'views/property_menu_all.xml',
|
||||
],
|
||||
|
||||
|
||||
@@ -617,6 +617,53 @@ class PropertyAccountsReceivable(models.Model):
|
||||
actual_coping = fields.Float(string="实际应付", compute='_compute_actual_coping', store=True)
|
||||
charging_range = fields.Text(string="收费区间")
|
||||
|
||||
def verification_wizard(self):
|
||||
receivable_lines = self.env['property.accounts.receivable'].search([
|
||||
('contract_id', '=', self.contract_id.id),
|
||||
('is_reconciliation', '=', False),
|
||||
])
|
||||
receivable_line_vals = []
|
||||
for line in receivable_lines:
|
||||
receivable_line_vals.append((0, 0, {
|
||||
'due_date': line.due_date,
|
||||
'management_type_id': line.management_type_id.id,
|
||||
'amount': line.submitted,
|
||||
'payment_type': 'pay',
|
||||
'receivable_id': line.id,
|
||||
'remake': line.remark,
|
||||
}))
|
||||
|
||||
bills_lines = self.env['property.bills.list'].search([
|
||||
('contract_id', '=', self.contract_id.id),
|
||||
('actual_date', '!=', False),
|
||||
])
|
||||
bills_line_vals = []
|
||||
for line in bills_lines:
|
||||
bills_line_vals.append((0, 0, {
|
||||
'due_date': line.due_date,
|
||||
'management_type_id': line.management_type_id.id,
|
||||
'amount': line.amount,
|
||||
'bills_id': line.id,
|
||||
'payment_type': 'spending',
|
||||
'remake': line.remake
|
||||
}))
|
||||
all_line_vals = receivable_line_vals + bills_line_vals
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": "押金核销弹窗",
|
||||
"res_model": "property.deposit.wizard",
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
"context": {
|
||||
"default_contract_id": self.contract_id.id,
|
||||
"default_lessee_id": self.lessee_id.id,
|
||||
"default_actual_date": self.due_date,
|
||||
"default_deposit": self.original_amount,
|
||||
'default_reconciliation_line_ids': all_line_vals
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@api.depends('contract_id', 'due_date')
|
||||
def compute_tenure_type(self):
|
||||
for record in self:
|
||||
@@ -873,7 +920,16 @@ class PropertyAccountsReceivable(models.Model):
|
||||
valid_management_types = list(model_type_data.values())
|
||||
for rec in archives_ids:
|
||||
if rec.is_reconciliation == True:
|
||||
raise UserError("已对账的记录不能退回!请先银行流水撤销再退回")
|
||||
return {
|
||||
"name": "批量退回提醒弹窗",
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'action.refuse.wizard',
|
||||
"view_mode": "form",
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_receivable_ids': archives_ids.ids,
|
||||
}
|
||||
}
|
||||
model_type = model_type_data.get(rec.management_type_id.name)
|
||||
if model_type not in valid_management_types:
|
||||
rec.unlink()
|
||||
|
||||
@@ -1636,7 +1636,6 @@ class PropertyLeaseContract(models.Model):
|
||||
electricity_list = []
|
||||
water_list = []
|
||||
title_address = []
|
||||
fee_list = []
|
||||
for record in rec.lease_ids:
|
||||
if record.address_id and record.address_id.title_address:
|
||||
lease_name.append(record.address_id.name)
|
||||
@@ -1963,7 +1962,6 @@ class PropertyLeaseContract(models.Model):
|
||||
def _onchange_name(self):
|
||||
if self.property_name:
|
||||
self.address_for_delivery = self.property_name
|
||||
self.use_address = self.property_name
|
||||
|
||||
@api.onchange("admin_id")
|
||||
def _onchange_admin_id(self):
|
||||
|
||||
@@ -60,11 +60,22 @@ class PropertyLeaseRenewal(models.Model):
|
||||
deposit = fields.Float(string="原押金")
|
||||
is_full_refund = fields.Boolean(string="是否全额退押", default=True)
|
||||
refund_amount = fields.Float(string="退款金额")
|
||||
refund_remake = fields.Char(string="备注")
|
||||
total_receivables = fields.Float(string="应收金额", compute="_compute_total_receivables")
|
||||
total_remake = fields.Char(string="备注")
|
||||
balance = fields.Float(string="余额")
|
||||
remake = fields.Text(string="备注")
|
||||
balance_remake = fields.Char(string="备注")
|
||||
|
||||
receivables_ids = fields.One2many('early.receivables.line', 'renewal_id', string='应收明细')
|
||||
|
||||
@api.depends('receivables_ids', 'receivables_ids.original_amount', 'receivables_ids.reduction_amount',
|
||||
'receivables_ids.void')
|
||||
def _compute_total_receivables(self):
|
||||
for renewal in self:
|
||||
valid_receivable_lines = renewal.receivables_ids.filtered(lambda line: not line.void and line.is_reconciliation == False)
|
||||
total = sum(line.original_amount - line.reduction_amount for line in valid_receivable_lines)
|
||||
renewal.total_receivables = total
|
||||
|
||||
@api.onchange('refund_amount')
|
||||
def _onchange_refund_amount(self):
|
||||
for rec in self:
|
||||
@@ -177,19 +188,30 @@ class PropertyLeaseRenewal(models.Model):
|
||||
'contract_id': new_contract.id
|
||||
})
|
||||
else:
|
||||
receivable_ids = self.env['property.accounts.receivable'].search([
|
||||
('due_date', '<=', rec.early_quitting_date),
|
||||
('contract_id', '=', rec.contract_id.id),
|
||||
])
|
||||
# receivable_ids = self.env['property.accounts.receivable'].search([
|
||||
# ('due_date', '<=', rec.early_quitting_date),
|
||||
# ('contract_id', '=', rec.contract_id.id),
|
||||
# ])
|
||||
# if any(not receivable.is_reconciliation for receivable in receivable_ids):
|
||||
# raise UserError("该合同下存在未对账的应收单,无法提前退押金")
|
||||
|
||||
rec.contract_id.write({
|
||||
'actual_end_time': rec.early_quitting_date
|
||||
})
|
||||
rec.contract_id.get_property_contract_time()
|
||||
# rec.contract_id.get_property_contract_time()
|
||||
if rec.balance > rec.total_receivables:
|
||||
management_type_id = self.env['yuthon.management.type'].search([
|
||||
('name', '=', '违约金')
|
||||
])
|
||||
self.env['property.accounts.receivable'].create({
|
||||
'contract_id': rec.contract_id.id,
|
||||
'management_type_id': management_type_id.id,
|
||||
'due_date': rec.early_quitting_date,
|
||||
'original_amount': rec.balance - rec.total_receivables,
|
||||
'remark': rec.total_remake,
|
||||
})
|
||||
if rec.receivables_ids:
|
||||
refund_lines = rec.receivables_ids.filtered(lambda l: l.refund_amount > 0)
|
||||
refund_lines = rec.receivables_ids.filtered(lambda l: l.refund_amount > 0 and management_type_id.name != '押金')
|
||||
bills_line_list = []
|
||||
# 除押金的明细
|
||||
if refund_lines:
|
||||
@@ -199,7 +221,7 @@ class PropertyLeaseRenewal(models.Model):
|
||||
'management_type_id': refund_line.management_type_id.id,
|
||||
'amount': refund_line.refund_amount,
|
||||
'contract_id': rec.contract_id.id,
|
||||
'remake': rec.remake
|
||||
'remake': rec.refund_remake
|
||||
})
|
||||
# 押金
|
||||
deposit_management_type = self.env['yuthon.management.type'].search(
|
||||
@@ -213,7 +235,7 @@ class PropertyLeaseRenewal(models.Model):
|
||||
'management_type_id': deposit_management_type.id,
|
||||
'amount': deposit_amount,
|
||||
'contract_id': rec.contract_id.id,
|
||||
'remake': rec.remake
|
||||
'remake': rec.refund_remake
|
||||
})
|
||||
|
||||
if not rec.is_full_refund:
|
||||
@@ -222,7 +244,7 @@ class PropertyLeaseRenewal(models.Model):
|
||||
'start_time': start_time,
|
||||
'original_amount': rec.balance,
|
||||
'name_account': rec.lessee_id.name,
|
||||
'remake': rec.remake,
|
||||
'remake': rec.refund_remake,
|
||||
})
|
||||
|
||||
# 创建应付账单
|
||||
@@ -233,19 +255,16 @@ class PropertyLeaseRenewal(models.Model):
|
||||
for receivable_id in rec.receivables_ids:
|
||||
if receivable_id.void:
|
||||
receivable_id.receivable_id.write({
|
||||
'is_void': True,
|
||||
'is_invalid': True,
|
||||
'void_date': fields.Date.today()
|
||||
})
|
||||
if receivable_id.reduction_amount:
|
||||
receivable_id.receivable_id.reduction_amount = receivable_id.reduction_amount
|
||||
receivable_id.receivable_id.discount_amount = receivable_id.reduction_amount
|
||||
receivable_id.receivable_id.discount_date = fields.Date.today()
|
||||
|
||||
@api.onchange('early_quitting_date', 'contract_id')
|
||||
def _onchange_early_quitting_date(self):
|
||||
if not self.early_quitting_date :
|
||||
self.receivables_ids = [(5, 0, 0)]
|
||||
return
|
||||
|
||||
self.receivables_ids = [(5, 0, 0)]
|
||||
receivable_ids = self.env['property.accounts.receivable'].search([
|
||||
('due_date', '<=', self.early_quitting_date),
|
||||
('contract_id', '=', self.contract_id.id),
|
||||
|
||||
@@ -121,4 +121,7 @@ access_property_bills_line,property_bills_line,model_property_bills_line,base.gr
|
||||
access_property_payment_notice,property_payment_notice,model_property_payment_notice,base.group_user,1,1,1,1
|
||||
access_print_payment_wizard,print_payment_wizard,model_print_payment_wizard,base.group_user,1,1,1,1
|
||||
access_property_bills_list,property_bills_list,model_property_bills_list,base.group_user,1,1,1,1
|
||||
access_property_bills_wizard,property_bills_wizard,model_property_bills_wizard,base.group_user,1,1,1,1
|
||||
access_property_bills_wizard,property_bills_wizard,model_property_bills_wizard,base.group_user,1,1,1,1
|
||||
access_action_refuse_wizard,action_refuse_wizard,model_action_refuse_wizard,base.group_user,1,1,1,1
|
||||
access_property_deposit_wizard,property_deposit_wizard,model_property_deposit_wizard,base.group_user,1,1,1,1
|
||||
access_deposit_reconciliation_line,deposit_reconciliation_line,model_deposit_reconciliation_line,base.group_user,1,1,1,1
|
||||
|
@@ -408,6 +408,35 @@
|
||||
<field name="this_month_table" column_invisible="1"/>
|
||||
<field name="ratio" column_invisible="1"/>
|
||||
<field name="billable_quantity" column_invisible="1"/>
|
||||
<!-- <field name="company_id1"/>-->
|
||||
<field name="contract_id" string="合同编号"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='receivable_log']" position="after">
|
||||
<field name="penalty"/>
|
||||
<field name="penalty_date"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<record id="inherit_property_accounts_receivable_form_tree" model="ir.ui.view">
|
||||
<field name="name">property.accounts.receivable.tree</field>
|
||||
<field name="model">property.accounts.receivable</field>
|
||||
<field name="inherit_id" ref="yuthon_property.view_property_accounts_receivable_tree1"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='has_date']" position="before">
|
||||
<button name="verification_wizard" string="核销" type="object" class="btn btn-primary"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='remark']" position="after">
|
||||
<field name="charging_range"/>
|
||||
<field name="is_penalty" column_invisible="1"/>
|
||||
<field name="property_name" width="350px"/>
|
||||
<field name="property_ids" options="{'no_create': True}" widget="many2many_tags" column_invisible="1"/>
|
||||
<field name="lessee_id" options="{'no_create': True}" readonly="1"/>
|
||||
<field name="title_deed" readonly="1"/>
|
||||
<field name="company_id" column_invisible="1"/>
|
||||
<field name="last_month_table" column_invisible="1"/>
|
||||
<field name="this_month_table" column_invisible="1"/>
|
||||
<field name="ratio" column_invisible="1"/>
|
||||
<field name="billable_quantity" column_invisible="1"/>
|
||||
<!-- <field name="company_id1"/>-->
|
||||
<field name="contract_id" string="合同编号"/>
|
||||
</xpath>
|
||||
@@ -467,6 +496,15 @@
|
||||
<field name="search_view_id" ref="view_property_accounts_receivable_search"/>
|
||||
<field name="view_id" ref="yuthon_property.view_property_accounts_receivable_tree"/>
|
||||
</record>
|
||||
<record id="accounts_receivable_deposit_action" model="ir.actions.act_window">
|
||||
<field name="name">押金列表</field>
|
||||
<field name="res_model">property.accounts.receivable</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="context">{'search_default_group_by_contract_id': True}</field>
|
||||
<field name="domain">[('management_type_id.name','=', '押金')]</field>
|
||||
<field name="search_view_id" ref="view_property_accounts_receivable_search"/>
|
||||
<field name="view_id" ref="yuthon_property.view_property_accounts_receivable_tree1"/>
|
||||
</record>
|
||||
<!-- 合同应收报表 -->
|
||||
<record id="view_property_accounts_receivable_report_tree" model="ir.ui.view">
|
||||
<field name="name">property.accounts.receivable.tree.form</field>
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="is_back" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="work_end" invisible="1"/>
|
||||
<field name="is_manage" invisible="1"/>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<form string="租赁变更审批" create="0">
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="普件" bg_color="text-bg-success"
|
||||
invisible="urgency_level != 'normal'"/>
|
||||
invisible="urgency_level != 'normal'"/>
|
||||
<widget name="web_ribbon" title="急件" bg_color="text-bg-warning"
|
||||
invisible="urgency_level != 'urgent'"/>
|
||||
<widget name="web_ribbon" title="特级" bg_color="text-bg-danger"
|
||||
@@ -41,7 +41,7 @@
|
||||
<group string="审批事项">
|
||||
<field name="is_back" invisible="1"/>
|
||||
<field name="name" required="1"/>
|
||||
<field name="renewal_type" widget="radio"/>
|
||||
<field name="renewal_type" widget="radio"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="department_id" invisible="1"/>
|
||||
<field name="work_end" invisible="1"/>
|
||||
@@ -83,34 +83,63 @@
|
||||
<field name="phone" invisible="renewal_type != 'lease'"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="reason" invisible="renewal_type != 'lease'"/>
|
||||
<field name="effective_date" invisible="renewal_type != 'lease'"/>
|
||||
<field name="early_reason" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="deposit" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="is_full_refund" invisible="renewal_type != 'early_checkout'"/>
|
||||
</group>
|
||||
<group col="4">
|
||||
<group>
|
||||
<field name="reason" invisible="renewal_type != 'lease'"/>
|
||||
<field name="effective_date" invisible="renewal_type != 'lease'"/>
|
||||
<field name="early_reason" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="deposit" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="is_full_refund" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="refund_amount" invisible="is_full_refund"/>
|
||||
<field name="balance" invisible="is_full_refund"/>
|
||||
<field name="remake" invisible="is_full_refund"/>
|
||||
<field name="early_explain" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="document_ids" widget="preview_many2many"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="refund_remake" invisible="not refund_amount"/>
|
||||
</group>
|
||||
<group/>
|
||||
<group/>
|
||||
</group>
|
||||
<group col="4">
|
||||
<group>
|
||||
<field name="balance" invisible="is_full_refund"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="balance_remake" invisible="not balance"/>
|
||||
</group>
|
||||
<group/>
|
||||
<group/>
|
||||
</group>
|
||||
<group col="4">
|
||||
<group>
|
||||
<field name="total_receivables" invisible="is_full_refund"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="total_remake" invisible="not total_receivables"/>
|
||||
</group>
|
||||
<group/>
|
||||
<group/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="early_explain" invisible="renewal_type != 'early_checkout'"/>
|
||||
<field name="document_ids" widget="preview_many2many"/>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="应收明细" invisible="renewal_type != 'early_checkout'">
|
||||
<field name="receivables_ids" string=" ">
|
||||
<tree editable="bottom">
|
||||
<field name="renewal_id" column_invisible="1"/>
|
||||
<field name="receivable_id" column_invisible="1"/>
|
||||
<field name="management_type_id"/>
|
||||
<field name="due_date"/>
|
||||
<field name="original_amount"/>
|
||||
<field name="reduction_amount"/>
|
||||
<field name="refund_amount"/>
|
||||
<field name="is_reconciliation"/>
|
||||
<field name="void"/>
|
||||
</tree>
|
||||
<field name="receivables_ids" string=" ">
|
||||
<tree editable="bottom">
|
||||
<field name="renewal_id" column_invisible="1"/>
|
||||
<field name="receivable_id" column_invisible="1"/>
|
||||
<field name="management_type_id"/>
|
||||
<field name="due_date"/>
|
||||
<field name="original_amount"/>
|
||||
<field name="reduction_amount"/>
|
||||
<field name="refund_amount"/>
|
||||
<field name="is_reconciliation"/>
|
||||
<field name="void"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
|
||||
@@ -13,4 +13,6 @@ from . import contract_signature_wizard
|
||||
from . import build_pop_wizard
|
||||
from . import penalty_line_wizard
|
||||
from . import print_payment_wizard
|
||||
from . import property_bills_wizard
|
||||
from . import property_bills_wizard
|
||||
from . import action_refuse_wizard
|
||||
from . import property_deposit_wizard
|
||||
@@ -0,0 +1,51 @@
|
||||
from odoo import models, fields, api, _, SUPERUSER_ID
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from datetime import datetime, timedelta, date
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
class ActionRefuseWizard(models.TransientModel):
|
||||
_name = 'action.refuse.wizard'
|
||||
_description = '批量退回提醒弹窗'
|
||||
|
||||
receivable_ids = fields.Many2many('property.accounts.receivable', string='关联应收账单')
|
||||
|
||||
def confirm(self):
|
||||
model_type_data = {
|
||||
'水费': 'meter.water.line',
|
||||
'电费': 'meter.archives.line',
|
||||
'押金': 'property.deposit.list',
|
||||
'租金': 'property.rent.list',
|
||||
'管理费': 'property.management.list',
|
||||
}
|
||||
for rec in self.receivable_ids:
|
||||
if rec.is_reconciliation == True:
|
||||
continue
|
||||
model_type = model_type_data.get(rec.management_type_id.name)
|
||||
valid_management_types = list(model_type_data.values())
|
||||
if model_type not in valid_management_types:
|
||||
rec.unlink()
|
||||
continue
|
||||
if model_type in ('meter.archives.line', 'meter.water.line'):
|
||||
if not rec.charging_range:
|
||||
raise UserError("请输入计费区间, 按照应为'YYYY-MM-DD 到 YYYY-MM-DD格式")
|
||||
charging_range = rec.charging_range.strip()
|
||||
start_str, end_str = [x.strip() for x in charging_range.split("到")]
|
||||
start_date = (datetime.strptime(end_str, "%Y-%m-%d").date()).replace(day=1)
|
||||
end_date = datetime.strptime(end_str, "%Y-%m-%d").date()
|
||||
model_id = self.env[model_type].search([
|
||||
('contract_id', '=', rec.contract_id.id),
|
||||
('meter_date', '>=', start_date),
|
||||
('meter_date', '<=', end_date)
|
||||
])
|
||||
else:
|
||||
last_day = rec.due_date + relativedelta(months=1) - timedelta(days=1)
|
||||
model_id = self.env[model_type].search([
|
||||
('contract_id', '=', rec.contract_id.id),
|
||||
('due_date', '>=', rec.due_date),
|
||||
('due_date', '<=', last_day)
|
||||
])
|
||||
|
||||
if model_id:
|
||||
model_id.write({'is_push': False})
|
||||
rec.unlink()
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="action_refuse_wizard_form" model="ir.ui.view">
|
||||
<field name="name">action.refuse.wizard.form</field>
|
||||
<field name="model">action.refuse.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<div>
|
||||
<h1>
|
||||
包含已对账账单,需要退回可先从银行流水徹销已对账信息,是否继续?
|
||||
</h1>
|
||||
</div>
|
||||
<sheet>
|
||||
<footer>
|
||||
<button type="object" name="confirm" string="确认" class="oe_highlight"/>
|
||||
<button special="cancel" string="取消" class="btn-secondary"/>
|
||||
</footer>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -24,6 +24,7 @@ class ChoosePropertyWizard(models.Model):
|
||||
lease_ids_to_add = []
|
||||
title_deed = []
|
||||
title_address = []
|
||||
financial_address_list = []
|
||||
for record in self.property_ids:
|
||||
lease_name.append(record.name if record.name is not None else "")
|
||||
title_addr_name = record.title_address.name if (record.title_address and record.title_address.name) else ""
|
||||
@@ -50,12 +51,18 @@ class ChoosePropertyWizard(models.Model):
|
||||
rec.admin_id = admin_id
|
||||
rec.company_id = company_id
|
||||
rec.precinct_id = precinct_id
|
||||
fin_addr = record.financial_address if record.financial_address else ""
|
||||
if fin_addr: # 仅添加非空地址
|
||||
financial_address_list.append(fin_addr)
|
||||
|
||||
existing_names = []
|
||||
for lease in self.lease_contract_id.lease_ids:
|
||||
if lease.address_id:
|
||||
name_val = lease.address_id.name
|
||||
existing_names.append(name_val if name_val is not None else "无")
|
||||
fin_addr_exist = lease.address_id.financial_address if lease.address_id.financial_address else ""
|
||||
if fin_addr_exist:
|
||||
financial_address_list.append(fin_addr_exist)
|
||||
|
||||
title_name = []
|
||||
for lease in self.lease_contract_id.lease_ids:
|
||||
@@ -63,9 +70,9 @@ class ChoosePropertyWizard(models.Model):
|
||||
addr_name = lease.address_id.title_address.name if (lease.address_id.title_address and lease.address_id.title_address.name) else ""
|
||||
title_name.append(str(addr_name))
|
||||
|
||||
# 过滤空字符串,避免拼接时出现空内容
|
||||
all_names = [name for name in list(set(existing_names + lease_name)) if name]
|
||||
title_address_combined = [addr for addr in list(set(title_address + title_name)) if addr]
|
||||
use_address_combined = [addr for addr in list(set(financial_address_list)) if addr]
|
||||
|
||||
existing_lease_ids = [(4, lease.id) for lease in self.lease_contract_id.lease_ids]
|
||||
|
||||
@@ -77,7 +84,7 @@ class ChoosePropertyWizard(models.Model):
|
||||
'title_address': ','.join(title_address_combined),
|
||||
'lessor_id': self.lease_contract_id.lease_ids[0].address_id.company_id.id
|
||||
if self.lease_contract_id.lease_ids else False,
|
||||
'use_address': ','.join(all_names),
|
||||
'use_address': ','.join(use_address_combined),
|
||||
'address_for_delivery': ','.join(all_names),
|
||||
'total_area': sum([lease.property_area for lease in rec.lease_ids])
|
||||
})
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
from odoo import models, fields, api, _, SUPERUSER_ID
|
||||
from datetime import datetime, timedelta
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
import re
|
||||
|
||||
import logging
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class PropertyDepositWizard(models.Model):
|
||||
_name = 'property.deposit.wizard'
|
||||
_description = '押金核销'
|
||||
|
||||
lessee_id = fields.Many2one('property.tenant.information', string='承租方')
|
||||
contract_id = fields.Many2one('property.lease.contract', string='合同')
|
||||
property_name = fields.Char(related="contract_id.property_name", string='物业信息')
|
||||
actual_date = fields.Date(string='核销日期')
|
||||
|
||||
deposit = fields.Float(string='押金')
|
||||
reconciliation_line_ids = fields.One2many('deposit.reconciliation.line', 'reconciliation_id', string='对账明细')
|
||||
|
||||
def confirm(self):
|
||||
for record in self:
|
||||
reconciliation_lines = record.reconciliation_line_ids
|
||||
total_amount = sum(line.amount for line in reconciliation_lines)
|
||||
total_write_amount = sum(line.write_amount for line in reconciliation_lines)
|
||||
|
||||
amount_equal = abs(total_amount - total_write_amount) < 1e-6
|
||||
for line in reconciliation_lines:
|
||||
if line.write_amount:
|
||||
if line.receivable_id:
|
||||
if line.write_amount == line.amount:
|
||||
line.receivable_id.is_reconciliation = True
|
||||
else:
|
||||
line.receivable_id.yes_amount += line.write_amount
|
||||
if line.bills_id:
|
||||
line.bills_id.actual_date = record.actual_date
|
||||
line.bills_id.amount_actual = line.write_amount
|
||||
if amount_equal:
|
||||
if record.contract_id:
|
||||
record.contract_id.contact_state = 'settle'
|
||||
record.has_date = record.actual_date
|
||||
record.bills_list_id.contract_id.compute_is_has()
|
||||
|
||||
|
||||
class DepositReconciliationLine(models.Model):
|
||||
_name = 'deposit.reconciliation.line'
|
||||
_description = '押金对账明细'
|
||||
_order = 'due_date desc'
|
||||
|
||||
reconciliation_id = fields.Many2one('property.deposit.wizard', string='关联押金对账单弹窗')
|
||||
receivable_id = fields.Many2one('property.accounts.receivable', string='关联应收账单')
|
||||
bill_id = fields.Many2one('property.bills.list', string='关联应付账单')
|
||||
|
||||
due_date = fields.Date(string='应收日期')
|
||||
management_type_id = fields.Many2one('yuthon.management.type', string='类型')
|
||||
payment_type = fields.Selection([('pay', '支付'), ('spending', '支出')], string='收付款类型')
|
||||
amount = fields.Float(string='金额', store=True)
|
||||
write_amount = fields.Float(string='核销金额')
|
||||
remake = fields.Text(string='备注')
|
||||
|
||||
@api.onchange('write_amount')
|
||||
def onchange_remake(self):
|
||||
for line in self:
|
||||
if line.write_amount and line.payment_type == 'pay' and line.management_type_id.name != '违约金':
|
||||
line.remake = '押金转'+ line.management_type_id.name
|
||||
elif line.write_amount and line.payment_type == 'spending':
|
||||
line.remake = '退' + line.management_type_id.name
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="property_deposit_wizard_form" model="ir.ui.view">
|
||||
<field name="name">property.deposit.wizard.form</field>
|
||||
<field name="model">property.deposit.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="押金核销">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="actual_date"/>
|
||||
<h1>
|
||||
<field name="actual_date" style="font-weight: bold; color: #000000;" force_save="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group col="3">
|
||||
<group>
|
||||
<field name="property_name" readonly="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="lessee_id" readonly="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="contract_id" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="deposit"/>
|
||||
</group>
|
||||
<field name="reconciliation_line_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="reconciliation_id" column_invisible="1"/>
|
||||
<field name="receivable_id" column_invisible="1"/>
|
||||
<field name="bill_id" column_invisible="1"/>
|
||||
<field name="management_type_id"/>
|
||||
<field name="due_date"/>
|
||||
<field name="payment_type"/>
|
||||
<field name="amount"/>
|
||||
<field name="write_amount"/>
|
||||
<field name="remake"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
<button type="object" name="confirm" string="确认" class="oe_highlight"/>
|
||||
<button special="cancel" string="取消" class="btn-secondary"/>
|
||||
</footer>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -12,7 +12,7 @@
|
||||
<field name="actual_date" style="font-weight: bold; color: #000000;" readonly="1" force_save="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group col="4">
|
||||
<group col="3">
|
||||
<group>
|
||||
<field name="lessee_ids" widget="many2many_tags" readonly="1"/>
|
||||
</group>
|
||||
@@ -22,7 +22,6 @@
|
||||
<group>
|
||||
<field name="remake" readonly="1"/>
|
||||
</group>
|
||||
<group/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="bank_id" invisible="1"/>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="purchase_workflow_approval_code" model="ir.sequence">
|
||||
<field name="name">采购订单-编号</field>
|
||||
<field name="code">purchase_workflow_approval_code</field>
|
||||
<field name="prefix">CGOU%(y)s%(month)s%(day)s</field>
|
||||
<field name="padding">3</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -7,7 +7,7 @@ class PurchaseWorkflow(models.Model):
|
||||
_description = '采购审批单'
|
||||
_inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
|
||||
|
||||
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_order_sequence_code'))
|
||||
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_workflow_approval_code'))
|
||||
name = fields.Char(string="标题")
|
||||
name_title = fields.Char(string="默认标题", default=lambda self: self._description, readonly=True)
|
||||
user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user, required=True)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="action_leave_deduction_report" model="ir.actions.client">
|
||||
<field name="name">请假扣款报表</field>
|
||||
<field name="name">请假报表</field>
|
||||
<field name="tag">att_report_client</field>
|
||||
<field name="context">
|
||||
{
|
||||
@@ -22,7 +22,7 @@
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_meal_fee_report" model="ir.actions.client">
|
||||
<field name="name">误餐费报表</field>
|
||||
<field name="name">误餐报表</field>
|
||||
<field name="tag">att_report_client</field>
|
||||
<field name="context">
|
||||
{
|
||||
@@ -42,7 +42,7 @@
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_overtime_report" model="ir.actions.client">
|
||||
<field name="name">加班费报表</field>
|
||||
<field name="name">加班报表</field>
|
||||
<field name="tag">att_report_client</field>
|
||||
<field name="context">
|
||||
{
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record model="ir.rule" id="hr_payroll_structure_type_rule">
|
||||
<field name="name">职级类型多公司</field>
|
||||
<field name="model_id" ref="model_hr_payroll_structure_type"/>
|
||||
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
<record model="ir.rule" id="salary_payroll_distribution_rule">
|
||||
<field name="name">薪资方法多公司</field>
|
||||
<field name="model_id" ref="model_salary_payroll_distribution"/>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
'security/yuthon_will_task_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'views/yuthon_will_task_views.xml',
|
||||
'views/yuthon_dates_task_views.xml',
|
||||
'views/yuthon_task_time_views.xml',
|
||||
'views/yuthon_task_menu.xml',
|
||||
],
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<field name="name">定时任务:日程任务提醒</field>
|
||||
<field name="model_id" ref="model_yuthon_will_task"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.will_task_time()</field>
|
||||
<field name="code">model.add_comment()</field>
|
||||
<field eval="False" name="active"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from . import yuthon_will_task
|
||||
from . import yuthon_task_time
|
||||
from . import inherit_room_booking
|
||||
from . import yuthon_dates_task
|
||||
|
||||
@@ -47,7 +47,7 @@ class InheritRoomBooking(models.Model):
|
||||
start_datetime = new_record.start_datetime
|
||||
start_date = start_datetime.date()
|
||||
request_hour_from = get_hour_selection(new_record.start_datetime)
|
||||
request_hour_to = get_hour_selection(new_record.end_datetime)
|
||||
request_hour_to = get_hour_selection(new_record.stop_datetime)
|
||||
self.env['yuthon.will.task'].sudo().create({
|
||||
'name': new_record.name,
|
||||
'users_ids': [(6, 0, new_record.room_users_ids.ids)],
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import qrcode
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
import os
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
class YuthonDatesTask(models.Model):
|
||||
_name = "yuthon.dates.task"
|
||||
_description = "日程任务"
|
||||
|
||||
reminder_time = fields.Datetime(string='提醒时间')
|
||||
yuthon_will_task_id = fields.Many2one('yuthon.will.task', string='日程')
|
||||
employee_ids = fields.Many2many('hr.employee', string='提醒人员')
|
||||
task_state = fields.Selection([('to_do', '待提醒'), ('done', '已提醒')], string='状态')
|
||||
|
||||
@@ -163,35 +163,6 @@ class YuthonWillTask(models.Model):
|
||||
def read_number(self):
|
||||
return self.search_count([('task_state', '=', 'will'), ('users_ids', 'in', self.env.user.id)])
|
||||
|
||||
def will_task_time(self):
|
||||
# 任务状态判断
|
||||
for task in self.search([('task_state', '=', 'will')]):
|
||||
# 计算开始时间(将日期和时间选择转换为datetime对象)
|
||||
hour_from = float(task.request_hour_from)
|
||||
start_hour = int(hour_from)
|
||||
start_minute = int((hour_from - start_hour) * 60)
|
||||
start_datetime = datetime.combine(fields.Date.from_string(task.start_date), time(start_hour, start_minute))
|
||||
if task.request_hour_to:
|
||||
hour_to = float(task.request_hour_to)
|
||||
end_hour = int(hour_to)
|
||||
end_minute = int((hour_to - end_hour) * 60)
|
||||
end_datetime = start_datetime.replace(hour=end_hour, minute=end_minute)
|
||||
else:
|
||||
end_datetime = start_datetime + timedelta(hours=1)
|
||||
now = datetime.now() + timedelta(hours=8)
|
||||
if now > end_datetime:
|
||||
task.write({'task_state': 'done'})
|
||||
continue
|
||||
_logger.info(f"日程消息提醒定时任务判断\n当前时间:{now} --- 任务开始时间:{start_datetime}")
|
||||
if now <= start_datetime:
|
||||
if task.task_time_ids:
|
||||
for task_time in task.task_time_ids:
|
||||
duration = self._compute_duration(task_time)
|
||||
trigger_time = now + duration
|
||||
_logger.info(f"判断可否发送消息\n任务天:-{trigger_time.day}时:-{trigger_time.hour}分:-{trigger_time.minute}\n当前天:-{start_datetime.day}时:-{start_datetime.hour}分:-{start_datetime.minute}")
|
||||
if (trigger_time.day == start_datetime.day and trigger_time.hour == start_datetime.hour and trigger_time.minute == start_datetime.minute):
|
||||
task.add_comment()
|
||||
|
||||
def _compute_duration(self, task_time):
|
||||
if task_time.task_unit == 'min':
|
||||
return timedelta(minutes=task_time.number)
|
||||
@@ -203,20 +174,26 @@ class YuthonWillTask(models.Model):
|
||||
return timedelta.max
|
||||
|
||||
def add_comment(self):
|
||||
self.ensure_one()
|
||||
admin = self.env['hr.employee'].search([('name', '=', 'Administrator')])
|
||||
employee_list = [i.id for i in self.employee_ids] + [i.id for i in self.employee_ids2] + admin.id
|
||||
for employee_id in self.env['hr.employee'].search([('id', 'in', employee_list)]):
|
||||
if not employee_id.wecom_userid:
|
||||
raise UserError("请同步{}的企业微信".format(employee_id.name))
|
||||
url = f'https://oa.thtzjt.com/webh5#/journey?id={self.id}'
|
||||
data_name = "事项名称: " + self.name + '\n'
|
||||
data_user_ids = '参与人: ' + ', '.join(self.employee_ids.mapped('name')) + '\n'
|
||||
data_employee_id = ('司机:' + ', '.join(self.employee_ids2.mapped('name')) + '\n') if self.employee_ids2 else ''
|
||||
data_nota = ('备注:' + self.remarks) if self.remarks else ('') + '\n'
|
||||
data = data_name + data_user_ids + data_nota + data_employee_id
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid, title="日程事项提醒", description=data,
|
||||
url=url, btntxt="详细信息")
|
||||
"日程定时任务提醒"
|
||||
now = fields.datetime.now() + timedelta(hours=8)
|
||||
dates_task_ids = self.env['yuthon.dates.task'].search([('task_state', '=', 'to_do'), ('reminder_time', '<', fields.datetime.now() + timedelta(days=1))])
|
||||
for task in dates_task_ids:
|
||||
hour1 = (task.reminder_time + timedelta(hours=8)).hour
|
||||
minute1 = (task.reminder_time + timedelta(hours=8)).minute
|
||||
if minute1 == now.minute and hour1 == now.hour:
|
||||
task.write({'task_state': 'done'})
|
||||
will_id = task.yuthon_will_task_id
|
||||
for employee_id in will_id.employee_ids:
|
||||
url = f'https://oa.thtzjt.com/webh5#/journey?id={will_id.id}'
|
||||
data_name = "事项名称: " + task.yuthon_will_task_id.name + '\n'
|
||||
data_user_ids = '参与人: ' + ', '.join(will_id.employee_ids.mapped('name')) + '\n'
|
||||
data_employee_id = ('司机:' + ', '.join(will_id.employee_ids2.mapped('name')) + '\n') if will_id.employee_ids2 else ''
|
||||
data_nota = ('备注:' + will_id.remarks) if will_id.remarks else ('') + '\n'
|
||||
data = data_name + data_user_ids + data_nota + data_employee_id
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid, title="日程事项提醒", description=data,
|
||||
url=url, btntxt="详细信息")
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id="18562027762", title="日程事项提醒", description=data,
|
||||
url=url, btntxt="详细信息")
|
||||
|
||||
def button_add_comment(self):
|
||||
self.add_comment()
|
||||
@@ -236,14 +213,10 @@ class YuthonWillTask(models.Model):
|
||||
for employee_id in self.env['hr.employee'].search([('id', 'in', employee_list)]):
|
||||
if not employee_id.wecom_userid:
|
||||
raise UserError("请同步{}的企业微信".format(employee_id.name))
|
||||
menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的日程')])
|
||||
url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=yuthon.will.task&view_type=list&menu_id={menu_id.id}'
|
||||
url = f'https://oa.thtzjt.com/webh5#/journey?id={self.id}'
|
||||
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid,
|
||||
title="日程事项提醒", description="事项名称: " + self.name + '\t' + '该事项已取消',
|
||||
url=url, btntxt="详细信息")
|
||||
for record in self:
|
||||
partner_ids = record.employee_ids.user_id.partner_id.ids
|
||||
record.with_context(lang=record.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_will_task.mail_action_yuthon_will_task_add_comment')
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
@@ -252,4 +225,71 @@ class YuthonWillTask(models.Model):
|
||||
'message': '已发送取消提醒消息',
|
||||
'sticky': False,
|
||||
}
|
||||
}
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
"""创建日程时,同步创建提醒任务"""
|
||||
will_task = super(YuthonWillTask, self).create(vals)
|
||||
will_task._sync_dates_task()
|
||||
return will_task
|
||||
|
||||
def write(self, vals):
|
||||
"""修改日程时,先删除旧提醒任务,再创建新的"""
|
||||
res = super(YuthonWillTask, self).write(vals)
|
||||
key_fields = ['start_date', 'request_hour_from', 'task_time_ids', 'employee_ids', 'employee_ids2']
|
||||
if any(field in vals for field in key_fields):
|
||||
self._sync_dates_task()
|
||||
return res
|
||||
|
||||
def _sync_dates_task(self):
|
||||
reminder_employees = self.employee_ids | self.employee_ids2
|
||||
if not reminder_employees:
|
||||
return
|
||||
old_tasks = self.env['yuthon.dates.task'].search([('yuthon_will_task_id', '=', self.id), ('task_state', '=', 'to_do')])
|
||||
if old_tasks:
|
||||
old_tasks.unlink()
|
||||
start_hour = float(self.request_hour_from)
|
||||
hours = int(start_hour)
|
||||
minutes = int((start_hour - hours) * 60)
|
||||
task_start_datetime = datetime.combine(self.start_date,time(hour=hours, minute=minutes))
|
||||
for task_time in self.task_time_ids:
|
||||
reminder_time_str = task_time.name
|
||||
reminder_hours = 0.0
|
||||
import re
|
||||
match = re.match(r'(\d+)(分钟|小时|天)', reminder_time_str.strip())
|
||||
num = int(match.group(1))
|
||||
unit = match.group(2)
|
||||
if unit == '小时':
|
||||
reminder_hours = num
|
||||
elif unit == '分钟':
|
||||
reminder_hours = num / 60.0
|
||||
elif unit == '天':
|
||||
reminder_hours = num * 24.0
|
||||
reminder_datetime = task_start_datetime - timedelta(hours=reminder_hours)
|
||||
now = fields.datetime.now() + timedelta(hours=8)
|
||||
if now > reminder_datetime:
|
||||
continue
|
||||
existing_dates_task = self.env['yuthon.dates.task'].search([
|
||||
('yuthon_will_task_id', '=', self.id),
|
||||
('reminder_time', '=', reminder_datetime)
|
||||
])
|
||||
task_vals = {
|
||||
'reminder_time': reminder_datetime - timedelta(hours=8),
|
||||
'employee_ids': [(6, 0, reminder_employees.ids)],
|
||||
'task_state': 'to_do',
|
||||
}
|
||||
if existing_dates_task:
|
||||
existing_dates_task.write(task_vals)
|
||||
else:
|
||||
task_vals['yuthon_will_task_id'] = self.id
|
||||
self.env['yuthon.dates.task'].create(task_vals)
|
||||
|
||||
def schedule_reminders(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': '提醒任务详情',
|
||||
'view_mode': 'tree',
|
||||
'res_model': 'yuthon.dates.task',
|
||||
'domain': [('yuthon_will_task_id', '=', self.id)],
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_yuthon_task_time,yuthon_task_time,model_yuthon_task_time,yuthon_will_task.group_yuthon_will_task_user,1,1,1,1
|
||||
access_yuthon_will_task,yuthon_will_task,model_yuthon_will_task,yuthon_will_task.group_yuthon_will_task_user,1,1,1,1
|
||||
|
||||
access_yuthon_dates_task,yuthon_dates_task,model_yuthon_dates_task,yuthon_will_task.group_yuthon_will_task_user,1,1,1,1
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_yuthon_dates_task_tree" model="ir.ui.view">
|
||||
<field name="name">yuthon.dates.task.tree</field>
|
||||
<field name="model">yuthon.dates.task</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="日程任务" editable="bottom"
|
||||
decoration-success="task_state == 'to_do'"
|
||||
decoration-danger="task_state == 'done'"
|
||||
>
|
||||
<field name="yuthon_will_task_id"/>
|
||||
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}"/>
|
||||
<field name="reminder_time"/>
|
||||
<field name="task_state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_dates_task_search" model="ir.ui.view">
|
||||
<field name="name">yuthon.dates.task.search</field>
|
||||
<field name="model">yuthon.dates.task</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="日程任务">
|
||||
<field name="yuthon_will_task_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="task_state" string="状态" context="{'group_by':'task_state'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_yuthon_dates_task_action" model="ir.actions.act_window">
|
||||
<field name="name">日程任务</field>
|
||||
<field name="res_model">yuthon.dates.task</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_yuthon_dates_task_tree"/>
|
||||
<field name="search_view_id" ref="view_yuthon_dates_task_search"/>
|
||||
<field name="context">{'search_default_task_state':1}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -48,4 +48,9 @@
|
||||
parent="task_type_menu"
|
||||
action="yuthon_task_time_setting_action"
|
||||
sequence="5"/>
|
||||
<menuitem id="yuthon_dates_task_menu"
|
||||
name="日程任务"
|
||||
parent="task_type_menu"
|
||||
action="view_yuthon_dates_task_action"
|
||||
sequence="5"/>
|
||||
</odoo>
|
||||
@@ -26,6 +26,7 @@
|
||||
<field name='creation_time' optional="hide"/>
|
||||
<button name="button_add_comment" string="提醒" type="object" class="oe_highlight" invisible="task_state == 'cancel'"/>
|
||||
<button name="button_add_comment_cancel" string="取消" type="object" class="oe_highlight" invisible="task_state == 'cancel'"/>
|
||||
<button name="schedule_reminders" string="提醒任务" type="object" class="oe_highlight" groups="base.group_system"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -72,8 +73,8 @@
|
||||
<group>
|
||||
<label for="start_date"/>
|
||||
<div class="d-inline-flex w-100">
|
||||
<field name="start_date" string="日期:" class="me-2" style="max-width: 10rem !important;"/>时间
|
||||
<field name="request_hour_from" string=" " class="ms-2" style="max-width: 5rem !important;"/>至
|
||||
<field name="start_date" string="日期:" class="me-2" style="max-width: 10rem !important;"/>
|
||||
<field name="request_hour_from" string=" " class="ms-2" style="max-width: 5rem !important;"/>→
|
||||
<field name="request_hour_to" string=" " class="ms-2" style="max-width: 5rem !important;"/>
|
||||
</div>
|
||||
</group>
|
||||
@@ -173,9 +174,9 @@
|
||||
<label for="start_date"/>
|
||||
<div class="d-inline-flex w-100">
|
||||
<field name="start_date" string="日期:" class="me-2"
|
||||
style="max-width: 10rem !important;"/>时间
|
||||
style="max-width: 10rem !important;"/>
|
||||
<field name="request_hour_from" string=" " class="ms-2"
|
||||
style="max-width: 5rem !important;"/>至
|
||||
style="max-width: 5rem !important;"/>→
|
||||
<field name="request_hour_to" string=" " class="ms-2"
|
||||
style="max-width: 5rem !important;"/>
|
||||
</div>
|
||||
@@ -254,7 +255,7 @@
|
||||
<field name='name'>领导日程</field>
|
||||
<field name='res_model'>yuthon.will.task</field>
|
||||
<field name='view_mode'>tree,calendar,form</field>
|
||||
<field name='domain'>[('user_role_ids.name', 'in', ['董事长', '分管领导', '总经理', '部门副经理', '部门经理', '副总经理', '司机'])]</field>
|
||||
<field name='domain'>[('user_role_ids.name', 'in', ['董事长', '分管领导', '总经理', '部门副经理', '副总经理', '司机'])]</field>
|
||||
<field name="context">{'search_default_next_seven_days': 1}</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -207,21 +207,21 @@
|
||||
sequence="90"/>
|
||||
<menuitem
|
||||
id="menu_leave_deduction_report"
|
||||
name="请假扣款报表"
|
||||
name="请假报表"
|
||||
parent="menu_att_report"
|
||||
action="yuthon_report.action_leave_deduction_report"
|
||||
sequence="1"
|
||||
/>
|
||||
<menuitem
|
||||
id="menu_meal_fee_report"
|
||||
name="误餐费报表"
|
||||
name="误餐报表"
|
||||
parent="menu_att_report"
|
||||
action="yuthon_report.action_meal_fee_report"
|
||||
sequence="5"
|
||||
/>
|
||||
<menuitem
|
||||
id="menu_overtime_report"
|
||||
name="加班费报表"
|
||||
name="加班报表"
|
||||
parent="menu_att_report"
|
||||
action="yuthon_report.action_overtime_report"
|
||||
sequence="10"
|
||||
@@ -671,21 +671,21 @@
|
||||
parent="holiday_manage_menu_root_board"
|
||||
action="soong_workflow.action_kklw_workflow_approval_request"
|
||||
sequence="1"/>
|
||||
<menuitem id="menu_workflow_approval_request_my_start"
|
||||
name="我的流程"
|
||||
parent="holiday_manage_menu_root_board"
|
||||
action="soong_workflow.soong_workflow_record_my_action"
|
||||
sequence="2"/>
|
||||
<!-- <menuitem id="menu_workflow_approval_request_my_start"-->
|
||||
<!-- name="我的流程"-->
|
||||
<!-- parent="holiday_manage_menu_root_board"-->
|
||||
<!-- action="soong_workflow.soong_workflow_record_my_action"-->
|
||||
<!-- sequence="2"/>-->
|
||||
<menuitem id="menu_soong_workflow_todo_record"
|
||||
name="待办"
|
||||
parent="holiday_manage_menu_root_board"
|
||||
action="soong_workflow.soong_workflow_record_todo_action"
|
||||
sequence="5"/>
|
||||
sequence="4"/>
|
||||
<menuitem id="menu_soong_workflow_done_record"
|
||||
name="已办"
|
||||
parent="holiday_manage_menu_root_board"
|
||||
action="soong_workflow.soong_workflow_record_done_action"
|
||||
sequence="7"/>
|
||||
sequence="4"/>
|
||||
|
||||
<menuitem id="yuthon_notice_menu1_board"
|
||||
parent="holiday_manage_menu_root_board"
|
||||
@@ -874,7 +874,7 @@
|
||||
sequence="50"/>
|
||||
<menuitem id="yuthon_accounts_receivable_menu"
|
||||
sequence="1"
|
||||
name="应收账单(明细)"
|
||||
name="应收账单"
|
||||
parent="yuthon_financial_management_menu"
|
||||
action="yuthon_property_approval.property_accounts_receivable_action"/>
|
||||
<!-- <menuitem-->
|
||||
@@ -889,8 +889,14 @@
|
||||
name="应付账单"
|
||||
action="yuthon_property_approval.view_property_bills_list_action"
|
||||
sequence="4"/>
|
||||
<menuitem
|
||||
id="accounts_receivable_deposit_menu"
|
||||
parent="yuthon_financial_management_menu"
|
||||
name="押金列表"
|
||||
action="yuthon_property_approval.accounts_receivable_deposit_action"
|
||||
sequence="10"/>
|
||||
<menuitem id="yuthon_subject_form_menu"
|
||||
sequence="5"
|
||||
sequence="15"
|
||||
name="预算科目表"
|
||||
parent="yuthon_financial_management_menu"
|
||||
action="yuthon_property.view_property_subject_action"/>
|
||||
|
||||
Reference in New Issue
Block a user