Compare commits

..

2 Commits

Author SHA1 Message Date
Chris Chen 609ce6a439 WIP
ci-cd-vm / ci-cd (push) Successful in 1m49s
2026-06-24 21:47:22 -07:00
Chris Chen 46a4298a71 WIP 2026-06-24 21:37:41 -07:00
4 changed files with 359 additions and 6 deletions
@@ -56,6 +56,13 @@ public class DbSeederForm990Tests
var worship = await db.Ministries.FirstAsync(m => m.Name_en == "Worship"); var worship = await db.Ministries.FirstAsync(m => m.Name_en == "Worship");
Assert.Equal("ManagementGeneral", admin.DefaultFunctionalClass); Assert.Equal("ManagementGeneral", admin.DefaultFunctionalClass);
Assert.Equal("Program", worship.DefaultFunctionalClass); Assert.Equal("Program", worship.DefaultFunctionalClass);
// Activity/shepherding ministries are an attribution axis only; they default to Program
// so adding them never distorts the 990 functional columns.
var cellGroups = await db.Ministries.FirstAsync(m => m.Name_en == "Cell Groups");
var specialEvents = await db.Ministries.FirstAsync(m => m.Name_en == "Special Events");
Assert.Equal("Program", cellGroups.DefaultFunctionalClass);
Assert.Equal("Program", specialEvents.DefaultFunctionalClass);
} }
[Fact] [Fact]
@@ -77,4 +84,59 @@ public class DbSeederForm990Tests
.FirstAsync(s => s.Name_en == "Accounting & Audit"); .FirstAsync(s => s.Name_en == "Accounting & Audit");
Assert.Equal("11c", audit.Form990Line!.LineCode); Assert.Equal("11c", audit.Form990Line!.LineCode);
} }
[Fact]
public async Task SeedForm990Lines_MapsAuditCorrectedSubcategories_OffTheLine24CatchAll()
{
using var db = BuildDb();
await DbSeeder.SeedExpenseCategoriesAsync(db);
await DbSeeder.SeedForm990ExpenseLinesAsync(db);
async Task<string> CodeOf(string subEn) =>
(await db.ExpenseSubCategories.Include(s => s.Form990Line)
.FirstAsync(s => s.Name_en == subEn)).Form990Line!.LineCode;
// Newly mapped subcategories that previously fell through to line 24.
Assert.Equal("13", await CodeOf("Bank & Processing Fees"));
Assert.Equal("13", await CodeOf("Rental"));
Assert.Equal("13", await CodeOf("Maintenance & Repair"));
Assert.Equal("13", await CodeOf("Cleaning Supplies"));
Assert.Equal("13", await CodeOf("Craft Supplies"));
// Building repairs & maintenance are part of Occupancy (line 16), not equipment (line 13).
Assert.Equal("16", await CodeOf("Repairs & Maintenance"));
// Appreciation/outreach gifts are deliberately mapped to Other (line 24), not left unmapped.
Assert.Equal("24", await CodeOf("Gifts"));
// Visitation is a travel/program cost, not a grant to an individual.
Assert.Equal("17", await CodeOf("Visit Expenses"));
// Missions support paid to individual missionaries → line 2, not line 1 (organizations).
Assert.Equal("2", await CodeOf("Missionary Support"));
}
[Fact]
public async Task SeedForm990Lines_RemapsExistingBadMapping_ButNotAdminOverride()
{
using var db = BuildDb();
await DbSeeder.SeedExpenseCategoriesAsync(db);
await DbSeeder.SeedForm990ExpenseLinesAsync(db);
// Simulate a database seeded by the OLD code: Visit Expenses on line 2, Missionary
// Support on line 1. Also simulate an admin who deliberately moved one elsewhere.
var lineByCode = await db.Form990ExpenseLines.ToDictionaryAsync(l => l.LineCode, l => l.Id);
var visit = await db.ExpenseSubCategories.FirstAsync(s => s.Name_en == "Visit Expenses");
var missionary = await db.ExpenseSubCategories.FirstAsync(s => s.Name_en == "Missionary Support");
var transfer = await db.ExpenseSubCategories.FirstAsync(s => s.Name_en == "Offering Transfer");
visit.Form990LineId = lineByCode["2"]; // old (wrong) value → should be corrected
missionary.Form990LineId = lineByCode["1"]; // old (wrong) value → should be corrected
transfer.Form990LineId = lineByCode["24"]; // admin override → must be left alone
await db.SaveChangesAsync();
await DbSeeder.SeedForm990ExpenseLinesAsync(db);
await db.Entry(visit).ReloadAsync();
await db.Entry(missionary).ReloadAsync();
await db.Entry(transfer).ReloadAsync();
Assert.Equal(lineByCode["17"], visit.Form990LineId); // corrected 2 → 17
Assert.Equal(lineByCode["2"], missionary.Form990LineId); // corrected 1 → 2
Assert.Equal(lineByCode["24"], transfer.Form990LineId); // admin edit preserved
}
} }
+48 -5
View File
@@ -28,6 +28,8 @@ public static class DbSeeder
("Hospitality", "招待", 8), ("Hospitality", "招待", 8),
("Children", "兒牧", 9), ("Children", "兒牧", 9),
("Catering", "餐飲", 10), ("Catering", "餐飲", 10),
("Cell Groups", "小組牧養", 11),
("Special Events", "特別活動", 12),
]; ];
// (GroupEn, GroupZh, Sort, SubItems[(SubEn, SubZh)]) // (GroupEn, GroupZh, Sort, SubItems[(SubEn, SubZh)])
@@ -38,11 +40,11 @@ public static class DbSeeder
("Food & Beverage", "餐飲", 3, [("Catering","出餐費用"),("Food Ingredients","食材採購"),("Utensils","器具"),("Disposable Tableware","一次性餐具")]), ("Food & Beverage", "餐飲", 3, [("Catering","出餐費用"),("Food Ingredients","食材採購"),("Utensils","器具"),("Disposable Tableware","一次性餐具")]),
("Training", "培訓", 4, [("Course Fees","課程費用"),("Books","書籍"),("Conference","研討會"),("Travel","差旅")]), ("Training", "培訓", 4, [("Course Fees","課程費用"),("Books","書籍"),("Conference","研討會"),("Travel","差旅")]),
("Materials", "教材", 5, [("Curriculum Printing","教材印刷"),("Craft Supplies","手工材料"),("Copyright & Licensing","版權購買")]), ("Materials", "教材", 5, [("Curriculum Printing","教材印刷"),("Craft Supplies","手工材料"),("Copyright & Licensing","版權購買")]),
("Facility", "場地", 6, [("Rent","場地租金"),("Utilities","水電"),("Property Insurance","財產保險"),("Decoration","裝飾")]), ("Facility", "場地", 6, [("Rent","場地租金"),("Utilities","水電"),("Property Insurance","財產保險"),("Decoration","裝飾"),("Repairs & Maintenance","修繕維護")]),
("Printing", "印刷", 7, [("Bulletins","週報"),("Order of Service","程序單"),("Posters","海報"),("Advertising & Promotion","廣告推廣")]), ("Printing", "印刷", 7, [("Bulletins","週報"),("Order of Service","程序單"),("Posters","海報"),("Advertising & Promotion","廣告推廣")]),
("Missions", "宣教", 8, [("Offering Transfer","奉獻轉帳"),("Missionary Support","宣教士支援"),("Foreign Missions Support","國外宣教支援"),("Travel","差旅")]), ("Missions", "宣教", 8, [("Offering Transfer","奉獻轉帳"),("Missionary Support","宣教士支援"),("Foreign Missions Support","國外宣教支援"),("Travel","差旅")]),
("Benevolence", "關懷救助", 9, [("Emergency Aid","急難救助"),("Condolence Gifts","慰問禮品"),("Visit Expenses","探訪費用")]), ("Benevolence", "關懷救助", 9, [("Emergency Aid","急難救助"),("Condolence Gifts","慰問禮品"),("Visit Expenses","探訪費用")]),
("Other", "其他", 10, [("Miscellaneous","雜支")]), ("Other", "其他", 10, [("Miscellaneous","雜支"),("Gifts","禮品")]),
("Personnel", "人事", 11, [("Officer / Key Employee Compensation","主要職員薪酬"),("Salary & Wages","薪資"),("Payroll Taxes","薪資稅費"),("Employee Benefits","員工福利"),("Retirement / Pension","退休金"),("Workers Compensation","勞工保險"),("Honorarium","酬庸"),("Staff Training","同工進修"),("Contract Labor","外包勞務")]), ("Personnel", "人事", 11, [("Officer / Key Employee Compensation","主要職員薪酬"),("Salary & Wages","薪資"),("Payroll Taxes","薪資稅費"),("Employee Benefits","員工福利"),("Retirement / Pension","退休金"),("Workers Compensation","勞工保險"),("Honorarium","酬庸"),("Staff Training","同工進修"),("Contract Labor","外包勞務")]),
("Professional Services", "專業服務", 12, [("Legal","法律服務"),("Accounting & Audit","會計與審計"),("Other Professional","其他專業服務")]), ("Professional Services", "專業服務", 12, [("Legal","法律服務"),("Accounting & Audit","會計與審計"),("Other Professional","其他專業服務")]),
("Information Technology", "資訊科技", 13, [("Software & Subscriptions","軟體與訂閱"),("Website & Hosting","網站與主機"),("Internet & Telecom","網路與電信")]), ("Information Technology", "資訊科技", 13, [("Software & Subscriptions","軟體與訂閱"),("Website & Hosting","網站與主機"),("Internet & Telecom","網路與電信")]),
@@ -91,23 +93,36 @@ public static class DbSeeder
("Facility", "Utilities", "16"), ("Facility", "Utilities", "16"),
("Facility", "Property Insurance", "23"), ("Facility", "Property Insurance", "23"),
("Facility", "Decoration", "24"), ("Facility", "Decoration", "24"),
// Building repairs & maintenance (plumbing, electrical, painting) are part of Occupancy.
("Facility", "Repairs & Maintenance", "16"),
("Training", "Course Fees", "19"), ("Training", "Course Fees", "19"),
("Training", "Conference", "19"), ("Training", "Conference", "19"),
("Training", "Books", "24"), ("Training", "Books", "24"),
("Training", "Travel", "17"), ("Training", "Travel", "17"),
("Missions", "Travel", "17"), ("Missions", "Travel", "17"),
("Missions", "Offering Transfer", "1"), // Domestic missions support is paid to individual missionaries/families → line 2 (grants to individuals).
("Missions", "Missionary Support", "1"), ("Missions", "Offering Transfer", "2"),
("Missions", "Missionary Support", "2"),
("Missions", "Foreign Missions Support", "3"), ("Missions", "Foreign Missions Support", "3"),
("Benevolence", "Emergency Aid", "2"), ("Benevolence", "Emergency Aid", "2"),
("Benevolence", "Condolence Gifts", "2"), ("Benevolence", "Condolence Gifts", "2"),
("Benevolence", "Visit Expenses", "2"), // Visitation is the church's own travel/program cost, not a grant to an individual.
("Benevolence", "Visit Expenses", "17"),
("Consumables", "Office Supplies", "13"), ("Consumables", "Office Supplies", "13"),
// General supplies belong with office expenses (line 13), not the "Other" catch-all.
("Consumables", "Batteries", "13"),
("Consumables", "Accessories", "13"),
("Consumables", "Cleaning Supplies", "13"),
// IRS line 13 covers equipment rental and maintenance.
("Equipment", "Rental", "13"),
("Equipment", "Maintenance & Repair", "13"),
("Printing", "Bulletins", "13"), ("Printing", "Bulletins", "13"),
("Printing", "Order of Service", "13"), ("Printing", "Order of Service", "13"),
("Printing", "Posters", "12"), ("Printing", "Posters", "12"),
("Printing", "Advertising & Promotion", "12"), ("Printing", "Advertising & Promotion", "12"),
("Materials", "Curriculum Printing", "13"), ("Materials", "Curriculum Printing", "13"),
// Classroom/craft supplies fall under IRS line 13 office expenses ("supplies… classroom…").
("Materials", "Craft Supplies", "13"),
("Professional Services", "Legal", "11b"), ("Professional Services", "Legal", "11b"),
("Professional Services", "Accounting & Audit", "11c"), ("Professional Services", "Accounting & Audit", "11c"),
("Professional Services", "Other Professional", "11g"), ("Professional Services", "Other Professional", "11g"),
@@ -115,6 +130,22 @@ public static class DbSeeder
("Information Technology", "Website & Hosting", "14"), ("Information Technology", "Website & Hosting", "14"),
("Information Technology", "Internet & Telecom", "14"), ("Information Technology", "Internet & Telecom", "14"),
("Finance & Banking", "Interest", "20"), ("Finance & Banking", "Interest", "20"),
// Bank/processing fees are office expenses per IRS line 13 (consistent with Interest → 20).
("Finance & Banking", "Bank & Processing Fees", "13"),
// Appreciation/outreach gifts have no natural 990 line; mapped to 24 explicitly so this
// deliberate "Other" choice doesn't inflate UnmappedExpenseCount. (Benevolence gifts → line 2.)
("Other", "Gifts", "24"),
];
// One-time corrections for subcategories that were mapped to the WRONG line in an earlier
// seed. The normal mapping loop below only fills NULLs, so it cannot fix an existing bad
// value — this block does. Idempotent: each row fires only while the subcategory still holds
// the OLD line, so it never clobbers a deliberate admin re-mapping. (GroupEn, SubEn, Old, New)
private static readonly (string GroupEn, string SubEn, string OldCode, string NewCode)[] Form990RemapSeed =
[
("Benevolence", "Visit Expenses", "2", "17"),
("Missions", "Missionary Support", "1", "2"),
("Missions", "Offering Transfer", "1", "2"),
]; ];
private static readonly (string Name, string Description)[] Roles = private static readonly (string Name, string Description)[] Roles =
@@ -329,6 +360,18 @@ public static class DbSeeder
if (sub is not null && sub.Form990LineId is null && linesByCode.TryGetValue(code, out var lineId)) if (sub is not null && sub.Form990LineId is null && linesByCode.TryGetValue(code, out var lineId))
sub.Form990LineId = lineId; sub.Form990LineId = lineId;
} }
// Correct earlier mis-mappings on existing databases (see Form990RemapSeed). Only fires
// while the subcategory still holds the OLD line, so a later admin edit is never clobbered.
foreach (var (groupEn, subEn, oldCode, newCode) in Form990RemapSeed)
{
var sub = subsByKey.FirstOrDefault(s => s.Group!.Name_en == groupEn && s.Name_en == subEn);
if (sub is null) continue;
if (linesByCode.TryGetValue(oldCode, out var oldId)
&& linesByCode.TryGetValue(newCode, out var newId)
&& sub.Form990LineId == oldId)
sub.Form990LineId = newId;
}
await db.SaveChangesAsync(); await db.SaveChangesAsync();
} }
+6 -1
View File
@@ -595,6 +595,7 @@ Table: ExpenseSubCategories
| 6 Facility | Utilities | 水電 | | 6 Facility | Utilities | 水電 |
| 6 Facility | Property Insurance | 財產保險 | | 6 Facility | Property Insurance | 財產保險 |
| 6 Facility | Decoration | 裝飾 | | 6 Facility | Decoration | 裝飾 |
| 6 Facility | Repairs & Maintenance | 修繕維護 |
| 7 Printing | Bulletins | 週報 | | 7 Printing | Bulletins | 週報 |
| 7 Printing | Order of Service | 程序單 | | 7 Printing | Order of Service | 程序單 |
| 7 Printing | Posters | 海報 | | 7 Printing | Posters | 海報 |
@@ -607,6 +608,7 @@ Table: ExpenseSubCategories
| 9 Benevolence | Condolence Gifts | 慰問禮品 | | 9 Benevolence | Condolence Gifts | 慰問禮品 |
| 9 Benevolence | Visit Expenses | 探訪費用 | | 9 Benevolence | Visit Expenses | 探訪費用 |
| 10 Other | Miscellaneous | 雜支 | | 10 Other | Miscellaneous | 雜支 |
| 10 Other | Gifts | 禮品 |
| 11 Personnel | Salary & Wages | 薪資 | | 11 Personnel | Salary & Wages | 薪資 |
| 11 Personnel | Officer / Key Employee Compensation | 主任/關鍵員工薪酬 | | 11 Personnel | Officer / Key Employee Compensation | 主任/關鍵員工薪酬 |
| 11 Personnel | Payroll Taxes | 薪資稅費 | | 11 Personnel | Payroll Taxes | 薪資稅費 |
@@ -618,6 +620,7 @@ Table: ExpenseSubCategories
| 11 Personnel | Contract Labor | 外包勞務 | | 11 Personnel | Contract Labor | 外包勞務 |
> **備注:** `Facility > 財產保險` 指建築物/場地責任險;員工健保、團體保險等歸 `Personnel > 員工福利`。同工代墊報銷依**實際購買物**選大類,不歸人事。 > **備注:** `Facility > 財產保險` 指建築物/場地責任險;員工健保、團體保險等歸 `Personnel > 員工福利`。同工代墊報銷依**實際購買物**選大類,不歸人事。
> **修繕歸類:** 建物日常修繕(水電、油漆等)歸 `Facility > 修繕維護`990 第16行 Occupancy);**設備**維修歸 `Equipment > Maintenance & Repair`990 第13行)。重大資本改良(整修屋頂、大規模裝修)應資本化、走折舊(第22行,目前未實作)。
> **子項目更名說明:** `Food & Beverage > Consumables`(消耗品)更名為 `Disposable Tableware`(一次性餐具)以消除與大類同名的歧義;`Materials > Printing`(印刷費用)更名為 `Curriculum Printing`(教材印刷)以與 Printing 大類區分。 > **子項目更名說明:** `Food & Beverage > Consumables`(消耗品)更名為 `Disposable Tableware`(一次性餐具)以消除與大類同名的歧義;`Materials > Printing`(印刷費用)更名為 `Curriculum Printing`(教材印刷)以與 Printing 大類區分。
### Expense(支出記錄) ### Expense(支出記錄)
@@ -995,7 +998,7 @@ Table: MinistryBudgets
super_admin, pastor, board_member, coworker_chair, ministry_leader, district_leader, cell_leader, coworker, finance, secretary, worship_leader, member, visitor super_admin, pastor, board_member, coworker_chair, ministry_leader, district_leader, cell_leader, coworker, finance, secretary, worship_leader, member, visitor
``` ```
### Ministries10 個事工部門) ### Ministries12 個事工部門)
``` ```
1. Administration / 行政 DefaultFunctionalClass = 'ManagementGeneral' 1. Administration / 行政 DefaultFunctionalClass = 'ManagementGeneral'
2. Preaching / 講道 DefaultFunctionalClass = 'Program' 2. Preaching / 講道 DefaultFunctionalClass = 'Program'
@@ -1007,6 +1010,8 @@ super_admin, pastor, board_member, coworker_chair, ministry_leader, district_lea
8. Hospitality / 招待 DefaultFunctionalClass = 'Program' 8. Hospitality / 招待 DefaultFunctionalClass = 'Program'
9. Children / 兒牧 DefaultFunctionalClass = 'Program' 9. Children / 兒牧 DefaultFunctionalClass = 'Program'
10. Catering / 餐飲 DefaultFunctionalClass = 'Program' 10. Catering / 餐飲 DefaultFunctionalClass = 'Program'
11. Cell Groups / 小組牧養 DefaultFunctionalClass = 'Program'
12. Special Events / 特別活動 DefaultFunctionalClass = 'Program'
``` ```
### GivingCategories(奉獻類型) ### GivingCategories(奉獻類型)
+243
View File
@@ -0,0 +1,243 @@
# 教會支出分類速查指南(財務同工版)
> 目的:幫助財務同工在登錄每一筆支出時,快速、正確地選對 **大類別** 與 **子類別**。
> 分類正確 = 報表正確 = 隨時能應付 IRS Form 990 級查帳。
>
> 看不懂某個欄位時,先讀「§1 三個關鍵觀念」,八成的疑問都在那裡。
---
## §0 這套分類在做什麼?(先讀懂目的)
教會**用自己習慣的方式**記帳,系統**自動翻譯成 IRS 看得懂的格式**。你只要照教會的習慣選,剩下的交給系統。
**我們自己用三個維度歸納每一筆支出:**
| 維度 | 回答的問題 | 例子 |
|---|---|---|
| **事工 Ministry** | 這筆錢是**誰/哪個服事或場合**花的? | 敬拜、兒牧、小組牧養、特別活動… |
| **大類別 Category** | 買的是**哪一種性質**的東西? | 餐飲、人事、場地、印刷… |
| **子類別 Subcategory** | 再**細一點**是什麼? | 出餐費用、薪資、水電、週報… |
這三個維度是**為教會自己設計的**,貼近我們的服事與生活,所以好選、好記。
**最終呈現給 IRS 時:**
```
教會的記帳方式 IRS 要的格式
事工 + 大類別 + 子類別 ──(系統自動對應)──▶ Form 990 Part IX
(同工只需選這邊) 功能性費用表(自動產生)
```
- 每個子類別背後都**預先對應好一條 Form 990 自然費用行**(就是速查表最右邊那欄「990行」)。
- 同工**完全不需要懂 990** —— 只要照教會習慣選對事工/大類/子類,系統就能在查帳時自動產出符合 IRS Form 990 的功能性費用表。
> 一句話:**你照教會的方式分類,系統幫你變成 IRS 的語言。** 所以「選對類別」這件小事,就是整個查帳整備的基礎。
> 補充:美國教會依 IRC §6033(a)(3)(A) **免於申報** Form 990;我們做這套對應,是為了在 IRS 查核時能**隨時拿得出** 990 等級的佐證,不是真的要報稅。
---
## §1 三個關鍵觀念(務必先讀)
### 觀念 1️⃣ 類別 = 你買了「**什麼**」,不是「為了哪個活動」
大類別/子類別描述的是**費用的性質**(買食物、付薪水、修水電),**不是活動名稱**。
- ❌ 沒有「父親節」「福音周」「周年慶」這種類別。
- ✅ 「活動/場合」請寫在 **事工(組別)** 欄 + **說明(Description)** 欄。
> 例:父親節買的 Pizza → 大類別選「餐飲」,**不是**去找「父親節」類別;
> 在說明欄寫「父親節活動加菜」,在事工欄選「特別活動」。
>
> 💡 事工欄有兩個專收「跨性質活動」花費的選項:**「特別活動」**(父親節、福音周、周年慶、愛宴…)與 **「小組牧養」**(各小組聚會、開放家庭、小組關懷)。記不得放哪個事工時,大多能用這兩個。
### 觀念 2️⃣ 一個活動 = 常常拆成「多筆、不同類別」
大型活動的花費橫跨好幾種性質,**請分開登錄**,不要硬塞進同一類。
> 例:**教會周年慶**可能拆成 ——
> - 餐點 → `餐飲 > 出餐費用`
> - 會場布置鮮花 → `場地 > 裝飾`
> - 海報/邀請卡 → `印刷 > 海報`
> - 給來賓的小禮 → `其他 > 雜支`
>
> 全部在事工欄選同一組別、說明欄都寫「周年慶」,但**類別各自照性質選**。
### 觀念 3️⃣ 不確定時:看「實際買的東西」,真的找不到才用「其他 > 雜支」
- 先問自己:「這筆錢**實際買到的是什麼**?」依那個東西選類別。
- 真的沒有對應 → `其他 > 雜支`,並**在說明欄寫清楚**(查帳時看得懂就好)。
---
## §2 你給的範例,這樣分
| 費用範例 | 事工(選組別) | 大類別 | 子類別 | (990行) |
|---|---|---|---|:--:|
| 父親節 — 給父親的小禮物(每份 < $20) | 特別活動 | 其他 | **禮品** | 24 |
| 父親節 — 加菜金(Pizza/水果/炸雞) | 特別活動 | 餐飲 | 出餐費用 | 24 |
| 福音周 — 買福音小組食物(現成) | 特別活動 | 餐飲 | 出餐費用 | 24 |
| 福音周 — 買食材自己煮 | 特別活動 | 餐飲 | 食材採購 | 24 |
| 福音周 — 福音小組小禮物 | 特別活動 | 其他 | **禮品** | 24 |
| 特別講員的講員費(一次性) | 講道 | 人事 | **酬庸** | 11g |
| 小組餐具費 — 可重複用的碗盤 | 小組牧養 | 餐飲 | 器具 | 24 |
| 小組餐具費 — 用完即丟的紙盤紙杯 | 小組牧養 | 餐飲 | 一次性餐具 | 24 |
| 小組生日聚餐 — 買蛋糕幫弟兄姊妹慶生 | 小組牧養 | 餐飲 | 出餐費用 | 24 |
| 同工退修會 — 兩天一夜住宿 | 行政/相關組 | 人事 | **同工進修**(住宿差旅同筆登即可) | 19 |
| 教會周年慶 — 整體預算 | 特別活動 | **拆多筆**(見觀念 2) | 各依性質 | 多 |
| 主日愛宴 | 餐飲/招待 | 餐飲 | 出餐費用 或 食材採購 | 24 |
| Part-time 同工薪水 | 行政 | 人事 | **薪資** | 7 |
> 講員費 vs 薪水:**一次性的外部講員 → 酬庸**;**固定領薪的同工(含兼職) → 薪資**。
---
## §3 常見費用速查表(依場景)
> 990 行欄位是系統**自動帶出**的,同工**不需要選**,僅供對帳參考。
### 🙏 主日崇拜/敬拜
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 司琴/敬拜團車馬費、特約樂手 | 人事 | 酬庸 | 11g |
| 詩歌版權(CCLI 等)、影片授權 | 教材 | 版權購買 | 24 |
| 主日週報印刷 | 印刷 | 週報 | 13 |
| 程序單印刷 | 印刷 | 程序單 | 13 |
| 講台鮮花、會場布置 | 場地 | 裝飾 | 24 |
| 聖餐餅/杯(消耗食材) | 餐飲 | 食材採購 | 24 |
| 麥克風電池 | 消耗品 | 電池 | 13 |
### 🍱 餐飲/愛宴/團契
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 外訂便當/Pizza/現成餐點 | 餐飲 | 出餐費用 | 24 |
| 自己煮 — 買食材 | 餐飲 | 食材採購 | 24 |
| 可重複用的鍋具、碗盤、保溫桶 | 餐飲 | 器具 | 24 |
| 紙盤、紙杯、免洗餐具 | 餐飲 | 一次性餐具 | 24 |
| 慶生蛋糕(屬聚餐的一部分) | 餐飲 | 出餐費用 | 24 |
### 👥 人事/薪酬
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 牧師/主要負責同工薪酬 | 人事 | 主要職員薪酬 | 5 |
| 一般同工、兼職薪水 | 人事 | 薪資 | 7 |
| 代扣/雇主薪資稅 | 人事 | 薪資稅費 | 10 |
| 健保、團保等員工福利 | 人事 | 員工福利 | 9 |
| 退休金提撥 | 人事 | 退休金 | 8 |
| 勞工保險 | 人事 | 勞工保險 | 9 |
| 一次性講員費、外部酬勞 | 人事 | 酬庸 | 11g |
| 外包勞務(設計、清潔承包) | 人事 | 外包勞務 | 11g |
| 同工進修、退修會、報名研習 | 人事 | 同工進修 | 19 |
### 🏠 場地/行政
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 場地租金 | 場地 | 場地租金 | 16 |
| 水費、電費、瓦斯費 | 場地 | 水電 | 16 |
| **建物修繕**(修水電、油漆、換燈管) | 場地 | **修繕維護** | 16 |
| 財產/場地保險 | 場地 | 財產保險 | 23 |
| 影印紙、碳粉、文具 | 消耗品 | 文具 | 13 |
| 清潔用品(洗手乳、垃圾袋、清潔劑) | 消耗品 | 清潔用品 | 13 |
| 電池、雜項配件 | 消耗品 | 電池/配件 | 13 |
### 🖥️ 資訊科技
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 軟體訂閱(Zoom、Planning Center、Office) | 資訊科技 | 軟體與訂閱 | 14 |
| 教會網站、網域、主機代管 | 資訊科技 | 網站與主機 | 14 |
| 網路費、市話/手機通訊 | 資訊科技 | 網路與電信 | 14 |
### 🛠️ 設備
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| **租**投影機、音響、桌椅 | 設備 | 租借 | 13 |
| **修**設備(音響、樂器、冷氣保養) | 設備 | 維修 | 13 |
| **買**設備(見下方 ⚠️ 大額提醒) | 設備 | 購置 | 24 |
> ⚠️ **大額設備購置請先問財務負責人**:單項 **≥ $2,500** 的設備(整套音響、車輛、冷氣主機等)在會計上要列「固定資產」分年折舊,**不是當年度費用**。低於 $2,500 的小設備(手機、麥克風、單張椅子)才直接走「設備 > 購置」。詳見 §5。
### 📚 培訓/裝備
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 報名特會、課程、研習費 | 培訓 | 課程費用/研討會 | 19 |
| 購買書籍、參考教材書 | 培訓 | 書籍 | 24 |
| 培訓的交通、住宿差旅 | 培訓 | 差旅 | 17 |
### 🧒 兒童/教材
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 主日學教材印刷 | 教材 | 教材印刷 | 13 |
| 美勞、手工材料 | 教材 | 手工材料 | 13 |
| 詩歌/影片/教材版權授權 | 教材 | 版權購買 | 24 |
### 🌏 宣教/關懷
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 支持個人宣教士/家庭 | 宣教 | 宣教士支援 | 2 |
| 國外宣教奉獻 | 宣教 | 國外宣教支援 | 3 |
| 短宣隊機票、交通 | 宣教 | 差旅 | 17 |
| 急難救助金(給有需要的人) | 關懷救助 | 急難救助 | 2 |
| 喪家慰問、白包、探病禮金 | 關懷救助 | 慰問禮品 | 2 |
| 探訪的交通、伴手禮 | 關懷救助 | 探訪費用 | 17 |
### 📢 福音/外展/推廣
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 福音單張、海報印刷 | 印刷 | 海報 | 12 |
| 臉書/網路廣告、推廣文宣 | 印刷 | 廣告推廣 | 12 |
| 福音活動食物 | 餐飲 | 出餐費用/食材採購 | 24 |
| 給福音朋友/來賓的小禮物 | 其他 | 禮品 | 24 |
### 💵 財務/銀行/專業服務
| 買了什麼 | 大類別 | 子類別 | 990 |
|---|---|---|:--:|
| 銀行手續費、金流/刷卡手續費 | 財務與銀行 | 銀行/金流手續費 | 13 |
| 貸款利息 | 財務與銀行 | 利息支出 | 20 |
| 會計師、報稅、查核費 | 專業服務 | 會計與審計 | 11c |
| 律師、法律諮詢費 | 專業服務 | 法律服務 | 11b |
| 其他專業顧問費 | 專業服務 | 其他專業服務 | 11g |
---
## §4 最容易選錯的 6 組(特別注意)
| 情境 | 選這個 ✅ | 不要選 ❌ |
|---|---|---|
| 用完即丟的紙盤紙杯 | 餐飲 > **一次性餐具** | 餐飲 > 器具(那是可重複用的) |
| 買食材回來自己煮 | 餐飲 > **食材採購** | 餐飲 > 出餐費用(那是買現成的) |
| 修教會的水電、油漆牆面 | 場地 > **修繕維護** | 設備 > 維修(那是修「設備」不是修「建物」) |
| 一次性外部講員費 | 人事 > **酬庸** | 人事 > 薪資(薪資是固定領薪同工) |
| 喪事白包/探病禮金 | 關懷救助 > **慰問禮品** | 其他 > 禮品 |
| 一般活動感謝小禮(父親節、福音禮) | 其他 > **禮品** | 關懷救助 > 慰問禮品(那是針對喪病急難) |
---
## §5 ⚠️ 大額設備:為什麼要特別處理?
IRS 規定:**單項價值 ≥ $2,500** 的設備不能當年度一次費用化,要列為「固定資產」、分年攤提折舊(Form 990 第22行)。
| 例子 | 單價 | 怎麼處理 |
|---|---|---|
| 手機、麥克風、單張椅子 | < $2,500 | ✅ 直接登錄 `設備 > 購置` |
| 一次買一批便宜椅子(每張 < $2,500) | 逐張算 | ✅ 仍可直接費用化 |
| 整套音響系統、車輛、冷氣主機 | ≥ $2,500 | ⚠️ **先問財務負責人**,要列固定資產 |
> 系統目前還沒有「固定資產/折舊」功能(規劃中)。遇到大額設備,**先暫停、找財務負責人確認**,不要自己登成一般支出。
---
## §6 還是不確定?
1. 重讀 **§1 觀念 1**:我**實際買到的東西**是什麼?
2.**§3 速查表**用那個東西找(不是用活動名稱找)。
3. 找不到完全吻合的 → 選**性質最接近**的子類別。
4. 真的沒有 → `其他 > 雜支`,並在**說明欄寫清楚買了什麼、什麼場合**。
5. 金額大(設備 ≥ $2,500、或不確定要不要列資產)→ **先問財務負責人**
---
> **給管理者的備注(非同工日常需要):**
> 1. 「特別活動」(父親節、福音周、周年慶)刻意**不設為類別** —— 活動是「場合」不是「費用性質」。活動名稱寫在說明欄、主辦組別選事工;若日後要依活動別出報表,應另開「活動標籤」維度,而非新增大類。
> 2. 一般活動感謝禮、福音贈品歸 `其他 > 禮品`(990 第24行);**喪病急難**的慰問仍歸 `關懷救助 > 慰問禮品`(990 第2行),兩者性質不同勿混。
> 3. 「990 行」欄位由系統依大類/子類別自動對應,維護於 `DbSeeder.Form990SubMappingSeed`;對應規則詳見 `docs/DB_SCHEMA.md`。