From 899a219761e4c7e7f02765ffba8747dfaa483edf Mon Sep 17 00:00:00 2001
From: zhou <123@>
Date: Thu, 1 May 2025 18:36:56 +0800
Subject: [PATCH 1/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
room/controllers/main_room_yuthon.py | 1 -
room/views/room_booking_views.xml | 12 +++---------
room/views/webclient_templates.xml | 5 -----
.../views/issue_approval_decision_views.xml | 4 ++--
.../static/src/js/task_create_button.js | 18 ++++++++++++++----
.../static/src/xml/task_create_button.xml | 5 ++++-
6 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/room/controllers/main_room_yuthon.py b/room/controllers/main_room_yuthon.py
index 038bf8dbd..0922c3262 100644
--- a/room/controllers/main_room_yuthon.py
+++ b/room/controllers/main_room_yuthon.py
@@ -70,7 +70,6 @@ class Home(http.Controller):
def web_room_partner_create(self, room_id=None, **kw):
ensure_db()
values = {k: v for k, v in request.params.items()}
- _logger.info("Initial values: %s", values)
if not (room_id or values['room_id']):
values['error'] = "缺少会议号"
response = request.render('room.partner_create_form_room', values)
diff --git a/room/views/room_booking_views.xml b/room/views/room_booking_views.xml
index bc3e9aea2..2a723b7d6 100644
--- a/room/views/room_booking_views.xml
+++ b/room/views/room_booking_views.xml
@@ -178,15 +178,9 @@
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/room/views/webclient_templates.xml b/room/views/webclient_templates.xml
index 1121e0bff..6e194c439 100644
--- a/room/views/webclient_templates.xml
+++ b/room/views/webclient_templates.xml
@@ -153,11 +153,6 @@
-
-
-
-
-
diff --git a/yuthon_issue/views/issue_approval_decision_views.xml b/yuthon_issue/views/issue_approval_decision_views.xml
index 3b633f1a8..e52408b37 100644
--- a/yuthon_issue/views/issue_approval_decision_views.xml
+++ b/yuthon_issue/views/issue_approval_decision_views.xml
@@ -18,7 +18,7 @@
-
+
@@ -40,7 +40,7 @@
-
+
diff --git a/yuthon_will_task/static/src/js/task_create_button.js b/yuthon_will_task/static/src/js/task_create_button.js
index 9475aef56..e70e99dff 100644
--- a/yuthon_will_task/static/src/js/task_create_button.js
+++ b/yuthon_will_task/static/src/js/task_create_button.js
@@ -10,12 +10,22 @@ export class CustomTaskListController extends ListController {
openTaskForm() {
this.actionService.doAction({
type: 'ir.actions.act_window',
- res_model: 'task.room.wizard',
- name: '日程会议',
+ res_model: 'yuthon.will.task',
+ name: '创建日程',
+ view_mode: 'form',
+ view_type: 'form',
+ views: [[false, 'form']],
+ context: {},
+ });
+ }
+ openMeetingArrangementForm() {
+ this.actionService.doAction({
+ type: 'ir.actions.act_window',
+ res_model: 'room.booking',
+ name: '会议安排',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
- target: 'new',
context: {},
});
}
@@ -25,4 +35,4 @@ registry.category("views").add("custom_task_tree_button", {
...listView,
Controller: CustomTaskListController,
buttonTemplate: "yuthon_task.ListView.Buttons",
-});
+});
\ No newline at end of file
diff --git a/yuthon_will_task/static/src/xml/task_create_button.xml b/yuthon_will_task/static/src/xml/task_create_button.xml
index 3fa99fcd1..b12f64da3 100644
--- a/yuthon_will_task/static/src/xml/task_create_button.xml
+++ b/yuthon_will_task/static/src/xml/task_create_button.xml
@@ -3,7 +3,10 @@
+
From 2e60e666b2adb610d50ade800b312d6c90b5cdab Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?=
Date: Fri, 2 May 2025 14:38:11 +0800
Subject: [PATCH 2/4] 1
---
soong_workflow/wizard/soong_workflow_comment_wizard.py | 2 +-
.../static/src/web_list_num/list_renderer.scss | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py
index 1ba38d5e8..bd1463920 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py
@@ -102,7 +102,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
'|', ('department_id', '=', record_id.department_id.id), ('department_ids', 'in', record_id.department_id.id), ('company_id', '=', self.env.user.company_id.id)]) # 不自动匹配
elif link_users_group_ids:
# 不自动匹配
- employee_user_role_ids = self.env['hr.employee'].search(['|', ('user_role_id', 'in', link_users_group_ids.user_role_ids.ids), ('user_role_ids', 'in', link_users_group_ids.user_role_ids.ids),])
+ employee_user_role_ids = self.env['hr.employee'].search(['|', ('user_role_id', 'in', link_users_group_ids.user_role_ids.ids), ('user_role_ids', 'in', link_users_group_ids.user_role_ids.ids)])
# 自动匹配
employee_user_role_id = self.env['hr.employee'].search([('id', 'in', employee_user_role_ids.ids),
'|', ('department_id', '=', record_id.department_id.id),
diff --git a/tree_view_advanced_filter/static/src/web_list_num/list_renderer.scss b/tree_view_advanced_filter/static/src/web_list_num/list_renderer.scss
index f434222d7..70f52aecc 100644
--- a/tree_view_advanced_filter/static/src/web_list_num/list_renderer.scss
+++ b/tree_view_advanced_filter/static/src/web_list_num/list_renderer.scss
@@ -5,9 +5,9 @@
text-overflow: clip !important; // 移除省略号(或直接不设置)
min-width: max-content !important; // 按内容撑开列宽(可选)
}
- tr .o_data_cell {
- white-space: pre-wrap !important;
- }
+ //tr .o_data_cell {
+ // white-space: pre-wrap !important;
+ //}
}
}
From 3307ea6bdecae84d56d34ea48a8cf09a33679c99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?=
Date: Sat, 3 May 2025 10:30:22 +0800
Subject: [PATCH 3/4] 1
---
room/models/room_booking.py | 7 ++++++
room/views/room_booking_views.xml | 14 +++--------
yuthon_will_task/__init__.py | 3 +--
yuthon_will_task/__manifest__.py | 1 -
yuthon_will_task/security/ir.model.access.csv | 1 -
.../security/yuthon_will_task_security.xml | 4 +--
.../static/src/js/task_create_button.js | 6 ++---
yuthon_will_task/wizard/__init__.py | 1 -
yuthon_will_task/wizard/task_room_wizard.py | 25 -------------------
yuthon_will_task/wizard/task_room_wizard.xml | 20 ---------------
10 files changed, 17 insertions(+), 65 deletions(-)
delete mode 100644 yuthon_will_task/wizard/__init__.py
delete mode 100644 yuthon_will_task/wizard/task_room_wizard.py
delete mode 100644 yuthon_will_task/wizard/task_room_wizard.xml
diff --git a/room/models/room_booking.py b/room/models/room_booking.py
index aff397290..1b202b8e1 100644
--- a/room/models/room_booking.py
+++ b/room/models/room_booking.py
@@ -36,6 +36,7 @@ class RoomBooking(models.Model):
required=True)
meeting_type_id = fields.Many2one('room.meeting.type', string="会议类型")
room_users_ids = fields.Many2many('res.users', string="出席人员")
+ room_users_names = fields.Char(string="出席人员char", compute="_compute_room_users", store=True)
other_company_id = fields.Many2one('res.partner', string="外部公司")
host = fields.Many2one('res.users', string="主持人")
stationed_group = fields.Boolean(string="驻组参会")
@@ -55,6 +56,12 @@ class RoomBooking(models.Model):
# 关联流程
relevancy_type = fields.Selection([('none', '无')], string="关联流程类型")
+ @api.depends('room_users_ids')
+ def _compute_room_users(self):
+ for i in self:
+ employee_list = [rec.name for rec in i.room_users_ids]
+ i.room_users_names = ','.join(employee_list)
+
@api.onchange('meeting_type_id')
def _onchange_meeting_type_id(self):
if self.meeting_type_id:
diff --git a/room/views/room_booking_views.xml b/room/views/room_booking_views.xml
index bc3e9aea2..3ec4e99fa 100644
--- a/room/views/room_booking_views.xml
+++ b/room/views/room_booking_views.xml
@@ -32,6 +32,8 @@
string="Bookings"
plan="0">
+
+
@@ -44,18 +46,10 @@
- -
+
-
参会人员:
+
- -
- 出席人员:
-
-
- ,
-
-
-
-
diff --git a/yuthon_will_task/__init__.py b/yuthon_will_task/__init__.py
index c536983e2..9a7e03ede 100644
--- a/yuthon_will_task/__init__.py
+++ b/yuthon_will_task/__init__.py
@@ -1,2 +1 @@
-from . import models
-from . import wizard
\ No newline at end of file
+from . import models
\ No newline at end of file
diff --git a/yuthon_will_task/__manifest__.py b/yuthon_will_task/__manifest__.py
index e07d5a4ee..b1bf9d8b0 100644
--- a/yuthon_will_task/__manifest__.py
+++ b/yuthon_will_task/__manifest__.py
@@ -15,7 +15,6 @@
'views/yuthon_will_task_views.xml',
'views/yuthon_task_time_views.xml',
'views/yuthon_task_menu.xml',
- 'wizard/task_room_wizard.xml',
],
'assets': {
'web.assets_backend': [
diff --git a/yuthon_will_task/security/ir.model.access.csv b/yuthon_will_task/security/ir.model.access.csv
index ff343d39d..6761eb5e7 100644
--- a/yuthon_will_task/security/ir.model.access.csv
+++ b/yuthon_will_task/security/ir.model.access.csv
@@ -1,7 +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_task_room_wizard,task_room_wizard,model_task_room_wizard,yuthon_will_task.group_yuthon_will_task_user,1,1,1,1
diff --git a/yuthon_will_task/security/yuthon_will_task_security.xml b/yuthon_will_task/security/yuthon_will_task_security.xml
index cfb9b40bc..d8e1b26a8 100644
--- a/yuthon_will_task/security/yuthon_will_task_security.xml
+++ b/yuthon_will_task/security/yuthon_will_task_security.xml
@@ -5,11 +5,11 @@
日程组
- 日程用户
+ 日程-用户
- 日程组管理员
+ 日程-管理员
diff --git a/yuthon_will_task/static/src/js/task_create_button.js b/yuthon_will_task/static/src/js/task_create_button.js
index 30d70e0b9..039452190 100644
--- a/yuthon_will_task/static/src/js/task_create_button.js
+++ b/yuthon_will_task/static/src/js/task_create_button.js
@@ -10,12 +10,12 @@ export class CustomTaskListController extends ListController {
openTaskForm() {
this.actionService.doAction({
type: 'ir.actions.act_window',
- res_model: 'task.room.wizard',
+ res_model: 'yuthon.will.task',
name: '日程会议',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
- target: 'new',
+ target: 'current',
context: {},
});
}
@@ -27,7 +27,7 @@ export class CustomTaskListController extends ListController {
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
- target: 'new',
+ target: 'current',
context: {},
});
}
diff --git a/yuthon_will_task/wizard/__init__.py b/yuthon_will_task/wizard/__init__.py
deleted file mode 100644
index 0baeab723..000000000
--- a/yuthon_will_task/wizard/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from . import task_room_wizard
diff --git a/yuthon_will_task/wizard/task_room_wizard.py b/yuthon_will_task/wizard/task_room_wizard.py
deleted file mode 100644
index 23b343b2d..000000000
--- a/yuthon_will_task/wizard/task_room_wizard.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from odoo import api, fields, models
-
-
-class TaskRoomWizard(models.Model):
- _name = 'task.room.wizard'
- _description = '安排日程会议弹窗'
-
- def create_will_task(self):
- form_id = self.env.ref('yuthon_will_task.view_yuthon_will_task_form').id
- return {
- "type": "ir.actions.act_window",
- "name": "日程安排",
- "res_model": "yuthon.will.task",
- "views": [[form_id, "form"]],
- }
-
- def create_room(self):
- form_id = self.env.ref('room.room_booking_view_form').id
- return {
- "type": "ir.actions.act_window",
- "name": "会议安排",
- "res_model": "room.booking",
- "views": [[form_id, "form"]],
- }
-
diff --git a/yuthon_will_task/wizard/task_room_wizard.xml b/yuthon_will_task/wizard/task_room_wizard.xml
deleted file mode 100644
index 9b26dd9ef..000000000
--- a/yuthon_will_task/wizard/task_room_wizard.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- 安排日程会议
- task.room.wizard
-
-
-
-
-
From 71c16e843d0e2db36bb50010a3c36e674f9a8846 Mon Sep 17 00:00:00 2001
From: zhou <123@>
Date: Sat, 3 May 2025 16:29:49 +0800
Subject: [PATCH 4/4] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
soong_workflow/models/soong_user_role.py | 19 +-
soong_workflow/models/soong_workflow_log.py | 1 +
soong_workflow/models/soong_workflow_mixin.py | 1 +
.../views/soong_workflow_log_views.xml | 1 +
.../views/soong_workflow_record.xml | 4 +-
.../wizard/soong_workflow_comment_wizard.py | 19 +-
.../soong_workflow_comment_wizard_view.xml | 4 +-
.../soong_workflow_record_delete_wizard.py | 17 +-
yuthon_holiday/views/hr_leave_batch.xml | 222 +++++++++---------
9 files changed, 161 insertions(+), 127 deletions(-)
diff --git a/soong_workflow/models/soong_user_role.py b/soong_workflow/models/soong_user_role.py
index 966cc895b..bf91a3a56 100644
--- a/soong_workflow/models/soong_user_role.py
+++ b/soong_workflow/models/soong_user_role.py
@@ -15,7 +15,7 @@ class YuthonUserRole(models.Model):
end_time = fields.Date(string="终止日期")
parent_id = fields.Many2one('soong.user.role', string='上级角色')
user_role_group_ids = fields.Many2many('soong.user.role.group', string='角色分组', index=True)
- personnel_ids = fields.Many2many('hr.employee', string='在岗人员')
+ personnel_ids = fields.Many2many('hr.employee', string='在岗人员', store=True, index=True)
number_people = fields.Integer(string="在岗人数", compute='_compute_employee_ids')
personnel = fields.Text(string="在岗人员")
employee_ids = fields.One2many('hr.employee', 'user_role_id')
@@ -32,14 +32,6 @@ class YuthonUserRole(models.Model):
display_parts.append(f"({record.department_id.name})")
record.display_name = " ".join(display_parts)
- def write(self, vals):
- res = super(YuthonUserRole, self).write(vals)
- if 'personnel_ids' in vals:
- for record in self:
- for personnel_id in record.personnel_ids:
- personnel_id.write({'user_role_id': record.id})
- return res
-
@api.depends('name')
def _compute_pinyin(self):
for employee in self:
@@ -61,6 +53,15 @@ class YuthonUserRole(models.Model):
if rec.personnel_ids:
rec.number_people = len(rec.personnel_ids)
+ @api.onchange('personnel_ids')
+ def _onchange_personnel_ids(self):
+ for record in self:
+ for personnel_id in record.personnel_ids:
+ employee = self.env['hr.employee'].search([('id', '=', personnel_id.id.origin)], limit=1)
+ if employee:
+ if self.id.origin != employee.user_role_id.id:
+ new_user_role_ids = employee.user_role_ids.ids + [self.id.origin]
+ employee.write({'user_role_ids': [(6, 0, new_user_role_ids)],})
class YuthonUserRoleGroup(models.Model):
_name = 'soong.user.role.group'
diff --git a/soong_workflow/models/soong_workflow_log.py b/soong_workflow/models/soong_workflow_log.py
index aa84d666e..fea639756 100644
--- a/soong_workflow/models/soong_workflow_log.py
+++ b/soong_workflow/models/soong_workflow_log.py
@@ -26,6 +26,7 @@ class SoongWorkflowLog(models.Model):
approval_state = fields.Selection([('0', '待办'), ('1', '办理中'), ('2', '已办结'), ('3', '结束')], string='审批状态', default='0')
comment = fields.Char(string="意见")
date_create = fields.Datetime(string="时间", default=lambda self: fields.Datetime.now())
+ active = fields.Boolean(string="归档", default=True)
@api.depends("workflow_id", "node_id", "node_btn_id")
def _compute_name(self):
diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py
index 002fb3186..cbf0ce539 100644
--- a/soong_workflow/models/soong_workflow_mixin.py
+++ b/soong_workflow/models/soong_workflow_mixin.py
@@ -289,6 +289,7 @@ class SoongWorkflowMixin(models.AbstractModel):
"target": "new",
"context": {
"default_res_id": self.id,
+ "default_code":self.code,
"default_res_model": self._name,
"default_log_ids": logs.ids,
"default_node_btn_id": btn_rec.id,
diff --git a/soong_workflow/views/soong_workflow_log_views.xml b/soong_workflow/views/soong_workflow_log_views.xml
index 166b3d2b1..1b19c3087 100644
--- a/soong_workflow/views/soong_workflow_log_views.xml
+++ b/soong_workflow/views/soong_workflow_log_views.xml
@@ -17,6 +17,7 @@
+
diff --git a/soong_workflow/views/soong_workflow_record.xml b/soong_workflow/views/soong_workflow_record.xml
index 1d58f05ab..a475033c5 100644
--- a/soong_workflow/views/soong_workflow_record.xml
+++ b/soong_workflow/views/soong_workflow_record.xml
@@ -115,7 +115,7 @@
ir.actions.act_window
soong.workflow.record
tree,form,search
-
+ [('reclaim_state', '=', False)]
@@ -123,7 +123,7 @@
ir.actions.act_window
soong.workflow.record
tree,form
- [('users_ids', 'in', [uid]), ('reclaim_state', '=', True)]
+ [('reclaim_state', '=', True)]
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py
index bd1463920..1f282a513 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py
@@ -15,11 +15,12 @@ class SoongWorkflowCommentWizard(models.TransientModel):
name = fields.Char(string="name")
res_model = fields.Char()
res_id = fields.Integer()
+ code = fields.Char()
log_ids = fields.Many2many(comodel_name="soong.workflow.log")
node_btn_id = fields.Many2one(comodel_name="soong.workflow.node.button")
node_btn_name = fields.Char(string="动作名称", related='node_btn_id.name')
user_id = fields.Many2one('res.users',string='用户',default=lambda self: self.env.user)
- user_role_id = fields.Many2one('soong.user.role', string="角色", compute='_compute_user_role_id', store=True)
+ user_role_ids = fields.Many2many('soong.user.role', string="角色", compute='_compute_user_role_ids', store=True)
node_link_len = fields.Char(string="转交2")
is_supervising = fields.Boolean(string="是否督办")
comment_note_id = fields.Many2one('soong.note', string="常用意见", default='妥否,呈领导审批')
@@ -47,13 +48,13 @@ class SoongWorkflowCommentWizard(models.TransientModel):
if self.comment_note_id:
self.comment_note = self.comment_note_id.name
- @api.depends('user_id.employee_id.user_role_id')
- def _compute_user_role_id(self):
+ @api.depends('user_id.employee_ids.user_role_ids')
+ def _compute_user_role_ids(self):
for record in self:
- if record.user_id and record.user_id.employee_ids:
- record.user_role_id = record.user_id.employee_ids.user_role_id
+ if record.user_id:
+ record.user_role_ids = record.user_id.employee_ids.user_role_ids
else:
- record.user_role_id = False
+ record.user_role_ids = False
@api.onchange('record_id')
def _onchange_record_id(self):
@@ -135,6 +136,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
first_node = self.sudo().env["soong.workflow.log"].search([("model", "=", self.res_model), ("res_id", "=", self.res_id)])
if not now_record_obj:
self.sudo().env["soong.workflow.log"].create({
+ "code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id if first_node else record_id.workflow_id.node_ids[0].id,
@@ -153,6 +155,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
next_node_id = record_id.workflow_id.node_ids.search([('name', 'ilike', self.trans_link_id.name),
('workflow_id', '=', record_id.workflow_id.id)])
self.sudo().env["soong.workflow.log"].create({
+ "code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
@@ -180,6 +183,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
"approval_state_copy": "0",
})
self.sudo().env["soong.workflow.log2"].create({
+ "code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
@@ -210,6 +214,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
"node_btn_name": "1"})
# if not self.sudo().env["soong.workflow.log"].search([('node_id', '=', next_node_id.id)]):
self.sudo().env["soong.workflow.log"].create({
+ "code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
@@ -235,6 +240,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
"approval_state": "2",
"lase_click_date": fields.Datetime.now()})
self.sudo().env["soong.workflow.log"].create({
+ "code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": record_id.workflow_id.node_ids[-1].id,
@@ -257,6 +263,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
"approval_state_copy": "0",
})
self.sudo().env["soong.workflow.log2"].create({
+ "code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
index db1495643..ccb96a0c7 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
@@ -9,10 +9,10 @@
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+