File size: 7,994 Bytes
8f25013
463287e
 
a09a188
463287e
8f25013
463287e
d162a62
 
463287e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f25013
463287e
 
 
 
 
 
 
8f25013
463287e
8f25013
a09a188
463287e
 
8f25013
463287e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f25013
463287e
 
a09a188
463287e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f25013
463287e
 
 
 
 
 
 
8f25013
463287e
 
8f25013
463287e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f25013
463287e
 
8f25013
463287e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f25013
463287e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import streamlit as st
from typing import Dict, Optional, List

from config import get_chart_theme, DESIGN_SYSTEM, get_translation

@st.cache_data
def get_material_stats(df: pd.DataFrame) -> Dict:
    stats = {}
    total = df['weight_kg'].sum()
    total_work_days = df['date'].nunique()
    
    for material in df['material_type'].unique():
        data = df[df['material_type'] == material]
        work_days = data['date'].nunique()
        daily_avg = data.groupby('date')['weight_kg'].sum().mean()
        
        stats[material] = {
            'total': data['weight_kg'].sum(),
            'percentage': (data['weight_kg'].sum() / total) * 100,
            'daily_avg': daily_avg,
            'work_days': work_days,
            'records': len(data)
        }
    
    stats['_total_'] = {
        'total': total,
        'percentage': 100.0,
        'daily_avg': df.groupby('date')['weight_kg'].sum().mean(),
        'work_days': total_work_days,
        'records': len(df)
    }
    
    return stats

@st.cache_data
def detect_outliers(df: pd.DataFrame) -> Dict:
    outliers = {}
    
    for material in df['material_type'].unique():
        material_data = df[df['material_type'] == material]
        data = material_data['weight_kg']
        
        Q1, Q3 = data.quantile(0.25), data.quantile(0.75)
        IQR = Q3 - Q1
        lower, upper = Q1 - 1.5 * IQR, Q3 + 1.5 * IQR
        
        outlier_mask = (data < lower) | (data > upper)
        outlier_dates = material_data[outlier_mask]['date'].dt.strftime('%Y-%m-%d').tolist()
        
        outliers[material] = {
            'count': len(outlier_dates),
            'range': f"{lower:.0f} - {upper:.0f} kg",
            'dates': outlier_dates
        }
    
    return outliers

def create_total_production_chart(df: pd.DataFrame, time_period: str = 'daily', lang: str = 'English'):
    t = get_translation(lang)
    
    if time_period == 'daily':
        grouped = df.groupby('date')['weight_kg'].sum().reset_index()
        fig = px.line(grouped, x='date', y='weight_kg', 
                     title=t.get('chart_total_production', 'Total Production Trend'),
                     labels={'weight_kg': t.get('label_weight', 'Weight (kg)'), 'date': t.get('label_date', 'Date')})
    elif time_period == 'weekly':
        df_copy = df.copy()
        df_copy['week'] = df_copy['date'].dt.isocalendar().week
        df_copy['year'] = df_copy['date'].dt.year
        grouped = df_copy.groupby(['year', 'week'])['weight_kg'].sum().reset_index()
        grouped['week_label'] = grouped['year'].astype(str) + '-W' + grouped['week'].astype(str)
        fig = px.bar(grouped, x='week_label', y='weight_kg',
                    title=t.get('chart_total_production_weekly', 'Total Production Trend (Weekly)'),
                    labels={'weight_kg': t.get('label_weight', 'Weight (kg)'), 'week_label': t.get('label_week', 'Week')})
    else:
        df_copy = df.copy()
        df_copy['month'] = df_copy['date'].dt.to_period('M')
        grouped = df_copy.groupby('month')['weight_kg'].sum().reset_index()
        grouped['month'] = grouped['month'].astype(str)
        fig = px.bar(grouped, x='month', y='weight_kg',
                    title=t.get('chart_total_production_monthly', 'Total Production Trend (Monthly)'),
                    labels={'weight_kg': t.get('label_weight', 'Weight (kg)'), 'month': t.get('label_month', 'Month')})
    
    fig.update_layout(**get_chart_theme()['layout'], height=400, showlegend=False)
    return fig

def create_materials_trend_chart(df: pd.DataFrame, time_period: str = 'daily', 
                                selected_materials: Optional[List[str]] = None, lang: str = 'English'):
    df_copy = df.copy()
    t = get_translation(lang)
    
    if selected_materials:
        df_copy = df_copy[df_copy['material_type'].isin(selected_materials)]
    
    if time_period == 'daily':
        grouped = df_copy.groupby(['date', 'material_type'])['weight_kg'].sum().reset_index()
        fig = px.line(grouped, x='date', y='weight_kg', color='material_type',
                     title=t.get('chart_materials_trends', 'Materials Production Trends'),
                     labels={'weight_kg': t.get('label_weight', 'Weight (kg)'), 
                             'date': t.get('label_date', 'Date'), 
                             'material_type': t.get('label_material', 'Material')})
    elif time_period == 'weekly':
        df_copy['week'] = df_copy['date'].dt.isocalendar().week
        df_copy['year'] = df_copy['date'].dt.year
        grouped = df_copy.groupby(['year', 'week', 'material_type'])['weight_kg'].sum().reset_index()
        grouped['week_label'] = grouped['year'].astype(str) + '-W' + grouped['week'].astype(str)
        fig = px.bar(grouped, x='week_label', y='weight_kg', color='material_type',
                    title=t.get('chart_materials_trends_weekly', 'Materials Production Trends (Weekly)'),
                    labels={'weight_kg': t.get('label_weight', 'Weight (kg)'), 
                            'week_label': t.get('label_week', 'Week'), 
                            'material_type': t.get('label_material', 'Material')})
    else:
        df_copy['month'] = df_copy['date'].dt.to_period('M')
        grouped = df_copy.groupby(['month', 'material_type'])['weight_kg'].sum().reset_index()
        grouped['month'] = grouped['month'].astype(str)
        fig = px.bar(grouped, x='month', y='weight_kg', color='material_type',
                    title=t.get('chart_materials_trends_monthly', 'Materials Production Trends (Monthly)'),
                    labels={'weight_kg': t.get('label_weight', 'Weight (kg)'), 
                            'month': t.get('label_month', 'Month'), 
                            'material_type': t.get('label_material', 'Material')})
    
    fig.update_layout(**get_chart_theme()['layout'], height=400)
    return fig

def create_shift_trend_chart(df: pd.DataFrame, time_period: str = 'daily', lang: str = 'English'):
    theme = get_chart_theme()
    t = get_translation(lang)
    
    if time_period == 'daily':
        grouped = df.groupby(['date', 'shift'])['weight_kg'].sum().reset_index()
        pivot_data = grouped.pivot(index='date', columns='shift', values='weight_kg').fillna(0)
        
        fig = go.Figure()
        
        if 'day' in pivot_data.columns:
            fig.add_trace(go.Bar(
                x=pivot_data.index, 
                y=pivot_data['day'], 
                name=t.get('label_day_shift', 'Day Shift'),
                marker_color=DESIGN_SYSTEM['colors']['warning'],
                text=pivot_data['day'].round(0), 
                textposition='inside'
            ))
        
        if 'night' in pivot_data.columns:
            fig.add_trace(go.Bar(
                x=pivot_data.index, 
                y=pivot_data['night'], 
                name=t.get('label_night_shift', 'Night Shift'),
                marker_color=DESIGN_SYSTEM['colors']['primary'],
                base=pivot_data['day'] if 'day' in pivot_data.columns else 0,
                text=pivot_data['night'].round(0), 
                textposition='inside'
            ))
        
        fig.update_layout(
            **theme['layout'],
            title=t.get('chart_shift_trends', 'Daily Shift Production Trends (Stacked)'),
            xaxis_title=t.get('label_date', 'Date'), 
            yaxis_title=t.get('label_weight', 'Weight (kg)'),
            barmode='stack', 
            height=400, 
            showlegend=True
        )
    else:
        grouped = df.groupby(['date', 'shift'])['weight_kg'].sum().reset_index()
        fig = px.bar(grouped, x='date', y='weight_kg', color='shift',
                    title=t.get('chart_shift_trends_period', f'{time_period.title()} Shift Production Trends'),
                    barmode='stack')
        fig.update_layout(**theme['layout'], height=400)
    
    return fig