@@ -47,8 +47,11 @@
|
||||
'web.assets_backend': [
|
||||
'soong_workflow/static/src/css/record_scss.scss',
|
||||
'soong_workflow/static/src/css/button_css.scss',
|
||||
'soong_workflow/static/src/css/urgency_level.scss',
|
||||
'soong_workflow/static/src/js/view_button.js',
|
||||
'soong_workflow/static/src/js/select_create_dialog.js',
|
||||
'soong_workflow/static/src/js/urgency_level_widget.js',
|
||||
'soong_workflow/static/src/js/urgency_level_widget.xml',
|
||||
'soong_workflow/static/src/diagram_plus_dialog/*',
|
||||
],
|
||||
},
|
||||
|
||||
@@ -667,6 +667,10 @@ class SoongWorkflowMixin(models.AbstractModel):
|
||||
sorted_logs = rec.log_ids.sorted(lambda log: log.id)
|
||||
if sorted_logs and sorted_logs[-1].lase_click_date:
|
||||
node_update_time = sorted_logs[-1].lase_click_date
|
||||
|
||||
# 补丁:如果审批状态已经是结束,但还没拿到时间,则尝试用当前时间作为办结时间
|
||||
if not node_update_time and record_obj.approve_state == 'end':
|
||||
node_update_time = fields.Datetime.now()
|
||||
except Exception as e:
|
||||
_logger.debug(f"Failed to get node_update_time: {e}")
|
||||
|
||||
|
||||
@@ -79,12 +79,33 @@ class SoongWorkflowRecord(models.Model):
|
||||
)
|
||||
|
||||
priority = fields.Selection([('0', 'Normal'), ('1', 'Urgent')], 'Priority', default='0', index=True)
|
||||
|
||||
urgency_level = fields.Selection(
|
||||
[('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')],
|
||||
string='紧急度',
|
||||
compute='_compute_urgency_level',
|
||||
store=False
|
||||
)
|
||||
|
||||
is_company = fields.Boolean(string="本公司", default=True, compute='_compute_is_company',search='_search_part_of_company')
|
||||
|
||||
# 办结时间(上一节点的结束时间)
|
||||
node_update_time = fields.Datetime(string="办结时间")
|
||||
|
||||
@api.depends('res_model', 'res_id')
|
||||
def _compute_urgency_level(self):
|
||||
"""从关联的业务模型中获取urgency_level值"""
|
||||
for record in self:
|
||||
record.urgency_level = 'normal' # 默认值
|
||||
if record.res_model and record.res_id:
|
||||
try:
|
||||
target_record = self.env[record.res_model].browse(record.res_id)
|
||||
if target_record.exists() and hasattr(target_record, 'urgency_level'):
|
||||
record.urgency_level = target_record.urgency_level or 'normal'
|
||||
except Exception as e:
|
||||
_logger.warning(f"Failed to get urgency_level from {record.res_model}: {e}")
|
||||
record.urgency_level = 'normal'
|
||||
|
||||
@api.depends_context('uid', 'company')
|
||||
@api.depends('company_id')
|
||||
def _compute_is_company(self):
|
||||
@@ -622,6 +643,48 @@ class SoongWorkflowRecord(models.Model):
|
||||
},
|
||||
}
|
||||
|
||||
def action_update_history_end_time(self):
|
||||
"""
|
||||
批量计算已结束流程的办结时间
|
||||
"""
|
||||
# 寻找所有审批状态为结束(end)且办结时间为空的记录
|
||||
records = self.search([
|
||||
('approve_state', '=', 'end'),
|
||||
('node_update_time', '=', False)
|
||||
])
|
||||
|
||||
count = 0
|
||||
for rec in records:
|
||||
if not rec.res_model or not rec.res_id:
|
||||
continue
|
||||
|
||||
try:
|
||||
# 获取对应的业务单据
|
||||
source_record = self.env[rec.res_model].browse(rec.res_id)
|
||||
if not source_record.exists():
|
||||
continue
|
||||
|
||||
# 提取该单据最后一条审批日志的时间
|
||||
if hasattr(source_record, 'log_ids') and source_record.log_ids:
|
||||
# 按ID排序,取最后一条记录
|
||||
sorted_logs = source_record.log_ids.sorted(lambda l: l.id)
|
||||
if sorted_logs and sorted_logs[-1].lase_click_date:
|
||||
# 更新办结时间
|
||||
rec.write({'node_update_time': sorted_logs[-1].lase_click_date})
|
||||
count += 1
|
||||
except Exception as e:
|
||||
_logger.error(f"计算记录 {rec.id} 办结时间失败: {e}")
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'title': '处理完成',
|
||||
'message': f'成功更新了 {count} 条记录的办结时间',
|
||||
'sticky': False,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
.urgency-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
min-width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.urgency-normal {
|
||||
background-color: white;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.urgency-urgent {
|
||||
background-color: #ffc107;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.urgency-emergency {
|
||||
background-color: #dc3545;
|
||||
color: #fff;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/** @odoo-module **/ // 声明这是一个Odoo模块,Odoo 17+必须有这个声明
|
||||
|
||||
// 从Odoo核心库导入注册表工具,用于注册自定义组件
|
||||
import { registry } from "@web/core/registry";
|
||||
// 从OWL框架导入Component基类,OWL是Odoo的前端框架
|
||||
import { Component } from "@odoo/owl";
|
||||
|
||||
// 定义紧急度徽章Widget类,继承自OWL的Component基类
|
||||
export class UrgencyLevelWidget extends Component {
|
||||
// 指定使用的XML模板名称,对应urgency_level_widget.xml中的模板
|
||||
static template = "soong_workflow.UrgencyLevelWidget";
|
||||
|
||||
// getter方法:根据紧急度值返回对应的CSS类名
|
||||
get urgencyClass() {
|
||||
// 从props中获取当前记录的urgency_level字段值
|
||||
const level = this.props.record.data.urgency_level;
|
||||
// 如果是急件,返回黄色样式类名
|
||||
if (level === 'urgent') {
|
||||
return 'urgency-urgent';
|
||||
// 如果是特急件,返回红色样式类名
|
||||
} else if (level === 'emergency') {
|
||||
return 'urgency-emergency';
|
||||
}
|
||||
// 默认返回白色样式类名(普件)
|
||||
return 'urgency-normal';
|
||||
}
|
||||
|
||||
// getter方法:判断是否显示"急"字徽章
|
||||
get isVisible() {
|
||||
// 从props中获取当前记录的urgency_level字段值
|
||||
const level = this.props.record.data.urgency_level;
|
||||
// 只有当值存在且不是'normal'时才显示(即只显示急件和特急件)
|
||||
return level && level !== 'normal';
|
||||
}
|
||||
}
|
||||
|
||||
// 将自定义Widget注册到Odoo的字段组件注册表中
|
||||
// 注册名为"urgency_level_badge",在视图中通过widget="urgency_level_badge"使用
|
||||
registry.category("fields").add("urgency_level_badge", {
|
||||
component: UrgencyLevelWidget, // 指定使用的组件类
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> <!-- XML文件声明,指定版本为1.0,字符编码为UTF-8 -->
|
||||
<!-- Odoo OWL模板文件,用于定义前端组件的HTML结构 -->
|
||||
<templates xml:space="preserve"> <!-- templates标签包裹所有模板,xml:space="preserve"表示保留空格和换行 -->
|
||||
<!-- 定义一个名为"soong_workflow.UrgencyLevelWidget"的模板,owl="1"表示这是OWL框架的模板 -->
|
||||
<t t-name="soong_workflow.UrgencyLevelWidget" owl="1">
|
||||
<!-- span标签用于显示"急"字徽章 -->
|
||||
<!-- t-if="isVisible":条件渲染,只有当JavaScript中的isVisible方法返回true时才显示这个span -->
|
||||
<!-- t-att-class="urgencyClass":动态绑定CSS类名,从JavaScript的urgencyClass方法获取类名 -->
|
||||
<!-- class="urgency-badge":固定的CSS类名,定义基础样式(内边距、圆角等) -->
|
||||
<span t-if="isVisible" t-att-class="urgencyClass" class="urgency-badge">急</span> <!-- 这里的"急"是实际显示的文字内容 -->
|
||||
</t>
|
||||
</templates>
|
||||
@@ -92,6 +92,8 @@
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="delete_record" type="object" string="删除" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="action_update_history_end_time" type="object" string="一键补全办结时间" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
</header>
|
||||
<field name="code"/>
|
||||
<field name="workflow_id" string="审批类型"/>
|
||||
@@ -140,6 +142,8 @@
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="delete_record" type="object" string="删除" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="action_update_history_end_time" type="object" string="一键补全办结时间" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
</header>
|
||||
<field name="code"/>
|
||||
<field name="workflow_id" string="审批类型"/>
|
||||
@@ -234,8 +238,11 @@
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="delete_record" type="object" string="删除" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="action_update_history_end_time" type="object" string="一键补全办结时间" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
</header>
|
||||
<field name="priority" optional="show" widget="priority" nolabel="1"/>
|
||||
<field name="urgency_level" column_invisible="1"/>
|
||||
<field name="urgency_level" widget="urgency_level_badge" nolabel="1" optional="show"/>
|
||||
<field name="code"/>
|
||||
<field name="workflow_id" string="审批类型"/>
|
||||
<field name="name"/>
|
||||
@@ -243,12 +250,12 @@
|
||||
decoration-danger="approve_state == 'end'" decoration-success="approve_state == 'pending'"/>
|
||||
<field name="create_uid"/>
|
||||
<field name="employee_ids" widget="many2many_tags" string="当前经办人" class="list_ids_width"/>
|
||||
<field name="soong_state"/>
|
||||
<field name="node_update_time" string="到达时间" optional="show"/>
|
||||
<field name="soong_state"/><field name="node_update_time" string="到达时间" optional="show"/>
|
||||
<field name="is_manager" column_invisible="1"/>
|
||||
<field name="is_unlink" column_invisible="1"/>
|
||||
<field name="is_log2" column_invisible="1"/>
|
||||
<button name="delete_record" type="object" string="删除" class="btn-primary" confirm="你确定要删除吗?"
|
||||
<button name="delete_record" type="object" string="删除" class="btn-primary"
|
||||
confirm="你确定要删除吗?"
|
||||
invisible="not is_unlink"/>
|
||||
<button name="greater_record" type="object" string="更多" class="btn-primary" invisible="not is_log2"/>
|
||||
<button name="reminders_record" type="object" string="催办" class="btn-primary"
|
||||
@@ -272,8 +279,11 @@
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="delete_record" type="object" string="删除" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="action_update_history_end_time" type="object" string="一键补全办结时间" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
</header>
|
||||
<field name="priority" optional="show" widget="priority" nolabel="1"/>
|
||||
<field name="urgency_level" column_invisible="1"/>
|
||||
<field name="urgency_level" widget="urgency_level_badge" nolabel="1" optional="show"/>
|
||||
<field name="code"/>
|
||||
<field name="workflow_id" string="审批类型"/>
|
||||
<field name="name"/>
|
||||
@@ -328,8 +338,11 @@
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="delete_record" type="object" string="删除" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
<button name="action_update_history_end_time" type="object" string="一键补全办结时间" class="oe_highlight"
|
||||
groups="soong_workflow.group_soong_workflow_manager"/>
|
||||
</header>
|
||||
<field name="priority" optional="show" widget="priority" nolabel="1"/>
|
||||
<field name="urgency_level" column_invisible="1"/>
|
||||
<field name="urgency_level" widget="urgency_level_badge" nolabel="1" optional="show"/>
|
||||
<field name="code"/>
|
||||
<field name="workflow_id" string="审批类型"/>
|
||||
<field name="name"/>
|
||||
@@ -351,7 +364,7 @@
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_kanban_card oe_kanban_global_click">
|
||||
<div class="oe_kanban_details">
|
||||
<div class="o_kanban_record_top mb-0 o_kanban_soong_wkf_record">
|
||||
<div class="o_kanban_record_top mb-0">
|
||||
<div class="o_kanban_record_headings">
|
||||
<strong class="o_kanban_record_title">
|
||||
<field name="name"/>
|
||||
@@ -410,7 +423,8 @@
|
||||
<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">{'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}
|
||||
<field name="context">{'header_search_default_approve_state': 1, 'header_search_default_to_do':1,
|
||||
'check_employee': 1}
|
||||
</field>
|
||||
<field name="domain">[('is_to_do', '=', True)]</field>
|
||||
<field name="search_view_id" ref="soong_workflow_record_search1"/>
|
||||
@@ -425,7 +439,7 @@
|
||||
'check_employee': 1}
|
||||
</field>
|
||||
<field name="domain">[('users_ids', 'in', uid), ('reclaim_state', '=', False), ('soong_state', 'in',
|
||||
['done', 'active'])]
|
||||
['done', 'active']), ('is_company', '=', True)]
|
||||
</field>
|
||||
<field name="search_view_id" ref="soong_workflow_record_search1"/>
|
||||
<field name="view_id" ref="soong_workflow_record_done_tree"/>
|
||||
@@ -490,6 +504,14 @@
|
||||
<field name="code">action = model.delete_record()</field>
|
||||
<field name="groups_id" eval="[(4, ref('base.group_system'))]"/>
|
||||
</record>
|
||||
<record id="action_update_history_end_time" model="ir.actions.server">
|
||||
<field name="name">一键补全办结时间</field>
|
||||
<field name="model_id" ref="soong_workflow.model_soong_workflow_record"/>
|
||||
<field name="binding_model_id" ref="soong_workflow.model_soong_workflow_record"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.action_update_history_end_time()</field>
|
||||
<field name="groups_id" eval="[(4, ref('base.group_system'))]"/>
|
||||
</record>
|
||||
<record id="action_admin_delete_end" model="ir.actions.server">
|
||||
<field name="name">管理员强制结束</field>
|
||||
<field name="model_id" ref="soong_workflow.model_soong_workflow_record"/>
|
||||
|
||||
@@ -638,7 +638,7 @@
|
||||
<field name="name">vacation.over.line.overtime.tree</field>
|
||||
<field name="model">vacation.over.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="加班情况" editable="bottom">
|
||||
<tree string="加班明细" editable="bottom">
|
||||
<field name="overtime_name"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
|
||||
@@ -360,7 +360,7 @@ class YuthonHrEmployee(models.Model):
|
||||
eighty_percent_items = [
|
||||
'基本工资',
|
||||
'职级工资',
|
||||
'预发绩效奖金'
|
||||
'月绩效奖金'
|
||||
]
|
||||
full_amount_items = [
|
||||
'通讯补贴',
|
||||
|
||||
@@ -9,7 +9,7 @@ class CurrentReceivableRentReport(models.Model):
|
||||
@api.model
|
||||
def get_current_receivable_rent_report(self, params):
|
||||
"""
|
||||
当期应收-租金:
|
||||
当期应收:
|
||||
- 过滤应收日期区间
|
||||
- 默认管理类型包含“租”,可通过 management_type_id 精确指定
|
||||
- 含税金额:original_amount
|
||||
@@ -50,32 +50,39 @@ class CurrentReceivableRentReport(models.Model):
|
||||
|
||||
if management_type_id:
|
||||
domain.append(('management_type_id', '=', management_type_id))
|
||||
else:
|
||||
rent_types = self.env['yuthon.management.type'].search([('name', 'ilike', '租')])
|
||||
if rent_types:
|
||||
domain.append(('management_type_id', 'in', rent_types.ids))
|
||||
# 删除默认过滤,显示所有类型
|
||||
|
||||
receivables = self.search(domain, limit=3000, order="due_date asc")
|
||||
receivables = self.search(domain, order="due_date asc")
|
||||
|
||||
rows = []
|
||||
total_amount = 0.0
|
||||
total_amount_nt = 0.0
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {'amount': 0, 'amount_nt': 0}}
|
||||
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amt = rec.original_amount or 0.0
|
||||
discount = rec.discount_amount or 0.0
|
||||
# 实际应收 = 原始金额 - 减免金额
|
||||
actual_amt = amt - discount
|
||||
tax_rate = rec.tax or 0.0
|
||||
amt_nt = amt / (1 + tax_rate / 100) if tax_rate else amt
|
||||
total_amount += amt
|
||||
total_amount_nt += amt_nt
|
||||
actual_amt_nt = actual_amt / (1 + tax_rate / 100) if tax_rate else actual_amt
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0, 'amount_nt': 0.0}
|
||||
type_totals[type_name]['amount'] += actual_amt
|
||||
type_totals[type_name]['amount_nt'] += actual_amt_nt
|
||||
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"应收开始": rec.due_date.strftime("%Y-%m-%d") if rec.due_date else "",
|
||||
"应收结束": rec.due_date_end.strftime("%Y-%m-%d") if rec.due_date_end else "",
|
||||
"承租方名称": rec.lessee_id.name if rec.lessee_id else "",
|
||||
"金额(含税)": round(amt, 2),
|
||||
"原始金额": round(amt, 2),
|
||||
"减免金额": round(discount, 2) if discount else "",
|
||||
"实际金额(含税)": round(actual_amt, 2),
|
||||
"税率": tax_rate,
|
||||
"金额(不含税)": round(amt_nt, 2),
|
||||
"实际金额(不含税)": round(actual_amt_nt, 2),
|
||||
"物业名称": rec.property_name or "",
|
||||
"产权证": rec.title_deed or "",
|
||||
"合同编号": rec.contract_id.contract_code if rec.contract_id else "",
|
||||
@@ -83,21 +90,40 @@ class CurrentReceivableRentReport(models.Model):
|
||||
"acc_type": rec.acc_type if rec.acc_type else False,
|
||||
})
|
||||
|
||||
# 返回字典格式,包含数据行和合计行
|
||||
# 构造合计数据:将各分类合计作为独立的统计数据返回
|
||||
summary_stats = []
|
||||
total_all_amount = 0.0
|
||||
total_all_amount_nt = 0.0
|
||||
|
||||
# 按管理类型名称排序
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
total_all_amount += totals['amount']
|
||||
total_all_amount_nt += totals['amount_nt']
|
||||
summary_stats.append({
|
||||
'name': type_name,
|
||||
'amount': round(totals['amount'], 2),
|
||||
'amount_nt': round(totals['amount_nt'], 2)
|
||||
})
|
||||
|
||||
# 返回字典格式,包含数据行、简化的表格合计行、独立的统计卡片数据
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": "",
|
||||
"应收开始": False,
|
||||
"应收结束": False,
|
||||
"承租方名称": "合计:",
|
||||
"金额(含税)": round(total_amount, 2),
|
||||
"应收开始": "",
|
||||
"应收结束": "",
|
||||
"承租方名称": "总合计:",
|
||||
"原始金额": "",
|
||||
"减免金额": "",
|
||||
"实际金额(含税)": round(total_all_amount, 2),
|
||||
"税率": "",
|
||||
"金额(不含税)": round(total_amount_nt, 2),
|
||||
"物业名称": False,
|
||||
"产权证": False,
|
||||
"合同编号": False,
|
||||
"管理员": False,
|
||||
}
|
||||
"实际金额(不含税)": round(total_all_amount_nt, 2),
|
||||
"物业名称": "",
|
||||
"产权证": "",
|
||||
"合同编号": "",
|
||||
"管理员": "",
|
||||
},
|
||||
"stats": summary_stats # 新增统计卡片数据
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ class ReceivableReport extends Component {
|
||||
{'name': '自有', 'value': 'self'},
|
||||
{'name': '代管', 'value': 'agency'}
|
||||
],
|
||||
domainUsers: []
|
||||
domainUsers: [],
|
||||
stats: [] // 新增统计数据
|
||||
});
|
||||
|
||||
this.config = this.props.action.context.report_config || {};
|
||||
@@ -50,6 +51,11 @@ class ReceivableReport extends Component {
|
||||
theme: agGrid.themeMaterial,
|
||||
columnDefs: this.config.columns || [],
|
||||
rowData: [],
|
||||
rowClassRules: {
|
||||
'ag-row-new-rent': function(params) {
|
||||
return params.data && params.data.acc_type === 'new';
|
||||
}
|
||||
},
|
||||
sideBar: {
|
||||
toolPanels: [
|
||||
{
|
||||
@@ -224,10 +230,15 @@ class ReceivableReport extends Component {
|
||||
if (result && typeof result === 'object' && result.rows && result.summary) {
|
||||
// 新格式:分离数据行和合计行
|
||||
this.grid.setGridOption('rowData', result.rows);
|
||||
this.grid.setGridOption('pinnedBottomRowData', [result.summary]);
|
||||
// summary可能是单个对象或数组
|
||||
const summaryData = Array.isArray(result.summary) ? result.summary : [result.summary];
|
||||
this.grid.setGridOption('pinnedBottomRowData', summaryData);
|
||||
// 更新统计卡片数据
|
||||
this.state.stats = result.stats || [];
|
||||
} else {
|
||||
// 兼容旧格式:数组
|
||||
this.grid.setGridOption('rowData', result);
|
||||
this.state.stats = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 统计卡片区域 -->
|
||||
<div class="card mb-2" t-if="state.stats and state.stats.length">
|
||||
<div class="card-body py-2">
|
||||
<div class="row g-2">
|
||||
<div class="col-auto" t-foreach="state.stats" t-as="stat" t-key="stat.name">
|
||||
<div class="badge bg-light text-dark p-2" style="font-size: 0.9rem; background-color: #d1ecf1 !important; border: 1px solid #bee5eb;">
|
||||
<strong t-esc="stat.name"/>: <t t-esc="stat.amount"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ag-grid 表格区域 -->
|
||||
<div class="row flex-grow-1">
|
||||
<div class="col-12 h-100">
|
||||
|
||||
@@ -28,4 +28,11 @@
|
||||
/* 下拉框placeholder样式 */
|
||||
#formview_default_conditions option[value=""] {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* 新租记录整行样式 */
|
||||
.ag-row-new-rent {
|
||||
background-color: #d4edda !important;
|
||||
color: #155724 !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -12,18 +12,19 @@
|
||||
"method": "get_current_receivable_rent_report",
|
||||
"columns": [
|
||||
{"headerName": "序号", "field": "序号", "flex": 0.6, "valueFormatter": "params.value === false || params.value === null || params.value === undefined || params.value === 'false' ? '' : params.value"},
|
||||
{"headerName": "应收开始", "field": "应收开始", "flex": 1.2},
|
||||
{"headerName": "应收结束", "field": "应收结束", "flex": 1.2},
|
||||
{"headerName": "应收开始", "field": "应收开始", "flex": 1},
|
||||
{"headerName": "应收结束", "field": "应收结束", "flex": 1},
|
||||
{"headerName": "承租方名称", "field": "承租方名称", "flex": 1.6},
|
||||
{"headerName": "金额(含税)", "field": "金额(含税)", "flex": 1, "type": "number"},
|
||||
{"headerName": "税率", "field": "税率", "flex": 0.8, "valueFormatter": "params.value === false || params.value === null || params.value === undefined || params.value === 'false' ? '' : params.value"},
|
||||
{"headerName": "金额(不含税)", "field": "金额(不含税)", "flex": 1, "type": "number"},
|
||||
{"headerName": "原始金额", "field": "原始金额", "flex": 0.9, "type": "number", "valueFormatter": "params.value === '' || params.value === null || params.value === undefined ? '' : params.value"},
|
||||
{"headerName": "减免金额", "field": "减免金额", "flex": 0.9, "type": "number", "valueFormatter": "params.value === '' || params.value === null || params.value === undefined ? '' : params.value"},
|
||||
{"headerName": "实际金额(含税)", "field": "实际金额(含税)", "flex": 1.1, "type": "number"},
|
||||
{"headerName": "税率", "field": "税率", "flex": 0.6, "valueFormatter": "params.value === false || params.value === null || params.value === undefined || params.value === 'false' || params.value === '' ? '' : params.value"},
|
||||
{"headerName": "实际金额(不含税)", "field": "实际金额(不含税)", "flex": 1.1, "type": "number"},
|
||||
{"headerName": "物业名称", "field": "物业名称", "flex": 2},
|
||||
{"headerName": "产权证", "field": "产权证", "flex": 1.2},
|
||||
{"headerName": "合同编号", "field": "合同编号", "flex": 1.2},
|
||||
{"headerName": "管理员", "field": "管理员", "flex": 1}
|
||||
],
|
||||
"getRowStyle": "function(params) { if (params.data.acc_type === 'new') { return { color: '#28a745' }; } return null; }"
|
||||
}
|
||||
}
|
||||
</field>
|
||||
@@ -31,7 +32,7 @@
|
||||
|
||||
<menuitem
|
||||
id="menu_current_receivable_rent_report"
|
||||
name="当期应收-租金"
|
||||
name="当期应收"
|
||||
parent="yuthon_property_approval.property_approval_report_menu"
|
||||
action="action_current_receivable_rent_report"
|
||||
sequence="19"
|
||||
|
||||
@@ -25,7 +25,7 @@ class HrPayrollStructure(models.Model):
|
||||
position_salary = fields.Monetary(string="岗位工资", currency_field="currency_id")
|
||||
position_subsidy = fields.Monetary(string="岗位补贴", currency_field="currency_id")
|
||||
integrated_subsidy = fields.Monetary(string="综合补贴", currency_field="currency_id")
|
||||
advance_performance_bonuses = fields.Monetary(string="预发绩效奖金", currency_field="currency_id")
|
||||
advance_performance_bonuses = fields.Monetary(string="月绩效奖金", currency_field="currency_id")
|
||||
renk_log_ids = fields.One2many("rank.log.line", "structure_id", string="职级日志明细行")
|
||||
|
||||
@api.depends('create_time', 'end_time')
|
||||
@@ -108,7 +108,7 @@ class HrPayrollStructure(models.Model):
|
||||
|
||||
@api.onchange('advance_performance_bonuses')
|
||||
def _onchange_advance_performance_bonuses(self):
|
||||
self._handle_salary_rule('预发绩效奖金', self.advance_performance_bonuses)
|
||||
self._handle_salary_rule('月绩效奖金', self.advance_performance_bonuses)
|
||||
|
||||
def open_record(self):
|
||||
return {
|
||||
@@ -127,7 +127,7 @@ class HrPayrollStructure(models.Model):
|
||||
'rank_salary': '职级工资',
|
||||
'communication_subsidy': '通讯补贴',
|
||||
'position_salary': '岗位工资',
|
||||
'advance_performance_bonuses': '预发绩效奖金' # 补充新增字段
|
||||
'advance_performance_bonuses': '月绩效奖金' # 补充新增字段
|
||||
}
|
||||
for record in self:
|
||||
for field, name in field_mapping.items():
|
||||
@@ -182,7 +182,7 @@ class HrPayrollStructure(models.Model):
|
||||
'天河粮储': {
|
||||
'基本工资': 'base_salary',
|
||||
'职级工资': 'rank_salary',
|
||||
'预发绩效奖金': 'advance_performance_bonuses'
|
||||
'月绩效奖金': 'advance_performance_bonuses'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ class RankLogLine(models.Model):
|
||||
rank_salary = fields.Float(string="职级工资")
|
||||
communication_subsidy = fields.Float(string="通讯补贴")
|
||||
position_salary = fields.Float(string="岗位工资")
|
||||
advance_performance_bonuses = fields.Float(string="预发绩效奖金")
|
||||
advance_performance_bonuses = fields.Float(string="月绩效奖金")
|
||||
effective_date = fields.Date(string="生效日期")
|
||||
lapse_date = fields.Date(string="失效日期")
|
||||
is_enable = fields.Boolean(string="启用")
|
||||
|
||||
@@ -24,7 +24,7 @@ class InheritHrPayslip(models.Model):
|
||||
identification_id = fields.Char(string='证件号码', related='employee_id.identification_id', store=True)
|
||||
card_type = fields.Char(string='证件类型', store=True, default="居民身份证")
|
||||
salary_group_id = fields.Many2one('yuthon.salary.group', string="工资组", store=True, index=True)
|
||||
performance_bonuses = fields.Float(string='预发绩效奖金', compute='_compute_salary', store=True)
|
||||
performance_bonuses = fields.Float(string='月绩效', compute='_compute_salary', store=True)
|
||||
full_attendance_award = fields.Float(string='全勤奖', compute='_compute_salary', store=True)
|
||||
commuting_allowance = fields.Float(string='通信补贴', compute='_compute_salary', store=True)
|
||||
position_subsidy = fields.Monetary(string="岗位补贴", compute="_compute_salary", store=True)
|
||||
@@ -503,7 +503,7 @@ class InheritHrPayslip(models.Model):
|
||||
rec.position_salary = line.total
|
||||
if line.name == '基本工资':
|
||||
rec.base_salary = line.total
|
||||
if line.name == '预发绩效奖金':
|
||||
if line.name == '月绩效奖金':
|
||||
rec.performance_bonuses = line.total
|
||||
if line.name == '工龄工资':
|
||||
rec.seniority_salary = line.total
|
||||
|
||||
@@ -31,7 +31,7 @@ class YuthonSalaryActive(models.Model):
|
||||
select_year = fields.Selection(selection=[(str(i), str(i)) for i in range(2024, 2040)], string='年份')
|
||||
basic_salary = fields.Float(string='基本工资')
|
||||
rank_salary = fields.Float(string='职级工资')
|
||||
pre_performance_bonus = fields.Float(string='预发绩效奖金')
|
||||
pre_performance_bonus = fields.Float(string='月绩效')
|
||||
post_salary = fields.Float(string='岗位工资')
|
||||
communication_subsidy = fields.Float(string='通讯补贴')
|
||||
seniority_wage = fields.Float(string='工龄工资')
|
||||
|
||||
@@ -243,7 +243,7 @@ class SalaryComputeWizard(models.Model):
|
||||
'职级工资': 'rank_salary', # 0.8
|
||||
'岗位工资': 'position_salary',
|
||||
'全勤奖': 'full_attendance_award',
|
||||
'预发绩效奖金': 'performance_bonuses', # 0.8
|
||||
'月绩效奖金': 'performance_bonuses', # 0.8
|
||||
'通讯补贴': 'commuting_allowance',
|
||||
'工龄工资': 'seniority_salary',
|
||||
'工会会费': 'union_dues',
|
||||
|
||||
@@ -124,7 +124,7 @@ class SalaryPrintWizard(models.Model):
|
||||
'基本工资',
|
||||
'职级工资',
|
||||
'岗位工资',
|
||||
'预发绩效奖金',
|
||||
'月绩效奖金',
|
||||
'通信补贴',
|
||||
'工龄工资',
|
||||
'全勤奖',
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<field name="work_end" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="users_id" options="{'no_create': True}"/>
|
||||
<field name="type_stamp_ids" widget="many2many_tags" options="{'no_create': True, 'no_open': True}}"/>
|
||||
<field name="type_stamp_ids" widget="many2many_tags" options="{'no_create': True, 'no_open': True}" context="{'search_default_group_by_scope': 1, 'search_default_filter_effective': 1}"/>
|
||||
<field name="approval_unit"/>
|
||||
<field name="remake"/>
|
||||
<field name="document_ids" widget="preview_many2many"/>
|
||||
|
||||
@@ -43,10 +43,26 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_seals_type_setting_search" model="ir.ui.view">
|
||||
<field name="name">seals.type.setting.search</field>
|
||||
<field name="model">seals.type.setting</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="用章类型">
|
||||
<field name="name"/>
|
||||
<field name="scope_setting_id"/>
|
||||
<filter string="已生效" name="filter_effective" domain="[('start_date', '<=', context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<group expand="1" string="分组">
|
||||
<filter string="用章范围" name="group_by_scope" context="{'group_by': 'scope_setting_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_seals_type_setting_action" model="ir.actions.act_window">
|
||||
<field name="name">用章类型</field>
|
||||
<field name="res_model">seals.type.setting</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="context">{'group_by': 'scope_setting_id'}</field>
|
||||
<field name="domain">[('start_date', '<=', context_today().strftime('%Y-%m-%d'))]</field>
|
||||
</record>
|
||||
<record id="view_seals_scope_setting_tree" model="ir.ui.view">
|
||||
<field name="name">seals.scope.setting.tree</field>
|
||||
|
||||
Reference in New Issue
Block a user