要实现的效果如下图

原始数据如下图,此项目要对(分摊明细)字符串进行控制(切片等),相对麻烦一些

实现方法如下

选择脚本报表类型,过滤条件在写完代码后添加,如下图

脚本代码如下

# === 过滤条件获取 ===
# 从报表界面获取三个关键过滤参数用于后续查询
# 上图过滤条件的前提代码,一一对应
expense_claim_type = filters.get('expense_claim_type')
year = filters.get('year')
month = filters.get('month')


# === 员工金额统计模块 ===
# 目标:获取指定条件下的员工报销分配明细
# as_dict=True将结果转为字典格式方便操作
sql_emp_amount = f"""
SELECT
    tb2.empno, 
    tb2.employee_name,
    tb2.total_hours,
    tb2.amount 
FROM `tabExpense Allocation Doc` tb1 join `tabAllocation Item` tb2 on tb1.name=tb2.parent 
WHERE 
    tb1.expense_claim_type = '{expense_claim_type}' AND year = '{year}' AND month = '{month}' AND reverse=1
"""
emp_amount = frappe.db.sql(sql_emp_amount, as_dict=True)  
# 系统标准方法,查询前的f,用于动态查询,如 '{expense_claim_type}'

# === 出勤天数计算 ===
# 构建单独列
# 逻辑:为每个员工补充计算当月出勤天数
for i in emp_amount:
    i["qqq"]=0  # 初始化出勤天数字段
    a=i.empno
    sql_emp_amount1 = f"""
    SELECT DISTINCT
        tb2.from_time
    FROM `tabTimesheet` tb1 join `tabTimesheet Detail` tb2 on tb1.name=tb2.parent 
    WHERE
        month(tb2.from_time) = '{month}' AND tb1.employee = '{a}' AND  year(tb2.from_time) = '{year}'
    """
    emp_amount1 = frappe.db.sql(sql_emp_amount1, as_dict=True)
    
    i["qqq"]=len(emp_amount1)  # 存储考勤记录数


# === 动态列生成模块 ===
# 2.1 项目号统计
# 逻辑:从首个Expense Allocation Doc获取所有分配项目
# 注意:
doc_list = frappe.get_all('Expense Allocation Doc',filters={'expense_claim_type': expense_claim_type,'year': year,'month': month}) # 系统标准方法,用于筛选获取

# 字符串控制,提取所需
if len(doc_list) > 0:
    doc = frappe.get_doc('Expense Allocation Doc',doc_list[0].name)
    list_all = []
    for row in doc.allocation_item:
        # 解析分配明细字符串
        for i in row.allocation_detail.split(','):
            if len(i)>0:
                list_all.append(i.split('/')[0])  # 提取项目号部分
    list_result = set(list_all)  # 去重获得唯一项目号集合
    
    # 2.2 动态添加字段
    # 初始化所有项目相关字段为0
    # 注意:分两次添加项目工时列和项目金额列
    for i in emp_amount:
        for pro in list_result:
            i[pro] = 0  # 添加项目工时字段
    # 二次遍历添加金额字段
    for i in emp_amount:
        for pro in list_result:
            pro = pro+'金额'
            i[pro] = 0  # 添加项目金额字段
    
    
    # === 数据填充模块 ===
    # 3. 解析分配明细并填充数据
    # 流程:
    # 1. 提取原始分配数据 -> list0
    # 2. 展开分配明细 -> list1
    # 3. 分割明细项 -> list2(结构:[empno, 项目, 工时, 金额])
    list0 = []
    for row in doc.allocation_item:
        l = []
        l.append(row.empno)
        l.append(row.allocation_detail)
        list0.append(l)
    
    list1 = []
    for i in list0:
        for item in i[1].split(','):  # 拆分多个分配项
            l = []
            if len(item) > 0:
                l.append(i[0])  # empno
                l.append(item)  # 分配项字符串
                list1.append(l)
    
    list2 = []
    for i in list1:
        l = []
        l.append(i[0])  # empno
        for item in i[1].split('/'):  # 分割单个分配项
            l.append(item)
        list2.append(l)  # 结构:[empno, 项目, 工时, 金额]
    
    # 数据填充到emp_amount字典
    for i in list2:
        key_value = i[1]
        key_value_a = i[1]+'金额'
        for obj in emp_amount:
            if obj.empno == i[0]:  # 匹配员工
                obj[key_value] = i[2]  # 填充工时
                obj[key_value_a] = i[3]  # 填充金额
    
    
    # === 报表列配置 ===
    # 4. 动态构建报表列
    # 结构:
    # - 基础信息列
    # - 动态项目工时列
    # - 总金额列
    # - 动态项目金额列
    # 注意:
    # - 列顺序影响前端显示
    # - 金额列字段名需与数据字段名严格对应
    columns = [
        {
            "label": _("EmpNo"),
            "fieldtype": "Data",
            "fieldname": "empno",
            "width": 80
        },
        {
            "label": _("姓名"),
            "fieldtype": "Data",
            "fieldname": "employee_name",
            "width": 80
        },
         {
            "label": "出勤天数",
            "fieldtype": "Data",
            "fieldname": "qqq",
            "width": 88
        },
         {
            "label": _("Total Hours"),
            "fieldtype": "Currency",
            "fieldname": "total_hours",
            "width": 100
        },
    ]
    
    # 添加动态项目工时列
    for pro in list_result:
    	element = {"label": pro,"fieldtype": "Currency","fieldname": pro,"width": 108,}
    	columns.append(element)
    
    # 添加总金额列
    amounts1 = {
            "label": _("Amount"),
            "fieldtype": "Currency",
            "fieldname": "amount",
            "width": 100}
    columns.append(amounts1)
    
    # 添加动态项目金额列
    for pro in list_result:
        plement = {"label": pro,"fieldtype": "Currency","fieldname": pro+'金额',"width": 108,}
        columns.append(plement)
    
    
    # === 最终输出 ===
    # 系统标准输出格式
    # 注意:columns需要与emp_amount中的字段完全匹配
    data = columns, emp_amount

 代码仅供参考,有许多可以优化的地方

Logo

永洪科技,致力于打造全球领先的数据技术厂商,具备从数据应用方案咨询、BI、AIGC智能分析、数字孪生、数据资产、数据治理、数据实施的端到端大数据价值服务能力。

更多推荐