cormort commited on
Commit
d620b26
·
verified ·
1 Parent(s): fdb18a5

Update src/app.py

Browse files
Files changed (1) hide show
  1. src/app.py +63 -69
src/app.py CHANGED
@@ -1,36 +1,39 @@
1
  import streamlit as st
2
  import pandas as pd
3
  import plotly.graph_objects as go
 
4
  import sqlite3
5
  import datetime
6
  from database import init_db, load_full_project_example, clear_to_actual, backup_current_project, DB_PATH
7
 
8
- # 初始化
9
  init_db()
10
- st.set_page_config(page_title="SPV 財務整合系統", layout="wide")
 
11
 
12
- # --- 側邊欄 ---
13
  with st.sidebar:
14
- st.header("🏗️ 專案管理")
15
- if st.button("🆕 切換至原實際專案 (空白)", use_container_width=True):
 
 
 
 
16
  backup_current_project()
17
  clear_to_actual()
18
- st.success("已重置為空白實際專案")
19
  st.rerun()
20
-
21
- if st.button("💡 載入全生命週期範例", use_container_width=True):
22
- load_full_project_example(100000)
23
- st.success("範例載入成功")
24
  st.rerun()
25
 
26
  st.divider()
27
- st.subheader("➕ 手動增加自訂目")
28
- with st.form("add_custom_item"):
29
  f_month = st.number_input("月份", min_value=1, value=1)
30
- f_name = st.text_input("項目名稱 (如:代銷費、增值稅)")
31
- f_type = st.selectbox("性質", ["支出", "收入"])
32
  f_amt = st.number_input("金額 (萬)", min_value=0.0)
33
- if st.form_submit_button("確認新增項目"):
34
  if f_name:
35
  conn = sqlite3.connect(DB_PATH)
36
  conn.execute("INSERT OR REPLACE INTO finance_transactions VALUES (?, '實際', ?, ?, ?)",
@@ -39,63 +42,54 @@ with st.sidebar:
39
  conn.close()
40
  st.rerun()
41
 
42
- # --- 主介面 ---
43
- tabs = st.tabs(["📊 損益分析", "💰 現金流流水帳", "🏗️ 工程排程"])
44
 
45
- # --- Tab 2: 現金流總表 (修復 SQL 報錯) ---
46
- with tabs[1]:
47
- st.subheader("📅 動態現金流流水帳")
48
  conn = sqlite3.connect(DB_PATH)
49
- # 修正:使用正確的資料表名稱 finance_transactions
50
- df = pd.read_sql_query("SELECT * FROM finance_transactions WHERE 類型='實際' ORDER BY 月份 ASC", conn)
51
  conn.close()
52
-
53
  if not df.empty:
54
- # 動態轉置表格,列出所有自訂科目
55
- pivot_df = df.pivot_table(index='月份', columns='科目名稱', values='金額', fill_value=0).reset_index()
56
-
57
- # 區分收支色彩
58
- inc_list = df[df['科目性質']=='收入']['科目名稱'].unique()
59
- exp_list = df[df['科目性質']=='支出']['科目名稱'].unique()
60
 
61
- st.dataframe(pivot_df.style.format(precision=0)
62
- .applymap(lambda x: 'color: #228B22; font-weight: bold', subset=[c for c in inc_list if c in pivot_df.columns])
63
- .applymap(lambda x: 'color: #DC143C', subset=[c for c in exp_list if c in pivot_df.columns]),
64
- use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
65
  else:
66
- st.info("目前尚無資料,請利用側邊欄新增項目。")
67
 
68
- # --- Tab 1: 損益分析 (汇总自訂科目) ---
69
- with tabs[0]:
 
70
  if not df.empty:
71
- total_inc = df[df['科目性質']=='收入']['金額'].sum()
72
- total_exp = df[df['科目性質']=='支出']['金額'].sum()
73
-
74
- col1, col2, col3 = st.columns(3)
75
- col1.metric("總流入金額", f"{total_inc:,.0f} 萬")
76
- col2.metric("總流出金額", f"{total_exp:,.0f} 萬")
77
- col3.metric("專案剩餘毛利", f"{(total_inc - total_exp):,.0f} 萬")
78
 
79
- # 成本結構圖 (自動包含所有手動增加的支出項)
80
- exp_summary = df[df['科目性質']=='支出'].groupby('科目名稱')['金額'].sum()
81
- fig = go.Figure(data=[go.Pie(labels=exp_summary.index, values=exp_summary.values, hole=.4)])
82
- fig.update_layout(title="自訂項目支出占比分析")
83
- st.plotly_chart(fig, use_container_width=True)
84
-
85
- # --- Tab 2: 現金流總表 (色系區分) ---
86
- with tabs[1]:
87
- conn = sqlite3.connect(DB_PATH)
88
- df_act = pd.read_sql_query("SELECT * FROM finance_data WHERE 類型='實際' ORDER BY 月份 ASC", conn)
89
- conn.close()
90
- if not df_act.empty:
91
- num_cols = ['工程款', '貸款撥入', '利息支出', '貸款還本', '預售收入', '代銷費用']
92
- st.subheader("📅 現金流明細 (🟢 流入 / 🔴 流出)")
93
- st.dataframe(df_act.style.format(subset=num_cols, formatter="{:,.0f}")
94
- .applymap(lambda x: 'color: #228B22; font-weight: bold', subset=['貸款撥入', '預售收入'])
95
- .applymap(lambda x: 'color: #DC143C', subset=['工程款', '利息支出', '貸款還本', '代銷費用']),
96
  use_container_width=True)
97
 
98
- # --- Tab 3, 4, 5: 修復空白分頁 ---
99
  with tabs[2]:
100
  conn = sqlite3.connect(DB_PATH)
101
  stages = pd.read_sql_query("SELECT * FROM project_stages", conn)
@@ -105,14 +99,14 @@ with tabs[2]:
105
  st.plotly_chart(ff.create_gantt(df_g, index_col='Resource', group_tasks=True), use_container_width=True)
106
  conn.close()
107
 
 
108
  with tabs[3]:
109
- st.subheader("🏦 融資合約清單")
110
- conn = sqlite3.connect(DB_PATH)
111
- st.dataframe(pd.read_sql_query("SELECT 貸款名稱, 授信額度, 年利率, 狀態 FROM loan_contracts", conn), use_container_width=True)
112
- conn.close()
113
-
114
- with tabs[4]:
115
- st.subheader("🏠 房屋銷售清單")
116
  conn = sqlite3.connect(DB_PATH)
117
- st.dataframe(pd.read_sql_query("SELECT 物件名稱, 預計售價, 總數量, 地主分回數量, 銷售狀態 FROM inventory", conn), use_container_width=True)
 
 
 
 
 
 
118
  conn.close()
 
1
  import streamlit as st
2
  import pandas as pd
3
  import plotly.graph_objects as go
4
+ import plotly.figure_factory as ff
5
  import sqlite3
6
  import datetime
7
  from database import init_db, load_full_project_example, clear_to_actual, backup_current_project, DB_PATH
8
 
9
+ # 系統初始化
10
  init_db()
11
+ st.set_page_config(page_title="SPV 都更財務動態系統", layout="wide")
12
+ st.title("🏢 SPV 都更計畫:現金流整合管理系統")
13
 
14
+ # --- 側邊欄:專案管理與自訂項目 ---
15
  with st.sidebar:
16
+ st.header("️ 專案管理面板")
17
+ total_b = st.number_input("總工程預算 ()", value=100000, step=1000)
18
+ project_start = st.date_input("計畫啟動日期", datetime.date(2026, 1, 20))
19
+
20
+ col_a, col_b = st.columns(2)
21
+ if col_a.button("🆕 切換至原專案", use_container_width=True):
22
  backup_current_project()
23
  clear_to_actual()
 
24
  st.rerun()
25
+ if col_b.button("💡 載入範例", type="primary", use_container_width=True):
26
+ load_full_project_example(total_b)
 
 
27
  st.rerun()
28
 
29
  st.divider()
30
+ st.subheader("➕ 錄入自訂收支項目")
31
+ with st.form("custom_item_form"):
32
  f_month = st.number_input("月份", min_value=1, value=1)
33
+ f_name = st.text_input("項目名稱 (如:公關費、印花稅)")
34
+ f_type = st.selectbox("科目性質", ["支出", "收入"])
35
  f_amt = st.number_input("金額 (萬)", min_value=0.0)
36
+ if st.form_submit_button("確認提交項目"):
37
  if f_name:
38
  conn = sqlite3.connect(DB_PATH)
39
  conn.execute("INSERT OR REPLACE INTO finance_transactions VALUES (?, '實際', ?, ?, ?)",
 
42
  conn.close()
43
  st.rerun()
44
 
45
+ # --- 主介面 Tabs ---
46
+ tabs = st.tabs(["📊 損益與利潤分析", "💰 現金流動態總表", "🏗️ 工程管理", "🏦 融資與銷售"])
47
 
48
+ # --- Tab 1: 損益與瀑布圖 (自動整合自訂項目) ---
49
+ with tabs[0]:
 
50
  conn = sqlite3.connect(DB_PATH)
51
+ df = pd.read_sql_query("SELECT * FROM finance_transactions WHERE 類型='實際'", conn)
52
+ params = pd.read_sql_query("SELECT * FROM project_params", conn)
53
  conn.close()
54
+
55
  if not df.empty:
56
+ total_in = df[df['科目性質']=='收入']['金額'].sum()
57
+ total_out = df[df['科目性質']=='支出']['金額'].sum()
 
 
 
 
58
 
59
+ st.subheader("⚖️ 專案獲利結構分析")
60
+ c1, c2, c3 = st.columns(3)
61
+ c1.metric("總流入金額", f"{total_in:,.0f} 萬")
62
+ c2.metric("總流出支出", f"{total_out:,.0f} 萬")
63
+ c3.metric("預計結餘毛利", f"{(total_in - total_out):,.0f} 萬")
64
+
65
+ # 瀑布圖:自動抓取所有支出科目
66
+ exp_df = df[df['科目性質']=='支出'].groupby('科目名稱')['金額'].sum().reset_index()
67
+ fig_w = go.Figure(go.Waterfall(
68
+ orientation = "v",
69
+ measure = ["absolute"] + ["relative"] * len(exp_df) + ["total"],
70
+ x = ["總收入預估"] + exp_df['科目名稱'].tolist() + ["最終淨利"],
71
+ y = [total_in] + (-exp_df['金額']).tolist() + [0],
72
+ connector = {"line":{"color":"rgb(63, 63, 63)"}},
73
+ ))
74
+ st.plotly_chart(fig_w, use_container_width=True)
75
  else:
76
+ st.info("請利用選單載入數據。")
77
 
78
+ # --- Tab 2: 現金流總表 (色系與科目) ---
79
+ with tabs[1]:
80
+ st.subheader("📅 動態現金流流水帳 (實際發生額)")
81
  if not df.empty:
82
+ # 動態轉置表格
83
+ pivot_df = df.pivot_table(index='月份', columns='科目名稱', values='金額', fill_value=0).reset_index()
84
+ inc_cols = df[df['科目性質']=='收入']['科目名稱'].unique()
85
+ exp_cols = df[df['科目性質']=='支出']['科目名稱'].unique()
 
 
 
86
 
87
+ st.dataframe(pivot_df.style.format(precision=0)
88
+ .applymap(lambda x: 'color: #228B22; font-weight: bold', subset=[c for c in inc_cols if c in pivot_df.columns])
89
+ .applymap(lambda x: 'color: #DC143C', subset=[c for c in exp_cols if c in pivot_df.columns]),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  use_container_width=True)
91
 
92
+ # --- Tab 3: 工程排程 ---
93
  with tabs[2]:
94
  conn = sqlite3.connect(DB_PATH)
95
  stages = pd.read_sql_query("SELECT * FROM project_stages", conn)
 
99
  st.plotly_chart(ff.create_gantt(df_g, index_col='Resource', group_tasks=True), use_container_width=True)
100
  conn.close()
101
 
102
+ # --- Tab 4: 融資與銷售 ---
103
  with tabs[3]:
 
 
 
 
 
 
 
104
  conn = sqlite3.connect(DB_PATH)
105
+ col_l, col_r = st.columns(2)
106
+ with col_l:
107
+ st.subheader("🏦 融資合約清單")
108
+ st.dataframe(pd.read_sql_query("SELECT * FROM loan_contracts", conn), use_container_width=True)
109
+ with col_r:
110
+ st.subheader("🏠 房屋銷售計畫")
111
+ st.dataframe(pd.read_sql_query("SELECT * FROM inventory", conn), use_container_width=True)
112
  conn.close()