零售贸易报告生成器

SKILL研究检索

原名 retail-trade-report-generator

研究检索 只读 许可证明确 OpenClaw
安装这个技能

retail-trade-report-generator 用于查找、检索和筛选相关信息,适合在 OpenClaw 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

累计安装 51,947 本周 2,122
GitHub 星标 1 仓库 retail-trade-report-generator
下载量 16,636 技能市场下载数
权限级别 只读 安装前请确认风险范围
许可证 许可证明确 MIT-0

安装

ClawHub 市场
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
openclaw skills install retail-trade-report-generator

技能档案

研究检索
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方wuminmin仓库 retail-trade-report-generator · 版本 1.0.0
宿主客户端OpenClaw技能可被这些客户端加载
安装方式ClawHub 市场安装包 wuminmin/retail-trade-report-generator
权限级别只读安装前请确认风险范围
许可证MIT-0许可证明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-05-01上游最后核验时间 · 数据更新 未标注
正文体量16.7 KBSKILL.md 原文大小,越大说明说明书写得越细

能做什么

5 项能力
上游给出的能力概览与适用场景
  • 按任务关键词查找相关 Skills
  • 展示可复制的安装命令
  • 保留来源站点、仓库和原始说明,方便继续核验
  • 补充不同宿主或平台的使用分布数据
  • 展示第三方安全扫描或审计结果
OpenClaw 用户查找和安装 Skill 时用户想查找某类 Agent Skill 时需要根据任务场景推荐可安装能力包时需要对比不同来源的安装命令和来源信息时

权限与风险

只读
装之前先读完这段

安装与使用指南

安装步骤

本站只展示命令,不托管安装包,也不自动执行。

怎么用

安装后应在对应宿主中按原始 README 的触发条件使用;当前草稿只做目录说明,具体调用方式由规则抽取,异常条目再复核。

SKILL.md 全文

16.7 KB
模型实际读到的说明书原文,来自技能仓库

Retail Trade Weekly Report Generator - Skill Documentation

Overview

This skill processes multiple weekly sales report Excel files to generate a consolidated Retail Trade Weekly Report with week-over-week (WoW) comparisons across different channels (DRP, DXS, License Store) and product types (Mobile Prepaid/Postpaid, FWA 4G/5G).

Purpose

  • Consolidate 12 Excel files (6 current week + 6 previous week) into a single comprehensive weekly report
  • Calculate Average Daily Acquisition (ADA) metrics by region and channel
  • Compute Week-over-Week (WoW) performance indicators
  • Generate formatted Excel output with charts and color-coded performance indicators

Input Requirements

Required Files (12 total)

Current Week (6 files):
1. DRP_Channel_Sales_Report_DRP_M_DD-M_DD.xlsx
2. DRP_Special_SIM_Monitor_Report_Daily_TECNO_M_DD-M_DD.xlsx
3. License_Store_Performance_Monitor_Report_LS_M_DD-M_DD.xlsx
4. DXS_Acquisition_Report_Mobile_Prepaid_M_DD-M_DD.xlsx
5. DXS_Acquisition_Report_Mobile_Postpaid_M_DD-M_DD.xlsx
6. DXS_Acquisition_Report_FWA_M_DD-M_DD.xlsx

Previous Week (6 files with earlier dates):
Same file types with earlier date ranges in filename

Store Mapping CSV

File containing Store Name to Region mapping with aliases support:

Store Name,Region,Aliases
SM Megamall,NCR,"Megamall|SM Mega|MEGAMALL"
...

Data Processing Logic

1. File Identification

  • Extract date ranges from filenames (format: M_DD-M_DD)
  • Auto-group into current week vs previous week based on date comparison
  • Validate all 12 required files are present

2. Data Extraction Rules

DRP Channel Sales Report

  • Header rows: Skip rows 0-7
  • Data rows: Start from row 8
  • Region field: Column 0 (AREA)
  • Key columns:
  • Column 1: MOBILE POSTPAID > TOTAL ACTIVATION
  • Column 5: MOBILE PREPAID > TOTAL ACTIVATION
  • Column 6: Double Data_Sum
  • Column 9: 4G WiFi 980 SIM_Sum (FWA 4G)
  • Column 10: Unli 5G WIFI 100Mbps Starter SIM_Sum (FWA 5G)
  • Column 11: 5G WiFi 4990 SIM_Sum (FWA 5G)

DRP TECNO Report

  • Header rows: Skip rows 0-6
  • Data rows: Start from row 7
  • Region field: Column 0 (Activation Area)
  • Key columns:
  • Column 1: CARMON Activation (CAMON 40)
  • Column 2: POVA Activation (POVA 7)
  • Column 3: Total Activation (TECNO ADA = CAMON 40 + POVA 7)

License Store Report

  • Header rows: Skip rows 0-7
  • Data rows: Start from row 8
  • Store field: Column 0 (Store Name) - Requires mapping to Region
  • Key columns:
  • Column 1: Mobile Prepaid
  • Column 3: Mobile Postpaid
  • Column 29 (AD): DITO Home Prepaid 4G WiFi 980 SIM (FWA 4G)
  • Need to find: Unli 5G WIFI 100Mbps Starter SIM (FWA 5G)
  • Need to find: 5G WiFi 4990 SIM (FWA 5G)

DXS Mobile Prepaid Report

  • Header rows: Skip rows 0-7
  • Data rows: Start from row 8
  • Store field: Column 0 (DXS Name) - Requires mapping to Region
  • Key column:
  • Column 4: Total

DXS Mobile Postpaid Report

  • Header rows: Skip rows 0-7
  • Data rows: Start from row 8
  • Store field: Column 0 (DXS Name) - Requires mapping to Region
  • Key column:
  • Column 12: Total

DXS FWA Report

  • Header rows: Skip rows 0-7
  • Data rows: Start from row 8
  • Store field: Column 0 (DXS Name) - Requires mapping to Region
  • Key columns:
  • Column 1: DITO Home Prepaid 4G WiFi 980 (FWA 4G)
  • Column 18: Total
  • FWA 5G calculation: Total (Col 18) - 4G (Col 1)

3. Store Name to Region Mapping

# Build mapping dictionary from CSV
store_mapping = {}
for row in mapping_csv:
    main_name = row['Store Name']
    region = row['Region']
    aliases = row['Aliases'].split('|') if row['Aliases'] else []

    # Add main name and all aliases to mapping
    store_mapping[main_name.upper()] = region
    for alias in aliases:
        store_mapping[alias.strip().upper()] = region

# Apply fuzzy matching for unmatched stores
def map_store_to_region(store_name):
    # Exact match (case-insensitive)
    if store_name.upper() in store_mapping:
        return store_mapping[store_name.upper()]

    # Fuzzy match using substring search
    for key in store_mapping:
        if key in store_name.upper() or store_name.upper() in key:
            return store_mapping[key]

    # Default to "Others" if no match
    return "Others"

4. Regional Aggregation

Standard Regions: NCR, SLZ, NLZ, CLZ, EVIS, WVIS, MIN, Others

For each product type and region:

# DRP data: Direct mapping (already by region)
DRP_ADA = drp_data[region][product_column]

# DXS data: Aggregate stores by region
DXS_ADA = sum(dxs_data[store][product_column] 
              for store in dxs_data 
              if map_store_to_region(store) == region)

# LS data: Aggregate stores by region
LS_ADA = sum(ls_data[store][product_column] 
             for store in ls_data 
             if map_store_to_region(store) == region)

# Total for region
RT_Total_ADA = DRP_ADA + DXS_ADA + LS_ADA

5. WoW Calculation

WoW = (current_week_value - previous_week_value) / previous_week_value

# Formatting rules:
# - Display as percentage (e.g., "21%", "-13%")
# - Round to nearest integer
# - Handle division by zero: display "-" if previous_week_value == 0
# - Handle cases where current = 0 and previous > 0: show "-100%"

6. Special Calculations

FWA 5G Components

# DRP FWA 5G
DRP_FWA_5G = Column_10 + Column_11

# DXS FWA 5G
DXS_FWA_5G = Total - Column_1_4G

# LS FWA 5G
LS_FWA_5G = Unli_5G_WIFI_100Mbps + WiFi_4990_SIM

TECNO ADA

TECNO_ADA = CAMON_40 + POVA_7

Output Format

Excel Structure

Single Sheet: "Weekly Report"

Sections:
1. Report Header (Rows 1-2)
- Title: "Retail Trade Weekly Report"
- Date ranges: "Last Week: [dates] | This Week: [dates]"

  1. Channel Summary (Rows 4-9)
    - Columns: Channel | Program name | This Week ADA | WoW | MoM
    - Rows: DRP BAU, DRP TECNO, License Store, DXS, RT Total

  2. Mobile Prepaid by Region (Rows 11-21)
    - Columns: Region | RT Total ADA | WoW | DXS ADA | WoW | LS ADA | WoW | DRP ADA | WoW
    - Rows: 8 regions + Total

  3. DRP Prepaid Program (Rows 23-33)
    - Columns: Region | Double Data ADA | WoW | TECNO ADA | WoW | CAMON 40 | WoW | POVA 7 | WoW
    - Rows: 8 regions + Total

  4. Mobile Postpaid by Region (Rows 35-45)
    - Same structure as Mobile Prepaid

  5. FWA 4G by Region (Rows 47-57)
    - Same structure as Mobile Prepaid

  6. FWA 5G by Region (Rows 59-69)
    - Same structure as Mobile Prepaid

Formatting Rules

Number Formatting

  • ADA values: Integer format with thousand separators (e.g., "1,876")
  • WoW percentages: Integer percentage (e.g., "21%", "-13%")
  • Small ADA values (< 10): Show 1 decimal place (e.g., "0.6", "2.9")

Color Coding

  • WoW Positive (>0%): Green text (#008000)
  • WoW Negative (<0%): Red text (#FF0000)
  • WoW Zero (0%): Black text
  • WoW N/A ("-"): Gray text (#808080)

Cell Styling

  • Headers: Bold, centered, light gray background (#F0F0F0)
  • Region names: Bold
  • Total rows: Bold, light blue background (#E6F2FF)
  • Borders: Thin borders around all data cells

Charts

Chart 1: Channel Performance Comparison
- Type: Clustered Column Chart
- Data: This Week ADA by Channel (DRP BAU, DRP TECNO, License Store, DXS)
- Position: Right side of Channel Summary section
- Size: 6 columns wide x 15 rows tall

Chart 2: Regional Mobile Prepaid Distribution
- Type: Stacked Column Chart
- Data: DRP ADA, DXS ADA, LS ADA by Region
- Position: Right side of Mobile Prepaid section
- Size: 6 columns wide x 15 rows tall

Chart 3: WoW Trend - Top 3 Regions
- Type: Line Chart with Markers
- Data: WoW % for top 3 regions by RT Total ADA
- Position: Below main tables
- Size: 12 columns wide x 12 rows tall

Error Handling

Missing Files

if len(current_week_files) != 6:
    raise ValueError(f&quot;Expected 6 current week files, found {len(current_week_files)}&quot;)

if len(previous_week_files) != 6:
    raise ValueError(f&quot;Expected 6 previous week files, found {len(previous_week_files)}&quot;)

Unmapped Stores

unmapped_stores = []
for store in all_stores:
    if map_store_to_region(store) == &quot;Others&quot;:
        # Log warning but continue processing
        unmapped_stores.append(store)

if unmapped_stores:
    print(f&quot;Warning: {len(unmapped_stores)} stores mapped to &#x27;Others&#x27; region&quot;)

Data Quality Checks

# Check for negative values
if any_value &lt; 0:
    print(f&quot;Warning: Negative value found in {file}:{column}&quot;)

# Check for missing regions
expected_regions = {&quot;NCR&quot;, &quot;SLZ&quot;, &quot;NLZ&quot;, &quot;CLZ&quot;, &quot;EVIS&quot;, &quot;WVIS&quot;, &quot;MIN&quot;, &quot;Others&quot;}
missing_regions = expected_regions - set(actual_regions)
if missing_regions:
    print(f&quot;Warning: Missing regions: {missing_regions}&quot;)

Implementation Notes

Python Libraries

import pandas as pd
import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.chart import BarChart, LineChart, Reference
import re
from datetime import datetime

Key Functions

1. File Parser

def extract_date_from_filename(filename):
    &quot;&quot;&quot;Extract date range from filename like &#x27;Report_1_11-1_17.xlsx&#x27;&quot;&quot;&quot;
    pattern = r&#x27;_(\d+)_(\d+)-(\d+)_(\d+)\.xlsx&#x27;
    match = re.search(pattern, filename)
    if match:
        start_month, start_day, end_month, end_day = match.groups()
        return (int(start_month), int(start_day), int(end_month), int(end_day))
    return None

def identify_file_type(filename):
    &quot;&quot;&quot;Identify file type from filename&quot;&quot;&quot;
    if &#x27;DRP_Channel_Sales&#x27; in filename:
        return &#x27;DRP&#x27;
    elif &#x27;TECNO&#x27; in filename:
        return &#x27;TECNO&#x27;
    elif &#x27;License_Store&#x27; in filename:
        return &#x27;LS&#x27;
    elif &#x27;Mobile_Prepaid&#x27; in filename:
        return &#x27;DXS_Prepaid&#x27;
    elif &#x27;Mobile_Postpaid&#x27; in filename:
        return &#x27;DXS_Postpaid&#x27;
    elif &#x27;FWA&#x27; in filename:
        return &#x27;DXS_FWA&#x27;
    return &#x27;Unknown&#x27;

2. Data Extractor

def extract_drp_data(filepath):
    &quot;&quot;&quot;Extract DRP channel sales data&quot;&quot;&quot;
    df = pd.read_excel(filepath, sheet_name=&#x27;Sheet0&#x27;, header=None)

    # Find data start row (usually row 8)
    data_start = 8

    # Extract by region
    regions_data = {}
    for idx in range(data_start, len(df)):
        region = df.iloc[idx, 0]
        if pd.isna(region) or region == &#x27;Total&#x27;:
            continue

        regions_data[region] = {
            &#x27;mobile_postpaid&#x27;: df.iloc[idx, 1],
            &#x27;mobile_prepaid&#x27;: df.iloc[idx, 5],
            &#x27;double_data&#x27;: df.iloc[idx, 6],
            &#x27;fwa_4g&#x27;: df.iloc[idx, 9],
            &#x27;fwa_5g&#x27;: df.iloc[idx, 10] + df.iloc[idx, 11]
        }

    return regions_data

def extract_dxs_data(filepath, product_type):
    &quot;&quot;&quot;Extract DXS acquisition data&quot;&quot;&quot;
    df = pd.read_excel(filepath, sheet_name=&#x27;Sheet1&#x27;, header=None)

    # Determine column based on product type
    if product_type == &#x27;prepaid&#x27;:
        value_col = 4
    elif product_type == &#x27;postpaid&#x27;:
        value_col = 12
    elif product_type == &#x27;fwa&#x27;:
        return extract_dxs_fwa_data(df)

    stores_data = {}
    for idx in range(8, len(df)):
        store = df.iloc[idx, 0]
        if pd.isna(store) or store in [&#x27;Grand Total&#x27;, &#x27;-&#x27;]:
            continue

        value = df.iloc[idx, value_col]
        if pd.notna(value):
            stores_data[store] = value

    return stores_data

def extract_dxs_fwa_data(df):
    &quot;&quot;&quot;Extract FWA data with 4G/5G split&quot;&quot;&quot;
    stores_data = {}
    for idx in range(8, len(df)):
        store = df.iloc[idx, 0]
        if pd.isna(store) or store in [&#x27;Grand Total&#x27;, &#x27;-&#x27;]:
            continue

        fwa_4g = df.iloc[idx, 1] if pd.notna(df.iloc[idx, 1]) else 0
        total = df.iloc[idx, 18] if pd.notna(df.iloc[idx, 18]) else 0
        fwa_5g = total - fwa_4g

        stores_data[store] = {
            &#x27;fwa_4g&#x27;: fwa_4g,
            &#x27;fwa_5g&#x27;: fwa_5g
        }

    return stores_data

3. Region Aggregator

def aggregate_by_region(stores_data, mapping_dict, regions):
    &quot;&quot;&quot;Aggregate store data by region&quot;&quot;&quot;
    regional_totals = {region: 0 for region in regions}

    for store, value in stores_data.items():
        region = map_store_to_region(store, mapping_dict)
        if isinstance(value, dict):
            # Handle nested data (e.g., FWA with 4G/5G)
            for key in value:
                if key not in regional_totals:
                    regional_totals[key] = {region: 0 for region in regions}
                regional_totals[key][region] += value[key]
        else:
            regional_totals[region] += value

    return regional_totals

4. WoW Calculator

def calculate_wow(current, previous):
    &quot;&quot;&quot;Calculate week-over-week percentage change&quot;&quot;&quot;
    if previous == 0 or pd.isna(previous):
        return &quot;-&quot;

    if current == 0 or pd.isna(current):
        return &quot;-100%&quot;

    wow = ((current - previous) / previous) * 100
    return f&quot;{int(round(wow))}%&quot;

5. Excel Formatter

def apply_formatting(ws, start_row, start_col, end_row, end_col):
    &quot;&quot;&quot;Apply formatting to Excel worksheet&quot;&quot;&quot;
    # Define styles
    header_fill = PatternFill(start_color=&quot;F0F0F0&quot;, end_color=&quot;F0F0F0&quot;, fill_type=&quot;solid&quot;)
    total_fill = PatternFill(start_color=&quot;E6F2FF&quot;, end_color=&quot;E6F2FF&quot;, fill_type=&quot;solid&quot;)

    green_font = Font(color=&quot;008000&quot;)
    red_font = Font(color=&quot;FF0000&quot;)
    gray_font = Font(color=&quot;808080&quot;)
    bold_font = Font(bold=True)

    thin_border = Border(
        left=Side(style=&#x27;thin&#x27;),
        right=Side(style=&#x27;thin&#x27;),
        top=Side(style=&#x27;thin&#x27;),
        bottom=Side(style=&#x27;thin&#x27;)
    )

    # Apply to cells
    for row in ws.iter_rows(min_row=start_row, max_row=end_row, 
                            min_col=start_col, max_col=end_col):
        for cell in row:
            cell.border = thin_border

            # Color code WoW values
            if isinstance(cell.value, str) and &#x27;%&#x27; in cell.value:
                try:
                    pct_value = int(cell.value.replace(&#x27;%&#x27;, &#x27;&#x27;))
                    if pct_value &gt; 0:
                        cell.font = green_font
                    elif pct_value &lt; 0:
                        cell.font = red_font
                except:
                    if cell.value == &#x27;-&#x27;:
                        cell.font = gray_font

def add_chart(ws, chart_type, data_range, position, title):
    &quot;&quot;&quot;Add chart to worksheet&quot;&quot;&quot;
    if chart_type == &#x27;column&#x27;:
        chart = BarChart()
    elif chart_type == &#x27;line&#x27;:
        chart = LineChart()

    chart.title = title
    chart.style = 10
    chart.height = 10
    chart.width = 15

    data = Reference(ws, min_col=data_range[0], min_row=data_range[1],
                     max_col=data_range[2], max_row=data_range[3])
    chart.add_data(data, titles_from_data=True)

    ws.add_chart(chart, position)

Usage Example

from retail_trade_report_skill import generate_weekly_report

# Input files directory
input_dir = &quot;/mnt/user-data/uploads/&quot;

# Store mapping CSV
mapping_file = &quot;/mnt/user-data/uploads/store_mapping.csv&quot;

# Generate report
output_file = generate_weekly_report(
    input_dir=input_dir,
    mapping_csv=mapping_file,
    output_path=&quot;/mnt/user-data/outputs/Retail_Trade_Weekly_Report.xlsx&quot;
)

print(f&quot;Report generated: {output_file}&quot;)

Validation Checklist

Before finalizing output:
- [ ] All 12 input files identified and processed
- [ ] Date ranges correctly extracted and displayed
- [ ] All stores mapped to regions (log unmapped as "Others")
- [ ] All WoW calculations completed
- [ ] No negative ADA values (except in error logs)
- [ ] All formulas validated against sample data
- [ ] Charts render correctly
- [ ] Color coding applied to all WoW cells
- [ ] Total rows sum correctly
- [ ] Output file opens without errors

Performance Considerations

  • Expected processing time: 10-30 seconds for 12 files
  • Memory usage: ~50-100 MB
  • Large file handling: Files up to 10MB each supported
  • Concurrent processing: Process files in parallel where possible

Troubleshooting

Common Issues

Issue: "File not found" error
- Solution: Verify all 12 files are uploaded and filenames match expected pattern

Issue: Store name not mapping to region
- Solution: Check mapping CSV for typos, add aliases for common variations

Issue: WoW showing "N/A" for all values
- Solution: Verify previous week files are correctly identified (earlier dates)

Issue: Charts not displaying
- Solution: Check openpyxl version >= 3.0, verify chart data ranges

Issue: Negative ADA values
- Solution: Check source data for errors, verify column indices

Version History

  • v1.0 (2026-02-02): Initial skill creation
  • Support for 12-file weekly report generation
  • WoW calculations with color coding
  • Store-to-region mapping with aliases
  • Three chart types for visualization

安全信息

审计结论
未标注不代表已通过审计
安全审计VirusTotal、ClawScan、Static analysis第三方安全审计平台给出的结论

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-05-01。