From 812ee2ffc087565175b875f3a44c5cc2aee5e5a5 Mon Sep 17 00:00:00 2001 From: "jay.chang" Date: Tue, 9 Jul 2024 15:24:08 +0800 Subject: [PATCH] =?UTF-8?q?[WebApi]=E6=B0=B4=E9=9B=BB=E5=A0=B1=E8=A1=A8?= =?UTF-8?q?=E6=96=B0=E5=A2=9ECSV=E6=AA=94=E5=8C=AF=E5=87=BA=E3=80=81?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E6=95=B4=E6=89=B9=E8=A8=AD=E5=AE=9A=EF=BC=8C?= =?UTF-8?q?=E7=B7=8A=E6=80=A5=E6=87=89=E8=AE=8A=E5=8A=A0=E5=85=A5Loading?= =?UTF-8?q?=E3=80=81=E8=AA=BF=E6=95=B4=E9=83=A8=E5=88=86=E8=AA=9E=E6=B3=95?= =?UTF-8?q?=E6=94=B9=E5=96=84=E6=9F=A5=E8=A9=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiControllers/BuildController.cs | 4 +- .../EmergencyRecordController.cs | 2 +- .../ApiControllers/HistoryController.cs | 4 +- .../ApiControllers/TenantBillController.cs | 835 +++++++++++++++--- FrontendWebApi/Models/Bill.cs | 16 +- .../Views/EmergencyRecord/Index.cshtml | 31 +- FrontendWebApi/Views/Shared/_Layout.cshtml | 37 +- 7 files changed, 785 insertions(+), 144 deletions(-) diff --git a/FrontendWebApi/ApiControllers/BuildController.cs b/FrontendWebApi/ApiControllers/BuildController.cs index c9482fa..ba17601 100644 --- a/FrontendWebApi/ApiControllers/BuildController.cs +++ b/FrontendWebApi/ApiControllers/BuildController.cs @@ -47,14 +47,14 @@ namespace FrontendWebApi.ApiControllers ( SELECT w.get_value FROM api_weateher w - WHERE w.weather_type = 'Wx' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC + WHERE w.weather_type = 'Wx' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC, w.id desc limit 1 ) AS WxText, ( SELECT wd.WeatherKey FROM api_weateher w LEFT JOIN weather_description wd ON w.get_value = wd.WeatherValue - WHERE w.weather_type = 'WxV' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC + WHERE w.weather_type = 'WxV' AND @DateNow BETWEEN w.start_time AND w.end_time ORDER BY created_at DESC, w.id desc limit 1 ) AS Wx, ( diff --git a/FrontendWebApi/ApiControllers/EmergencyRecordController.cs b/FrontendWebApi/ApiControllers/EmergencyRecordController.cs index 21a3159..af98d24 100644 --- a/FrontendWebApi/ApiControllers/EmergencyRecordController.cs +++ b/FrontendWebApi/ApiControllers/EmergencyRecordController.cs @@ -67,7 +67,7 @@ namespace FrontendWebApi.ApiControllers if (post.dateranger != null) { var date = post.dateranger.Replace(" ", "").Split("-"); - sqlplus += $"and ee.created_at between '{date[0].Replace(" / ", " - ")} 00:00:00' and '{date[1].Replace(" / ", " - ")} 23:59:59'"; + sqlplus += $"and ee.created_at between '{date[0].Replace("/", "-")} 00:00:00' and '{date[1].Replace("/", "-")} 23:59:59'"; } EmergencyRecordEvent = await backendRepository.GetAllAsync($@" diff --git a/FrontendWebApi/ApiControllers/HistoryController.cs b/FrontendWebApi/ApiControllers/HistoryController.cs index 33a89d7..1baac08 100644 --- a/FrontendWebApi/ApiControllers/HistoryController.cs +++ b/FrontendWebApi/ApiControllers/HistoryController.cs @@ -1144,7 +1144,7 @@ namespace FrontendWebApi.ApiControllers and di.device_system_tag COLLATE utf8mb4_unicode_ci = d.device_system_tag and di.device_name_tag COLLATE utf8mb4_unicode_ci = d.device_name_tag and d.deleted = 0 - where di.deleted = 0 and di.unit is not null and d.device_number IN @Device_number + where di.deleted = 0 and d.device_number IN @Device_number ) temp inner join building b on temp.device_building_tag COLLATE utf8mb4_unicode_ci = b.building_tag and b.deleted = 0 inner join variable v1 on temp.device_system_tag COLLATE utf8mb4_unicode_ci = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2' @@ -1364,7 +1364,7 @@ namespace FrontendWebApi.ApiControllers and di.device_system_tag COLLATE utf8mb4_unicode_ci = d.device_system_tag and di.device_name_tag COLLATE utf8mb4_unicode_ci = d.device_name_tag and d.deleted = 0 - where di.deleted = 0 and di.unit is not null and d.device_number = @Device_number + where di.deleted = 0 and d.device_number = @Device_number ) temp inner join building b on temp.device_building_tag COLLATE utf8mb4_unicode_ci = b.building_tag and b.deleted = 0 inner join variable v1 on temp.device_system_tag COLLATE utf8mb4_unicode_ci = v1.system_value and v1.deleted = 0 and v1.system_type = 'device_system_category_layer2' diff --git a/FrontendWebApi/ApiControllers/TenantBillController.cs b/FrontendWebApi/ApiControllers/TenantBillController.cs index 1fc6fff..81dcf9a 100644 --- a/FrontendWebApi/ApiControllers/TenantBillController.cs +++ b/FrontendWebApi/ApiControllers/TenantBillController.cs @@ -22,6 +22,15 @@ using System.Reflection; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Data.SqlTypes; using System.Linq; +using NPOI.SS.UserModel; +using NPOI.XSSF.UserModel; +using NPOI.Util; +using System.Globalization; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.IO.Compression; + @@ -285,18 +294,20 @@ namespace FrontendWebApi.ApiControllers string sqlString = null; string result = "0"; - if (tb.start_timestamp == "" || tb.end_timestamp == "" || tb.tenant_guid == "" || tb.tenant_guid == null) + if (string.IsNullOrEmpty(tb.start_timestamp) || string.IsNullOrEmpty(tb.end_timestamp) || string.IsNullOrEmpty(tb.tenant_guid)) { - sqlString = $@"UPDATE {TenantBilltable} - set tenant_name = (SELECT tenant_name from archive_electric_meter_tenant_list - WHERE tenant_guid = '{tb.tenant_guid}'), start_timestamp = '{start_timestamp}',end_timestamp = '{end_timestamp}' , - result= 0, - bill = 0, - updated_at = '{updated_at}', - tenant_guid = '{tb.tenant_guid}' - WHERE device_number = '{tb.device_number}'"; + sqlString = $@" + UPDATE {TenantBilltable} + SET tenant_name = (SELECT tenant_name FROM archive_electric_meter_tenant_list WHERE tenant_guid = @tenant_guid), + start_timestamp = @start_timestamp, + end_timestamp = @end_timestamp, + result = 0, + bill = 0, + updated_at = @updated_at, + tenant_guid = @tenant_guid + WHERE device_number = @device_number"; - await backendRepository.ExecuteSql(sqlString); + await backendRepository.ExecuteSql(sqlString, new { tb.tenant_guid, start_timestamp, end_timestamp, updated_at, tb.device_number }); apiResult.Code = "0000"; apiResult.Msg = "資料填寫不完整"; @@ -304,81 +315,71 @@ namespace FrontendWebApi.ApiControllers } else { - List howManyMonth = new List(); - List existMonth = new List(); DateTime date1 = DateTime.Parse(start_timestamp); DateTime date2 = DateTime.Parse(end_timestamp); int monthsApart = ((date2.Year - date1.Year) * 12) + date2.Month - date1.Month; - // 找出資料庫存在的水電月份表 - string checkTabelSql = $@"SELECT TABLE_NAME - FROM INFORMATION_SCHEMA.TABLES - WHERE TABLE_SCHEMA like 'ibms_dome_%' and TABLE_NAME like 'archive_electric_water_meter_day_%'"; + string checkTabelSql = @" + SELECT TABLE_NAME + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA LIKE 'ibms_dome_%' AND TABLE_NAME LIKE 'archive_electric_water_meter_day_%'"; var existTable = await backendRepository.GetAllAsync(checkTabelSql); - for (var i = 0; i <= monthsApart; i++) - { - howManyMonth.Add($@"archive_electric_water_meter_day_{date1.AddMonths(i).ToString("yyyyMM")}"); - } - foreach (var item in existTable) - { - foreach (var data in howManyMonth) - { - if (item == data) - { - existMonth.Add(data); - } - } - } + List howManyMonth = Enumerable.Range(0, monthsApart + 1) + .Select(i => $"archive_electric_water_meter_day_{date1.AddMonths(i):yyyyMM}") + .ToList(); + var existMonth = existTable.Intersect(howManyMonth).ToList(); + if (existMonth.Count == 0) { - sqlString = $@"UPDATE {TenantBilltable} - set tenant_name = (SELECT tenant_name from archive_electric_meter_tenant_list - WHERE tenant_guid = '{tb.tenant_guid}'), start_timestamp = '{start_timestamp}',end_timestamp = '{end_timestamp}' , - result= 0, - bill = 0, - updated_at = '{updated_at}', - tenant_guid = '{tb.tenant_guid}' - WHERE device_number = '{tb.device_number}'"; + sqlString = $@" + UPDATE {TenantBilltable} + SET tenant_name = (SELECT tenant_name FROM archive_electric_meter_tenant_list WHERE tenant_guid = @tenant_guid), + start_timestamp = @start_timestamp, + end_timestamp = @end_timestamp, + result = 0, + bill = 0, + updated_at = @updated_at, + tenant_guid = @tenant_guid + WHERE device_number = @device_number"; + + await backendRepository.ExecuteSql(sqlString, new { tb.tenant_guid, start_timestamp, end_timestamp, updated_at, tb.device_number }); } else { - string month = $@" - SELECT start_timestamp,device_number, sub_result - FROM {existMonth[0]} - WHERE device_number = '{tb.device_number}'"; - for (var i = 1; i < existMonth.Count; i++) - { - month += $@"UNION ALL - SELECT start_timestamp,device_number, sub_result - FROM {existMonth[i]} - WHERE device_number = '{tb.device_number}' "; - } + var monthQueries = existMonth.Select(month => $@" + SELECT start_timestamp, device_number, sub_result + FROM {month} + WHERE device_number = @device_number"); + + string month = string.Join(" UNION ALL ", monthQueries); + string checkDataSql = $@" + SELECT SUM(sub_result) + FROM ({month}) combined_result + WHERE start_timestamp BETWEEN @start_timestamp AND @end_timestamp"; + var existData = await backendRepository.GetAllAsync(checkDataSql, new { tb.device_number, start_timestamp, end_timestamp }); - string checkDataSql = $@"(SELECT sum(sub_result) - FROM ( {month} - ) combined_result - WHERE start_timestamp BETWEEN '{start_timestamp}' and '{end_timestamp}') "; - var existData = await backendRepository.GetAllAsync(checkDataSql); if (existData.Count != 0) { - result = $@"(SELECT ROUND(sum(sub_result)) - FROM ( {month} - ) combined_result - WHERE start_timestamp BETWEEN '{start_timestamp}' and '{end_timestamp}') "; + result = $@" + SELECT ROUND(SUM(sub_result),2) + FROM ({month}) combined_result + WHERE start_timestamp BETWEEN @start_timestamp AND @end_timestamp"; } - sqlString = - $@"UPDATE {TenantBilltable} - set tenant_name = (SELECT tenant_name from archive_electric_meter_tenant_list WHERE tenant_guid = '{tb.tenant_guid}'), start_timestamp = '{start_timestamp}',end_timestamp = '{end_timestamp}' , - result= {result}, - bill = ROUND(result *(SELECT {bill_per} from {TenantListtable} WHERE tenant_guid = '{tb.tenant_guid}') ), - updated_at = '{updated_at}', - tenant_guid = '{tb.tenant_guid}' - WHERE device_number = '{tb.device_number}'"; + + sqlString = $@" + UPDATE {TenantBilltable} + SET tenant_name = (SELECT tenant_name FROM archive_electric_meter_tenant_list WHERE tenant_guid = @tenant_guid), + start_timestamp = @start_timestamp, + end_timestamp = @end_timestamp, + result = ({result}), + bill = ROUND(result * (SELECT {bill_per} FROM {TenantListtable} WHERE tenant_guid = @tenant_guid)), + updated_at = @updated_at, + tenant_guid = @tenant_guid + WHERE device_number = @device_number"; + + await backendRepository.ExecuteSql(sqlString, new { tb.tenant_guid, start_timestamp, end_timestamp, updated_at, tb.device_number }); } - - await backendRepository.ExecuteSql(sqlString); - } } catch (Exception exception) @@ -389,36 +390,34 @@ namespace FrontendWebApi.ApiControllers return apiResult; } + apiResult = await CheckDay(tb); + return apiResult; } + [HttpPost] public async Task> CheckDay([FromBody] TenantBill tb) { ApiResult apiResult = new ApiResult(); - if (tb.start_timestamp != "" && tb.end_timestamp != "" && tb.tenant_guid != "") + + if (!string.IsNullOrEmpty(tb.start_timestamp) && !string.IsNullOrEmpty(tb.end_timestamp) && !string.IsNullOrEmpty(tb.tenant_guid)) { - List tenantBill = new List(); try { - string sqlString = $@"select * from {TenantBilltable} WHERE tenant_guid= '{tb.tenant_guid}' and deleted = 0"; + string sqlString = $@" + SELECT * FROM {TenantBilltable} + WHERE tenant_guid = @tenant_guid AND deleted = 0"; + + var tenantBill = await backendRepository.GetAllAsync(sqlString, new { tb.tenant_guid }); - tenantBill = await backendRepository.GetAllAsync(sqlString); if (tenantBill.Count > 1) { - foreach (TenantBill t in tenantBill) + if (tenantBill.Any(t => t.start_timestamp != tb.start_timestamp || t.end_timestamp != tb.end_timestamp)) { - if (t.start_timestamp == tb.start_timestamp && t.end_timestamp == tb.end_timestamp) - { - continue; - } - else - { - apiResult.Code = "0001"; - apiResult.Msg = "該用戶設備的起訖日期不一致,是否將所有設備起訖日期調為一致?"; - return apiResult; - - } + apiResult.Code = "0001"; + apiResult.Msg = "該用戶設備的起訖日期不一致,是否將所有設備起訖日期調為一致?"; + return apiResult; } apiResult.Code = "0000"; @@ -431,38 +430,58 @@ namespace FrontendWebApi.ApiControllers apiResult.Msg = "確認日期失敗。"; Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } - + } + else + { + apiResult.Code = "0000"; + apiResult.Msg = "修改成功且不執行CheckDay"; } apiResult.Code = "0000"; - apiResult.Msg = "修改成功且不執行CheckDay"; + apiResult.Msg = "修改成功且該用戶的所有設備日期一致"; return apiResult; } + [HttpPost] public async Task> ChangeDay([FromBody] TenantBill tb) { ApiResult apiResult = new ApiResult(); List tenantBill = new List(); + string sqlString = ""; + string sWhere = ""; try { - string sqlString = $@"select * from {TenantBilltable} WHERE tenant_guid= '{tb.tenant_guid}' and deleted = 0"; - - tenantBill = await backendRepository.GetAllAsync(sqlString); - foreach (TenantBill t in tenantBill) + if (tb.tenant_guid != null) { - if (t.start_timestamp == tb.start_timestamp && t.end_timestamp == tb.end_timestamp) + sqlString = $@" + SELECT * FROM {TenantBilltable} + WHERE tenant_guid = @tenant_guid AND deleted = 0"; + } + else + { + if (tb.building_tag != null) { - continue; + sWhere = "AND device_building_tag = @building_tag"; } - else + sqlString = $@" + SELECT * FROM archive_electric_meter_tenant_bill a + JOIN device d ON a.device_number = d.device_number AND d.deleted = 0 + WHERE a.deleted = 0 {sWhere}"; + } + + tenantBill = await backendRepository.GetAllAsync(sqlString, tb); + + var updateTasks = tenantBill + .Where(t => t.start_timestamp != tb.start_timestamp || t.end_timestamp != tb.end_timestamp) + .Select(t => { t.start_timestamp = tb.start_timestamp; t.end_timestamp = tb.end_timestamp; - t.tableType = t.device_name_tag == "E4" ? "elec": "water"; - await UpdateTenantBill(t); - } - } + t.tableType = t.device_name_tag == "E4" ? "elec" : "water"; + return UpdateTenantBill(t); + }); + await Task.WhenAll(updateTasks); apiResult.Code = "0000"; apiResult.Msg = "修改成功"; @@ -485,24 +504,28 @@ namespace FrontendWebApi.ApiControllers try { - List buildings = tb.building_tag_list; - string building_tag = ""; - foreach (var item in buildings) - { - if (item == buildings[0]) - { - building_tag = item == "D2" ? $@"device_building_tag = 'D1' and a.deleted = 0 || device_building_tag = '{item}' and a.deleted = 0" : $@"device_building_tag = '{item}' and a.deleted = 0" ; - } - else - { - building_tag += item == "D2" ? $@"|| device_building_tag = 'D1' and a.deleted = 0 || device_building_tag = '{item}' and a.deleted = 0" : $@"|| device_building_tag = '{item}' and a.deleted = 0"; - } - } + //List buildings = tb.building_tag_list; + //string building_tag = ""; + //foreach (var item in buildings) + //{ + // if (item == buildings[0]) + // { + // building_tag = item == "D2" ? $@"device_building_tag = 'D1' and a.deleted = 0 || device_building_tag = '{item}' and a.deleted = 0" : $@"device_building_tag = '{item}' and a.deleted = 0"; + // } + // else + // { + // building_tag += item == "D2" ? $@"|| device_building_tag = 'D1' and a.deleted = 0 || device_building_tag = '{item}' and a.deleted = 0" : $@"|| device_building_tag = '{item}' and a.deleted = 0"; + // } + //} + // string checkDataSql = $@"select * from archive_electric_meter_tenant_bill a + // join device c on a.device_number = c.device_number + // WHERE tenant_name is not null and tenant_guid is not null and tenant_name != '' and tenant_guid !='' + //AND ({building_tag})"; + string checkDataSql = $@"select * from archive_electric_meter_tenant_bill a - join device c on a.device_number = c.device_number WHERE tenant_name is not null and tenant_guid is not null and tenant_name != '' and tenant_guid !='' - AND ({building_tag})"; - var existData = await backendRepository.GetAllAsync(checkDataSql); + AND a.deleted = 0"; + var existData = await backendRepository.GetAllAsync(checkDataSql); if (existData.Count != 0) { string sqlString = @@ -533,7 +556,6 @@ namespace FrontendWebApi.ApiControllers FROM archive_electric_meter_tenant_bill a JOIN archive_electric_meter_tenant_list b ON a.tenant_guid = b.tenant_guid JOIN device c ON a.device_number = c.device_number - WHERE {building_tag} GROUP BY a.tenant_name ) AS subquery_alias;"; @@ -553,18 +575,16 @@ namespace FrontendWebApi.ApiControllers } else { - var data = new { Code = "0001",Msg = "還沒有選擇用戶,無法匯出檔案。"}; + var data = new { Code = "0001", Msg = "還沒有選擇用戶,無法匯出檔案。" }; return StatusCode(400, data); } } catch (Exception exception) { Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + var data = new { Code = "9999", Msg = "匯出失敗。" }; + return StatusCode(500, data); } - return new FileContentResult(new byte[0], "application/pdf") - { - FileDownloadName = "Empty.pdf" - }; } public string CreateOutputForm(List outputBill, List device) @@ -659,6 +679,13 @@ namespace FrontendWebApi.ApiControllers var devices = device.Where(x => x.tenant_guid == item.tenant_guid).Select(x => x.full_name).ToList(); string deviceList = string.Join(" , ", devices); + // 設備列表長度閥值,原因為設備如果超過2頁A4會發生內容重疊問題 + int maxLength = 1050; + if (deviceList.Length > maxLength) + { + deviceList = deviceList.Substring(0, maxLength) + "..."; + } + bill += @$"
Taipei Dome Logo @@ -694,7 +721,7 @@ namespace FrontendWebApi.ApiControllers

設備列表

- {deviceList} + {deviceList}
@@ -716,5 +743,571 @@ namespace FrontendWebApi.ApiControllers } } + + [HttpPost] + public async Task OutputTenantBillCSV([FromBody] TenantBill tb) + { + ApiResult apiResult = new ApiResult(); + var fileDateName = DateTime.Now.ToString("yyyy-MM-ddTHH-mm-ss"); + var waterMeterFileName = $"水電報表_水錶_{fileDateName}.csv"; + var electricMeterFileName = $"水電報表_電錶_{fileDateName}.csv"; + var zipFileName = $"水電報表_{fileDateName}.zip"; + + try + { + #region 撈數據 + string dateRangeSQL = $@"SELECT MIN(CAST(start_timestamp AS DATETIME)) start_timestamp, + MAX(CAST(end_timestamp AS DATETIME)) end_timestamp + FROM archive_electric_meter_tenant_bill WHERE deleted = 0;"; + var dateRange = await backendRepository.GetOneAsync(dateRangeSQL); + List howManyMonth = new List(); + List existMonth = new List(); + DateTime date1 = DateTime.Parse(dateRange.start_timestamp); + DateTime date2 = DateTime.Parse(dateRange.end_timestamp); + string month = ""; + int monthsApart = ((date2.Year - date1.Year) * 12) + date2.Month - date1.Month; + + // 找出資料庫存在的水電月份表 + string checkTabelSql = $@"SELECT TABLE_NAME + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA like 'ibms_dome_%' and TABLE_NAME like 'archive_electric_water_meter_day_%'"; + var existTable = await backendRepository.GetAllAsync(checkTabelSql); + + for (var i = 0; i <= monthsApart; i++) + { + howManyMonth.Add($@"archive_electric_water_meter_day_{date1.AddMonths(i).ToString("yyyyMM")}"); + } + foreach (var item in existTable) + { + foreach (var temp in howManyMonth) + { + if (item == temp) + { + existMonth.Add(temp); + } + } + } + // 判斷是否有資料 + if (existMonth.Count == 0) + { + var msg = new { Code = "0001", Msg = "還沒有選擇用戶,無法匯出檔案。" }; + return StatusCode(400, msg); + } + else + { + month = $@" SELECT device_number, start_timestamp, sub_result + FROM {existMonth[0]}"; + for (var i = 1; i < existMonth.Count; i++) + { + // 要有空格 + month += $@" UNION ALL + SELECT device_number, start_timestamp, sub_result + FROM {existMonth[i]}"; + } + } + // 查詢SQL + var sql = @$" + -- 删除臨時表 + DROP TEMPORARY TABLE IF EXISTS temp_combined_data; + + -- 建立臨時表 + CREATE TEMPORARY TABLE temp_combined_data ( + device_number VARCHAR(255), + start_timestamp DATETIME, + sub_result decimal(15,3) + ); + + -- 插入數據 + INSERT INTO temp_combined_data (device_number, start_timestamp, sub_result) + {month}; + + -- 優化后的查詢 + SELECT + c.tenant_name, + b.device_name_tag, + a.device_number, + d.full_name, + a.start_timestamp AS date, + CASE + WHEN b.device_name_tag = 'E4' THEN c.bill_perKWH + WHEN b.device_name_tag = 'W1' THEN c.bill_perRCV + END AS bill_per, + ROUND(a.sub_result, 2) sub_result, + ROUND(CASE + WHEN b.device_name_tag = 'E4' THEN c.bill_perKWH + WHEN b.device_name_tag = 'W1' THEN c.bill_perRCV + END * ROUND(a.sub_result, 2)) AS total_bill, + b.start_timestamp, + b.end_timestamp, + d.device_building_tag building_tag + FROM + temp_combined_data a + JOIN + archive_electric_meter_tenant_bill b ON a.device_number COLLATE utf8mb4_unicode_ci = b.device_number AND b.deleted = 0 + JOIN + archive_electric_meter_tenant_list c ON b.tenant_guid = c.tenant_guid + JOIN + device d ON d.device_number = a.device_number COLLATE utf8mb4_unicode_ci + WHERE + a.start_timestamp BETWEEN b.start_timestamp AND b.end_timestamp + ORDER BY b.device_name_tag,tenant_name,a.device_number,date; + + -- 删除臨時表 + DROP TEMPORARY TABLE IF EXISTS temp_combined_data;"; + + var outputBillExcel = await backendRepository.GetAllAsync(sql); + #endregion + + // 分別篩選水錶和電錶的數據 + var waterMeterData = outputBillExcel.Where(x => x.device_name_tag == "W1" && x.building_tag == tb.building_tag).ToList(); + var electricMeterData = outputBillExcel.Where(x => x.device_name_tag == "E4" && x.building_tag == tb.building_tag).ToList(); + + // 檢查是否有水錶或電錶數據 + //if (waterMeterData.Count == 0 && electricMeterData.Count == 0) + //{ + // var msg = new { Code = "0002", Msg = "該棟沒有可匯出的水錶或電錶數據。" }; + // return StatusCode(400, msg); + //} + + if (tb.tableType == "elec" && electricMeterData.Count == 0) + { + var msg = new { Code = "0002", Msg = "該棟沒有可匯出的電錶數據。" }; + return StatusCode(400, msg); + } + else if (tb.tableType == "water" && waterMeterData.Count == 0) + { + var msg = new { Code = "0002", Msg = "該棟沒有可匯出的水錶數據。" }; + return StatusCode(400, msg); + } + + // 生成CSV文件 + string waterMeterCsv = null; + string electricMeterCsv = null; + if (waterMeterData.Count > 0) + { + waterMeterCsv = GenerateCsv(waterMeterData); + } + if (electricMeterData.Count > 0) + { + electricMeterCsv = GenerateCsv(electricMeterData); + } + + // 返回CSV文件 + if (tb.tableType == "elec" && electricMeterCsv != null) + { + using (var electricMemoryStream = new MemoryStream()) + { + using (var streamWriter = new StreamWriter(electricMemoryStream, Encoding.UTF8)) + { + streamWriter.Write(electricMeterCsv); + } + return File(electricMemoryStream.ToArray(), "text/csv", electricMeterFileName); + } + } + else if (tb.tableType == "water" && waterMeterCsv != null) + { + using (var waterMemoryStream = new MemoryStream()) + { + using (var streamWriter = new StreamWriter(waterMemoryStream, Encoding.UTF8)) + { + streamWriter.Write(waterMeterCsv); + } + return File(waterMemoryStream.ToArray(), "text/csv", electricMeterFileName); + } + } + else + { + var msg = new { Code = "0003", Msg = "無效的表格類型。" }; + return StatusCode(400, msg); + } + + + + //// 創建ZIP檔案 + //using (var zipMemoryStream = new MemoryStream()) + //{ + // using (var archive = new ZipArchive(zipMemoryStream, ZipArchiveMode.Create, true)) + // { + // if (waterMeterData.Count > 0) + // { + // var waterEntry = archive.CreateEntry(waterMeterFileName); + // using (var entryStream = waterEntry.Open()) + // using (var streamWriter = new StreamWriter(entryStream, Encoding.UTF8)) + // { + // streamWriter.Write(waterMeterCsv); + // } + // } + + // if (electricMeterData.Count > 0) + // { + // var electricEntry = archive.CreateEntry(electricMeterFileName); + // using (var entryStream = electricEntry.Open()) + // using (var streamWriter = new StreamWriter(entryStream, Encoding.UTF8)) + // { + // streamWriter.Write(electricMeterCsv); + // } + // } + // } + + // zipMemoryStream.Seek(0, SeekOrigin.Begin); + // return File(zipMemoryStream.ToArray(), "application/zip", zipFileName); + //} + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + return Json(apiResult); + } + } + + + private string GenerateCsv(List data) + { + StringBuilder csv = new StringBuilder(); + + // 添加CSV標題行 + csv.AppendLine("用戶,設備代碼,設備名稱,日期,用電單價(元/度),當日用電(kWh),電費(元),起訖時間"); + + // 添加數據行 + foreach (var item in data) + { + csv.AppendLine($"{item.tenant_name},{item.device_number},{item.full_name},{item.date.ToString("yyyy/MM/dd")},{item.bill_per},{item.sub_result},{item.total_bill},{item.start_timestamp}~{item.end_timestamp}"); + } + + return csv.ToString(); + } + + + [HttpPost] + public async Task OutputTenantBillExcel([FromBody] TenantBill tb) + { + ApiResult apiResult = new ApiResult(); + var fileDateName = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"); + var fileName = "水電報表_" + fileDateName + ".xlsx"; + + XSSFWorkbook workbook = new XSSFWorkbook(); + try + { + string dateRangeSQL = $@"SELECT MIN(CAST(start_timestamp AS DATETIME)) start_timestamp, + MAX(CAST(end_timestamp AS DATETIME)) end_timestamp + FROM archive_electric_meter_tenant_bill WHERE deleted = 0;"; + var dateRange = await backendRepository.GetOneAsync(dateRangeSQL); + List howManyMonth = new List(); + List existMonth = new List(); + DateTime date1 = DateTime.Parse(dateRange.start_timestamp); + DateTime date2 = DateTime.Parse(dateRange.end_timestamp); + string month = ""; + int monthsApart = ((date2.Year - date1.Year) * 12) + date2.Month - date1.Month; + + // 找出資料庫存在的水電月份表 + string checkTabelSql = $@"SELECT TABLE_NAME + FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA like 'ibms_dome_%' and TABLE_NAME like 'archive_electric_water_meter_day_%'"; + var existTable = await backendRepository.GetAllAsync(checkTabelSql); + + for (var i = 0; i <= monthsApart; i++) + { + howManyMonth.Add($@"archive_electric_water_meter_day_{date1.AddMonths(i).ToString("yyyyMM")}"); + } + foreach (var item in existTable) + { + foreach (var temp in howManyMonth) + { + if (item == temp) + { + existMonth.Add(temp); + } + } + } + // 判斷是否有資料 + if (existMonth.Count == 0) + { + var msg = new { Code = "0001", Msg = "還沒有選擇用戶,無法匯出檔案。" }; + return StatusCode(400, msg); + } + else + { + month = $@" SELECT device_number, start_timestamp, sub_result + FROM {existMonth[0]}"; + for (var i = 1; i < existMonth.Count; i++) + { + // 要有空格 + month += $@" UNION ALL + SELECT device_number, start_timestamp, sub_result + FROM {existMonth[i]}"; + } + } + // 查詢SQL + var sql = @$" + -- 删除臨時表 + DROP TEMPORARY TABLE IF EXISTS temp_combined_data; + + -- 建立臨時表 + CREATE TEMPORARY TABLE temp_combined_data ( + device_number VARCHAR(255), + start_timestamp DATETIME, + sub_result decimal(15,3) + ); + + -- 插入數據 + INSERT INTO temp_combined_data (device_number, start_timestamp, sub_result) + {month}; + + -- 優化后的查詢 + SELECT + c.tenant_name, + b.device_name_tag, + a.device_number, + d.full_name, + a.start_timestamp AS date, + CASE + WHEN b.device_name_tag = 'E4' THEN c.bill_perKWH + WHEN b.device_name_tag = 'W1' THEN c.bill_perRCV + END AS bill_per, + ROUND(a.sub_result, 2) sub_result, + ROUND(CASE + WHEN b.device_name_tag = 'E4' THEN c.bill_perKWH + WHEN b.device_name_tag = 'W1' THEN c.bill_perRCV + END * ROUND(a.sub_result, 2)) AS total_bill, + b.start_timestamp, + b.end_timestamp, + d.device_building_tag building_tag + FROM + temp_combined_data a + JOIN + archive_electric_meter_tenant_bill b ON a.device_number COLLATE utf8mb4_unicode_ci = b.device_number AND b.deleted = 0 + JOIN + archive_electric_meter_tenant_list c ON b.tenant_guid = c.tenant_guid + JOIN + device d ON d.device_number = a.device_number COLLATE utf8mb4_unicode_ci + WHERE + a.start_timestamp BETWEEN b.start_timestamp AND b.end_timestamp + ORDER BY b.device_name_tag,tenant_name,a.device_number,date; + + -- 删除臨時表 + DROP TEMPORARY TABLE IF EXISTS temp_combined_data;"; + + var outputBillExcel = await backendRepository.GetAllAsync(sql); + + + #region export file progress + #region excel設定 + IFont font12 = workbook.CreateFont(); + font12.FontName = "新細明體"; + font12.FontHeightInPoints = 12; + ICellStyle style12 = workbook.CreateCellStyle(); + style12.SetFont(font12); + style12.Alignment = HorizontalAlignment.Center; + style12.VerticalAlignment = VerticalAlignment.Center; + IFont font12Times = workbook.CreateFont(); + font12Times.FontName = "Times New Roman"; + font12Times.FontHeightInPoints = 12; + IFont font18 = workbook.CreateFont(); + font18.FontName = "新細明體"; + font18.FontHeightInPoints = 18; + font18.IsBold = true; + ICellStyle styleTitle18 = workbook.CreateCellStyle(); + styleTitle18.SetFont(font18); + styleTitle18.Alignment = HorizontalAlignment.Center; + styleTitle18.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLeft12 = workbook.CreateCellStyle(); + styleLeft12.SetFont(font12); + styleLeft12.Alignment = HorizontalAlignment.Left; + styleLeft12.VerticalAlignment = VerticalAlignment.Center; + ICellStyle styleLine12 = workbook.CreateCellStyle(); + styleLine12.SetFont(font12); + styleLine12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center; + styleLine12.VerticalAlignment = VerticalAlignment.Center; + styleLine12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + styleLine12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + ICellStyle stylein12 = workbook.CreateCellStyle(); + stylein12.SetFont(font12Times); + stylein12.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Left; + stylein12.VerticalAlignment = VerticalAlignment.Center; + stylein12.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; + stylein12.WrapText = true; + #endregion + //var data = he.OrderByDescending(x => x.deviceName).ThenBy(x => x.type).ToList(); + var data = outputBillExcel.Where(x => x.building_tag == $"{tb.building_tag}").ToList(); + + if (data.Count > 0) + { + string lastDeviceItem = string.Empty; + string lastDevice = string.Empty; + string lastType = string.Empty; + string type = data[0].device_name_tag; + string typeName = type == "E4" ? "電錶" : "水錶"; + string bill_per = type == "E4" ? "用電單價(元/度)" : "用水單價(元/度)"; + string sub_result = type == "E4" ? "當日用電( kWh)" : "當日用水( m³)"; + string total_bill = type == "E4" ? "電費(元)" : "水費(元)"; + + int RowPosition = 0; + IRow row; + ISheet sheet; + #region set cell + sheet = workbook.CreateSheet($"{typeName}"); + row = sheet.CreateRow(RowPosition); + for (var i = 0; i < 8; i++) + { + sheet.SetColumnWidth(i, 4 * 160 * 12); + } + + ICell cell = row.CreateCell(0); + cell = row.CreateCell(0); + cell.SetCellValue("用戶"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(1); + cell.SetCellValue("設備代碼"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(2); + cell.SetCellValue("設備名稱"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(3); + cell.SetCellValue("日期"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(4); + cell.SetCellValue(bill_per); + cell.CellStyle = styleLine12; + cell = row.CreateCell(5); + cell.SetCellValue(sub_result); + cell.CellStyle = styleLine12; + cell = row.CreateCell(6); + cell.SetCellValue(total_bill); + cell.CellStyle = styleLine12; + cell = row.CreateCell(7); + cell.SetCellValue("起訖時間"); + cell.CellStyle = styleLine12; + #endregion + + foreach (var d in data) + { + if (RowPosition == 0 && lastType == "") + { + lastType = d.device_name_tag; //第一次不用建立 sheet; + } + if (d.device_name_tag != lastType) + { + RowPosition = 0; + type = d.device_name_tag; + lastType = type; + typeName = type == "E4" ? "電錶" : "水錶"; + bill_per = type == "E4" ? "用電單價(元/度)" : "用水單價(元/度)"; + sub_result = type == "E4" ? "當日用電( kWh)" : "當日用水( m³)"; + total_bill = type == "E4" ? "電費(元)" : "水費(元)"; + sheet = workbook.CreateSheet($"{typeName}"); + + #region set cell + row = sheet.CreateRow(RowPosition); + for (var i = 0; i < 8; i++) + { + sheet.SetColumnWidth(i, 4 * 160 * 12); + } + cell = row.CreateCell(0); + cell.SetCellValue("用戶"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(1); + cell.SetCellValue("設備代碼"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(2); + cell.SetCellValue("設備名稱"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(3); + cell.SetCellValue("日期"); + cell.CellStyle = styleLine12; + cell = row.CreateCell(4); + cell.SetCellValue(bill_per); + cell.CellStyle = styleLine12; + cell = row.CreateCell(5); + cell.SetCellValue(sub_result); + cell.CellStyle = styleLine12; + cell = row.CreateCell(6); + cell.SetCellValue(total_bill); + cell.CellStyle = styleLine12; + cell = row.CreateCell(7); + cell.SetCellValue("起訖時間"); + cell.CellStyle = styleLine12; + #endregion + RowPosition = 1; + } + else + { + RowPosition += 1; + } + + row = sheet.CreateRow(RowPosition); + for (var i = 0; i < 8; i++) + { + cell = row.CreateCell(i); + if (i == 0) + { + cell.SetCellValue(d.tenant_name); + } + if (i == 1) + { + cell.SetCellValue(d.device_number); + } + if (i == 2) + { + cell.SetCellValue(d.full_name); + } + if (i == 3) + { + cell.SetCellValue(d.date.ToString("yyyy/MM/dd")); + } + if (i == 4) + { + cell.SetCellValue(d.bill_per); + } + if (i == 5) + { + cell.SetCellValue(d.sub_result.ToString()); + } + if (i == 6) + { + cell.SetCellValue(d.total_bill.ToString()); + } + if (i == 7) + { + cell.SetCellValue($"{d.start_timestamp}~{d.end_timestamp}"); + } + + cell.CellStyle = style12; + } + } + } + else + { + var msg = new { Code = "0001", Msg = "還沒有選擇用戶,無法匯出檔案。" }; + return StatusCode(400, msg); + } + #endregion + + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。 Msg: " + exception.Message; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + return Json(apiResult); + } + + var ms = new NpoiMemoryStream + { + AllowClose = false + }; + workbook.Write(ms); + ms.Flush(); + ms.Seek(0, SeekOrigin.Begin); + Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition"); + + return File(ms, "application/vnd.ms-excel", fileName); + } } } \ No newline at end of file diff --git a/FrontendWebApi/Models/Bill.cs b/FrontendWebApi/Models/Bill.cs index 783b230..723f3bf 100644 --- a/FrontendWebApi/Models/Bill.cs +++ b/FrontendWebApi/Models/Bill.cs @@ -29,7 +29,7 @@ namespace FrontendWebApi.Models public string end_timestamp { get; set; } public string device_name_tag { get; set; } public decimal result { get; set; } - public int bill { get; set; } + public decimal bill { get; set; } public string created_by { get; set; } public DateTime created_at { get; set; } public string updated_by { get; set; } @@ -49,15 +49,21 @@ namespace FrontendWebApi.Models public string start_timestamp { get; set; } public string end_timestamp { get; set; } public decimal elec_result { get; set; } - public int elec_bill { get; set; } + public decimal elec_bill { get; set; } public decimal water_result { get; set; } - public int water_bill { get; set; } + public decimal water_bill { get; set; } public decimal bill_perKWH { get; set; } public decimal bill_perRCV { get; set; } - public int total_bill { get; set; } + public decimal total_bill { get; set; } public string tenant_guid { get; set; } } - + public class OutputBillExcel : TenantBill + { + public DateTime date { get; set; } + public string bill_per { get; set; } + public decimal sub_result { get; set; } + public decimal total_bill { get; set; } + } } } \ No newline at end of file diff --git a/FrontendWebApi/Views/EmergencyRecord/Index.cshtml b/FrontendWebApi/Views/EmergencyRecord/Index.cshtml index d8b7644..a582b37 100644 --- a/FrontendWebApi/Views/EmergencyRecord/Index.cshtml +++ b/FrontendWebApi/Views/EmergencyRecord/Index.cshtml @@ -348,6 +348,12 @@
+
+
+ Loading... +
+

資料載入中...

+
@section Scripts {