chore: 首次簽入 Thinkyu ASP.NET 專案
- 加入 Visual Studio / ASP.NET .gitignore - 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
This commit is contained in:
@@ -0,0 +1,533 @@
|
||||
using Newtonsoft.Json;
|
||||
using NPOI.SS.Formula.Functions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using WebLib;
|
||||
|
||||
namespace Education
|
||||
{
|
||||
/// <summary>
|
||||
/// 領據匯入類別
|
||||
/// </summary>
|
||||
public class 領據匯入 : ImportBase
|
||||
{
|
||||
public 領據匯入()
|
||||
{
|
||||
// 定義欄位
|
||||
columns.Add(new ImportColumn("活動日期", 12, required: true));
|
||||
columns.Add(new ImportColumn("身分別", 10, required: true));
|
||||
columns.Add(new ImportColumn("領款人姓名", 10, required: true));
|
||||
columns.Add(new ImportColumn("身分證字號", 15));
|
||||
columns.Add(new ImportColumn("憑證類別", 10, required: true));
|
||||
columns.Add(new ImportColumn("計畫代號", 15, required: true));
|
||||
columns.Add(new ImportColumn("活動地點", 20));
|
||||
columns.Add(new ImportColumn("活動類別", 10));
|
||||
columns.Add(new ImportColumn("付款方式", 10));
|
||||
columns.Add(new ImportColumn("活動名稱/事由", 30, fieldName: "活動名稱事由"));
|
||||
columns.Add(new ImportColumn("勞務費費用別", 15));
|
||||
columns.Add(new ImportColumn("扣繳類別", 15));
|
||||
columns.Add(new ImportColumn("單價", 10));
|
||||
columns.Add(new ImportColumn("數量", 10));
|
||||
columns.Add(new ImportColumn("單位", 10));
|
||||
columns.Add(new ImportColumn("服務費", 10));
|
||||
columns.Add(new ImportColumn("差旅票價資訊", 15));
|
||||
columns.Add(new ImportColumn("起點", 15));
|
||||
columns.Add(new ImportColumn("訖點", 15));
|
||||
columns.Add(new ImportColumn("捷運/公車", 10, fieldName: "捷運公車"));
|
||||
columns.Add(new ImportColumn("火車", 10));
|
||||
columns.Add(new ImportColumn("計程車", 10));
|
||||
columns.Add(new ImportColumn("高鐵/飛機", 10, fieldName: "高鐵飛機"));
|
||||
columns.Add(new ImportColumn("自行開車", 10));
|
||||
columns.Add(new ImportColumn("過路費/停車費", 10, fieldName: "過路費停車費"));
|
||||
columns.Add(new ImportColumn("住宿費", 10));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 進行額外的資料驗證(欄位內容檢查)
|
||||
/// </summary>
|
||||
public List<string> ValidateContent(string filePath)
|
||||
{
|
||||
List<string> errors = new List<string>();
|
||||
var workbook = LoadWorkbook(filePath);
|
||||
var sheet = workbook.GetSheetAt(0);
|
||||
|
||||
// 從標頭列建立欄位名稱 → 欄位索引對照表
|
||||
var columnMap = new Dictionary<string, int>();
|
||||
var headerRow = sheet.GetRow(0);
|
||||
if (headerRow != null)
|
||||
{
|
||||
for (int i = 0; i <= headerRow.LastCellNum; i++)
|
||||
{
|
||||
var cell = headerRow.GetCell(i);
|
||||
if (cell == null) continue;
|
||||
string title = cell.ToString().Trim();
|
||||
if (!string.IsNullOrEmpty(title) && !columnMap.ContainsKey(title))
|
||||
columnMap[title] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// 差旅費數值欄位清單
|
||||
var travelFeeColumns = new List<string> { "捷運/公車", "火車", "計程車", "高鐵/飛機", "自行開車", "過路費/停車費", "住宿費" };
|
||||
|
||||
var dac講師 = new DAC_講師(connection);
|
||||
var dac非講師 = new DAC_非講師(connection);
|
||||
|
||||
for (int rowId = 1; rowId <= sheet.LastRowNum; rowId++)
|
||||
{
|
||||
var row = sheet.GetRow(rowId);
|
||||
if (row == null)
|
||||
break;
|
||||
|
||||
// 以欄位名稱取得每欄的值
|
||||
var cellValues = new Dictionary<string, string>();
|
||||
foreach (var column in columns)
|
||||
{
|
||||
string cellValue = "";
|
||||
if (columnMap.ContainsKey(column.Title))
|
||||
{
|
||||
var cell = row.GetCell(columnMap[column.Title]);
|
||||
cellValue = cell == null ? "" : excel.CellValueToString(cell);
|
||||
}
|
||||
cellValues[column.Title] = cellValue;
|
||||
}
|
||||
|
||||
// 若所有欄位皆為空則停止
|
||||
bool allEmpty = true;
|
||||
foreach (var v in cellValues.Values)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(v)) { allEmpty = false; break; }
|
||||
}
|
||||
if (allEmpty)
|
||||
break;
|
||||
|
||||
// 驗證活動日期
|
||||
if (!string.IsNullOrEmpty(cellValues["活動日期"]))
|
||||
{
|
||||
// 日期要能接受兩種:字串與 Excel 裡日期
|
||||
if (!領據匯入驗證.IsValidDate(cellValues["活動日期"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「活動日期」:日期格式不正確,值為「{cellValues["活動日期"]}」");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「活動日期」:必填欄位不可為空");
|
||||
}
|
||||
|
||||
// 驗證身分別
|
||||
if (string.IsNullOrEmpty(cellValues["身分別"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「身分別」:必填欄位不可為空");
|
||||
}
|
||||
else if (cellValues["身分別"] != "講師" && cellValues["身分別"] != "非講師")
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「身分別」:只允許「講師」或「非講師」,實際值為「{cellValues["身分別"]}」");
|
||||
}
|
||||
|
||||
// 驗證領款人姓名
|
||||
if (string.IsNullOrEmpty(cellValues["領款人姓名"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「領款人姓名」:必填欄位不可為空");
|
||||
}
|
||||
else
|
||||
{
|
||||
var 講師_非講師編號 = string.Empty;
|
||||
if (cellValues["身分別"] == "講師")
|
||||
{
|
||||
var t = dac講師.Select(false, cellValues["領款人姓名"], null, null)
|
||||
.Where(x => string.Compare(x.姓名, cellValues["領款人姓名"]) == 0
|
||||
&& string.Compare(x.身份證字號, cellValues["身分證字號"]) == 0)
|
||||
.FirstOrDefault();
|
||||
if (t != null)
|
||||
講師_非講師編號 = t.編號.ToString();
|
||||
}
|
||||
else if (cellValues["身分別"] == "非講師")
|
||||
{
|
||||
var t = dac非講師.Select(false, null, cellValues["領款人姓名"], null, null, null)
|
||||
.Where(x => string.Compare(x.姓名, cellValues["領款人姓名"]) == 0
|
||||
&& string.Compare(x.身分證字號, cellValues["身分證字號"]) == 0)
|
||||
.FirstOrDefault();
|
||||
if (t != null)
|
||||
講師_非講師編號 = t.編號;
|
||||
}
|
||||
|
||||
if (講師_非講師編號 == string.Empty)
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「領款人姓名」:不存在於系統內");
|
||||
}
|
||||
}
|
||||
|
||||
// 驗證憑證類別
|
||||
if (string.IsNullOrEmpty(cellValues["憑證類別"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「憑證類別」:必填欄位不可為空");
|
||||
}
|
||||
else if (!領據匯入驗證.IsValidProofType(cellValues["憑證類別"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「憑證類別」:無效的值「{cellValues["憑證類別"]}」,允許值為「領據」、「發票」、「收據」");
|
||||
}
|
||||
|
||||
// 驗證計畫代號
|
||||
if (string.IsNullOrEmpty(cellValues["計畫代號"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「計畫代號」:必填欄位不可為空");
|
||||
}
|
||||
else
|
||||
{
|
||||
var planCode = cellValues["計畫代號"];
|
||||
bool isTYCode = System.Text.RegularExpressions.Regex.IsMatch(planCode, @"^TY\d{4}$");
|
||||
if (!isTYCode && !領據匯入驗證.IsValidProjectCode(planCode))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「計畫代號」:計畫代號「{planCode}」不存在於系統中");
|
||||
}
|
||||
}
|
||||
|
||||
// 驗證付款方式(選填)
|
||||
if (!string.IsNullOrEmpty(cellValues["付款方式"]) && !領據匯入驗證.IsValidPaymentMethod(cellValues["付款方式"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「付款方式」:無效的值「{cellValues["付款方式"]}」,允許值為「匯款」、「支票」、「現金」");
|
||||
}
|
||||
|
||||
// 驗證勞務費費用別(選填)
|
||||
if (!string.IsNullOrEmpty(cellValues["勞務費費用別"]) && !領據匯入驗證.IsValidLaborExpenseType(cellValues["勞務費費用別"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「勞務費費用別」:無效的值「{cellValues["勞務費費用別"]}」");
|
||||
}
|
||||
|
||||
// 驗證扣繳類別(選填)
|
||||
if (!string.IsNullOrEmpty(cellValues["扣繳類別"]))
|
||||
{
|
||||
cellValues["扣繳類別"] = 扣繳類別.MapValue(cellValues["扣繳類別"]);
|
||||
if (!領據匯入驗證.IsValidWithholdingCategory(cellValues["扣繳類別"]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「扣繳類別」:無效的值「{cellValues["扣繳類別"]}」");
|
||||
}
|
||||
}
|
||||
|
||||
// 驗證扣繳類別於費用別的對應關係
|
||||
if (cellValues["勞務費費用別"] == "演講費" || cellValues["勞務費費用別"] == "撰稿費" && cellValues["扣繳類別"] == "50")
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「扣繳類別」:扣繳類別只能是執行業務所得");
|
||||
}
|
||||
|
||||
// 驗證單價、數量、服務費(選填)
|
||||
int 單價 = 0;
|
||||
decimal 數量 = 0;
|
||||
bool 有勞務費金額 = false;
|
||||
|
||||
if (!string.IsNullOrEmpty(cellValues["單價"]))
|
||||
{
|
||||
if (!領據匯入驗證.IsValidDecimal(cellValues["單價"]))
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「單價」:應為數值,實際值為「{cellValues["單價"]}」");
|
||||
else
|
||||
{
|
||||
單價 = DAC.GetInt32(cellValues["單價"]);
|
||||
有勞務費金額 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(cellValues["數量"]))
|
||||
{
|
||||
if (!領據匯入驗證.IsValidDecimal(cellValues["數量"]))
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「數量」:應為數值,實際值為「{cellValues["數量"]}」");
|
||||
else
|
||||
{
|
||||
數量 = DAC.GetDecimal(cellValues["數量"]);
|
||||
有勞務費金額 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(cellValues["服務費"]))
|
||||
{
|
||||
if (!領據匯入驗證.IsValidDecimal(cellValues["服務費"]))
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「服務費」:應為數值,實際值為「{cellValues["服務費"]}」");
|
||||
else
|
||||
有勞務費金額 = true;
|
||||
}
|
||||
|
||||
// 有勞務費金額但費用別或單位未填
|
||||
if (有勞務費金額 && string.IsNullOrEmpty(cellValues["勞務費費用別"]))
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「勞務費費用別」:已輸入金額,此欄位不可為空");
|
||||
if (有勞務費金額 && string.IsNullOrEmpty(cellValues["單位"]))
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「單位」:已輸入金額,此欄位不可為空");
|
||||
|
||||
// 合計金額驗證
|
||||
int 合計金額 = (int)((decimal)單價 * 數量);
|
||||
if (cellValues["扣繳類別"] == "50" && 合計金額 >= PublicVariable.領據基本工資) {
|
||||
errors.Add($"第 {rowId + 1} 列:薪資不得超過基本工資 {PublicVariable.領據基本工資}(含),超過請拆成不同日期的領據");
|
||||
}
|
||||
if ((cellValues["扣繳類別"].StartsWith("9A") || cellValues["扣繳類別"].StartsWith("9B")) && 合計金額 >= PublicVariable.領據執行業務所得課稅門檻) {
|
||||
errors.Add($"第 {rowId + 1} 列:執行業務所得不得超過 {PublicVariable.領據執行業務所得課稅門檻}(含),超過請拆成不同日期的領據");
|
||||
}
|
||||
|
||||
// 驗證差旅費的數值欄位
|
||||
foreach (var colTitle in travelFeeColumns)
|
||||
{
|
||||
if (cellValues.ContainsKey(colTitle) && !string.IsNullOrEmpty(cellValues[colTitle]) && !領據匯入驗證.IsValidDecimal(cellValues[colTitle]))
|
||||
{
|
||||
errors.Add($"第 {rowId + 1} 列,欄位「{colTitle}」:應為數值,實際值為「{cellValues[colTitle]}」");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 驗證重複資料
|
||||
/// - 同一檔案內重複(允許匯入,但回傳警告)
|
||||
/// - 本次匯入資料與資料庫現有資料重複的總筆數超過 5 筆(不允許匯入,回傳錯誤)
|
||||
/// 重複條件:活動日期 + 領款人姓名 + 計畫代號 + 活動名稱/事由
|
||||
/// </summary>
|
||||
public void ValidateDuplicates(string filePath, DbConnection conn, out List<string> errors, out List<string> warnings)
|
||||
{
|
||||
errors = new List<string>();
|
||||
warnings = new List<string>();
|
||||
|
||||
var workbook = LoadWorkbook(filePath);
|
||||
var sheet = workbook.GetSheetAt(0);
|
||||
|
||||
// 建立欄位名稱 → 欄位索引對照表
|
||||
var columnMap = new Dictionary<string, int>();
|
||||
var headerRow = sheet.GetRow(0);
|
||||
if (headerRow != null)
|
||||
{
|
||||
for (int i = 0; i <= headerRow.LastCellNum; i++)
|
||||
{
|
||||
var cell = headerRow.GetCell(i);
|
||||
if (cell == null) continue;
|
||||
string title = cell.ToString().Trim();
|
||||
if (!string.IsNullOrEmpty(title) && !columnMap.ContainsKey(title))
|
||||
columnMap[title] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// 收集每一列的鍵值:key → List<int> Excel 顯示列號
|
||||
var fileKeyRows = new Dictionary<string, List<int>>();
|
||||
|
||||
for (int rowId = 1; rowId <= sheet.LastRowNum; rowId++)
|
||||
{
|
||||
var row = sheet.GetRow(rowId);
|
||||
if (row == null) break;
|
||||
|
||||
string GetCellValue(string colTitle)
|
||||
{
|
||||
if (!columnMap.ContainsKey(colTitle)) return "";
|
||||
var c = row.GetCell(columnMap[colTitle]);
|
||||
return c == null ? "" : excel.CellValueToString(c).Trim();
|
||||
}
|
||||
|
||||
string 活動日期Raw = GetCellValue("活動日期");
|
||||
string 領款人姓名 = GetCellValue("領款人姓名");
|
||||
string 計畫代號 = GetCellValue("計畫代號");
|
||||
string 活動名稱事由 = GetCellValue("活動名稱/事由");
|
||||
|
||||
// 若整列為空則停止
|
||||
if (string.IsNullOrEmpty(活動日期Raw) && string.IsNullOrEmpty(領款人姓名) && string.IsNullOrEmpty(計畫代號))
|
||||
break;
|
||||
|
||||
// 重複鍵需要四個欄位都有值才做比對
|
||||
if (string.IsNullOrEmpty(活動日期Raw) || string.IsNullOrEmpty(領款人姓名) || string.IsNullOrEmpty(計畫代號))
|
||||
continue;
|
||||
|
||||
string key = string.Format("{0}|{1}|{2}|{3}", 活動日期Raw, 領款人姓名, 計畫代號, 活動名稱事由);
|
||||
|
||||
if (!fileKeyRows.ContainsKey(key))
|
||||
fileKeyRows[key] = new List<int>();
|
||||
fileKeyRows[key].Add(rowId + 1); // +1 因為 rowId=1 對應 Excel 第 2 列(含標頭)
|
||||
}
|
||||
|
||||
// ── 1. 檔案內重複(警告,不阻擋)────────────────────────────────
|
||||
foreach (var kv in fileKeyRows)
|
||||
{
|
||||
if (kv.Value.Count <= 1) continue;
|
||||
|
||||
string[] parts = kv.Key.Split('|');
|
||||
warnings.Add(string.Format(
|
||||
"檔案內重複:活動日期「{0}」、領款人「{1}」、計畫代號「{2}」、活動名稱事由「{3}」出現於第 {4} 列(共 {5} 筆)",
|
||||
parts[0], parts[1], parts[2], parts[3],
|
||||
string.Join("、", kv.Value.ConvertAll(r => r.ToString()).ToArray()),
|
||||
kv.Value.Count));
|
||||
}
|
||||
|
||||
// ── 2. 與資料庫現有資料比對 ──────────────────────────────────────
|
||||
// 每個唯一鍵查一次 DB,累計所有重複筆數;每筆有重複的都顯示給使用者
|
||||
var dac = new DAC_領據(conn);
|
||||
int totalDbDuplicates = 0;
|
||||
var dbDuplicateMessages = new List<string>();
|
||||
|
||||
foreach (var kv in fileKeyRows)
|
||||
{
|
||||
string[] parts = kv.Key.Split('|');
|
||||
if (!DateTime.TryParse(parts[0], out DateTime 活動日期)) continue;
|
||||
|
||||
string 領款人姓名DB = parts[1];
|
||||
string 計畫代號DB = parts[2];
|
||||
string 活動名稱事由DB = parts[3];
|
||||
|
||||
int dbCount = dac.CountDuplicates(活動日期, 領款人姓名DB, 計畫代號DB, 活動名稱事由DB);
|
||||
if (dbCount <= 0) continue;
|
||||
|
||||
totalDbDuplicates += dbCount;
|
||||
dbDuplicateMessages.Add(string.Format(
|
||||
"與現有資料重複:活動日期「{0}」、領款人「{1}」、計畫代號「{2}」、活動名稱事由「{3}」已有 {4} 筆",
|
||||
parts[0], 領款人姓名DB, 計畫代號DB, 活動名稱事由DB, dbCount));
|
||||
}
|
||||
|
||||
// 不論是否超過 5 筆,有重複的都要顯示;超過 5 筆則放入 errors 阻擋匯入
|
||||
if (dbDuplicateMessages.Count > 0)
|
||||
{
|
||||
if (totalDbDuplicates > 5)
|
||||
{
|
||||
errors.Add(string.Format("與現有資料重複共 {0} 筆(超過 5 筆),不允許匯入:", totalDbDuplicates));
|
||||
errors.AddRange(dbDuplicateMessages);
|
||||
}
|
||||
else
|
||||
{
|
||||
warnings.Add(string.Format("與現有資料重複共 {0} 筆:", totalDbDuplicates));
|
||||
warnings.AddRange(dbDuplicateMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void InsertOne<T>(T item)
|
||||
{
|
||||
var row = item as 領據匯入Item;
|
||||
|
||||
if (row == null)
|
||||
return;
|
||||
|
||||
using (var ts = DAC.NewTransactionScope())
|
||||
{
|
||||
try
|
||||
{
|
||||
// 1. 插入領據資料
|
||||
var dac領據 = new DAC_領據(connection);
|
||||
var dac講師 = new DAC_講師(connection);
|
||||
var dac非講師 = new DAC_非講師(connection);
|
||||
var dacBPAA = new DAC_BPAA();
|
||||
var 領據Item = new 領據Item();
|
||||
|
||||
var 講師_非講師編號 = string.Empty;
|
||||
if (row.身分別 == "講師")
|
||||
{
|
||||
var t = dac講師.Select(false, row.領款人姓名, null, null)
|
||||
.Where(x => string.Compare(x.姓名, row.領款人姓名) == 0
|
||||
&& string.Compare(x.身份證字號, row.身分證字號) == 0)
|
||||
.FirstOrDefault();
|
||||
if (t != null)
|
||||
講師_非講師編號 = t.編號.ToString();
|
||||
}
|
||||
else if (row.身分別 == "非講師")
|
||||
{
|
||||
var t = dac非講師.Select(false, null, row.領款人姓名, null, null, null)
|
||||
.Where(x => string.Compare(x.姓名, row.領款人姓名) == 0
|
||||
&& string.Compare(x.身分證字號, row.身分證字號) == 0)
|
||||
.FirstOrDefault();
|
||||
if (t != null)
|
||||
講師_非講師編號 = t.編號;
|
||||
}
|
||||
|
||||
if (講師_非講師編號 == string.Empty)
|
||||
{
|
||||
throw new Exception($"插入資料時發生錯誤: {row.領款人姓名} 不存在於系統內");
|
||||
}
|
||||
|
||||
var dataTable = dacBPAA.GetBpaaWithTYPlusNone();
|
||||
foreach (DataRow r in dataTable.Rows)
|
||||
{
|
||||
if (r["BPPYN"].ToString() == row.計畫代號)
|
||||
{
|
||||
領據Item.計畫名稱 = DAC.GetString(r["BPPYM"]);
|
||||
}
|
||||
}
|
||||
|
||||
領據Item.活動日期 = row.活動日期.Value;
|
||||
領據Item.身分別 = row.身分別;
|
||||
領據Item.講師_非講師編號 = 講師_非講師編號;
|
||||
領據Item.領款人姓名 = row.領款人姓名;
|
||||
領據Item.身分證字號 = row.身分證字號;
|
||||
領據Item.憑證類別 = row.憑證類別;
|
||||
領據Item.計畫代號 = row.計畫代號;
|
||||
領據Item.活動地點 = row.活動地點;
|
||||
領據Item.活動類別 = row.活動類別;
|
||||
領據Item.活動名稱事由 = row.活動名稱事由;
|
||||
領據Item.付款方式 = row.付款方式;
|
||||
領據Item.製單人員 = dac領據.CurrentUserId;
|
||||
dac領據.InsertOne(領據Item);
|
||||
|
||||
int 領據編號 = 領據Item.編號;
|
||||
|
||||
// 2. 如果有勞務費資料,插入勞務費表
|
||||
if (!string.IsNullOrEmpty(row.勞務費費用別) || row.單價.HasValue || row.數量.HasValue || row.服務費.HasValue)
|
||||
{
|
||||
var dac勞務費 = new DAC_勞務費(connection);
|
||||
var 勞務費Item = new 勞務費Item();
|
||||
var a扣繳類別 = 扣繳類別.MapValue(row.扣繳類別);
|
||||
|
||||
var 扣繳稅額 = 0;
|
||||
var 扣繳稅額result = new Services.領據處理().CalcTax((int)((decimal)row.單價 * row.數量), a扣繳類別);
|
||||
if (扣繳稅額result.Success)
|
||||
{
|
||||
扣繳稅額 = DAC.GetInt32(扣繳稅額result.Data);
|
||||
}
|
||||
|
||||
勞務費Item.領據編號 = 領據編號;
|
||||
勞務費Item.費用別 = row.勞務費費用別;
|
||||
勞務費Item.扣繳類別 = a扣繳類別;
|
||||
勞務費Item.單價 = row.單價.HasValue ? row.單價.Value : 0;
|
||||
勞務費Item.數量 = row.數量.HasValue ? row.數量.Value : 0;
|
||||
勞務費Item.單位 = row.單位;
|
||||
勞務費Item.服務費 = row.服務費.HasValue ? row.服務費.Value : 0;
|
||||
勞務費Item.應扣繳稅額 = 扣繳稅額;
|
||||
dac勞務費.InsertOne(勞務費Item);
|
||||
}
|
||||
|
||||
// 3. 如果有差旅費資料,插入差旅費表
|
||||
if (!string.IsNullOrEmpty(row.差旅票價資訊) || row.捷運公車.HasValue || row.火車.HasValue ||
|
||||
row.計程車.HasValue || row.高鐵飛機.HasValue || row.自行開車.HasValue ||
|
||||
row.過路費停車費.HasValue || row.住宿費.HasValue)
|
||||
{
|
||||
var dac差旅費 = new DAC_差旅費(connection);
|
||||
var 差旅費Item = new 差旅費Item();
|
||||
差旅費Item.領據編號 = 領據編號;
|
||||
差旅費Item.費用別 = 差旅費_費用別.交通住宿費;
|
||||
差旅費Item.票價資訊 = row.差旅票價資訊;
|
||||
差旅費Item.起點 = row.起點;
|
||||
差旅費Item.訖點 = row.訖點;
|
||||
差旅費Item.捷運公車 = row.捷運公車.HasValue ? row.捷運公車.Value : 0;
|
||||
差旅費Item.火車 = row.火車.HasValue ? row.火車.Value : 0;
|
||||
差旅費Item.計程車 = row.計程車.HasValue ? row.計程車.Value : 0;
|
||||
差旅費Item.高鐵飛機 = row.高鐵飛機.HasValue ? row.高鐵飛機.Value : 0;
|
||||
差旅費Item.自行開車 = row.自行開車.HasValue ? row.自行開車.Value : 0;
|
||||
差旅費Item.過路費停車費 = row.過路費停車費.HasValue ? row.過路費停車費.Value : 0;
|
||||
差旅費Item.住宿費 = row.住宿費.HasValue ? row.住宿費.Value : 0;
|
||||
dac差旅費.InsertOne(差旅費Item);
|
||||
}
|
||||
|
||||
ts.Complete();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"插入資料時發生錯誤: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ImportRowErrorMessage<T>(T item, string errorMessage)
|
||||
{
|
||||
var row = item as 領據匯入Item;
|
||||
if (row != null)
|
||||
{
|
||||
return $"領款人:{row.領款人姓名},憑證類別:{row.憑證類別},計畫代號:{row.計畫代號},錯誤原因:{errorMessage}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ImportRowErrorMessage(item, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user