From 2a894546288565f776d5fc69b98060191194d42c Mon Sep 17 00:00:00 2001 From: "jay.chang" Date: Fri, 26 Jan 2024 11:35:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=B5=90=E7=AE=97=E8=A1=A8SQ?= =?UTF-8?q?L=E8=AA=9E=E6=B3=95=EF=BC=8C=E6=96=B0=E5=A2=9Epdf=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E8=B7=9F=E5=84=B2=E5=AD=98=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApiControllers/TenantBillController.cs | 252 +++++++++++++++--- FrontendWebApi/Models/Bill.cs | 15 +- FrontendWebApi/StaticFiles/import.html | 104 ++++++++ FrontendWebApi/appsettings.Development.json | 50 ++-- .../upload/OutputFormTemplate/import.html | 104 ++++++++ 5 files changed, 462 insertions(+), 63 deletions(-) create mode 100644 FrontendWebApi/StaticFiles/import.html create mode 100644 FrontendWebApi/wwwroot/upload/OutputFormTemplate/import.html diff --git a/FrontendWebApi/ApiControllers/TenantBillController.cs b/FrontendWebApi/ApiControllers/TenantBillController.cs index 09da3a9..5e7b31f 100644 --- a/FrontendWebApi/ApiControllers/TenantBillController.cs +++ b/FrontendWebApi/ApiControllers/TenantBillController.cs @@ -10,6 +10,17 @@ using static FrontendWebApi.Models.Bill; using Microsoft.Extensions.Logging; using System.Text.Json; using Newtonsoft.Json.Linq; +using System.Security.Cryptography; +using WkHtmlToPdfDotNet.Contracts; +using WkHtmlToPdfDotNet; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Configuration; +using Serilog.Core; +using static FrontendWebApi.ApiControllers.TenantBillController; +using System.Reflection; + + // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 @@ -22,15 +33,26 @@ namespace FrontendWebApi.ApiControllers //public class TenantBillController : MyBaseApiController { private readonly IBackendRepository backendRepository; + private readonly ILogger _logger; + private readonly IConfiguration Configuration; + private IWebHostEnvironment _webHostEnvironment; + private readonly IConverter _converter; const string TenantListtable = "archive_electric_meter_tenant_list"; const string TenantBilltable = "archive_electric_meter_tenant_bill"; - public TenantBillController(IBackendRepository backendRepository, IFrontendRepository frontendRepository) + public TenantBillController(IBackendRepository backendRepository, IFrontendRepository frontendRepository, ILogger logger, + IConfiguration configuration, + IWebHostEnvironment webHostEnvironment, + IConverter converter) { this.backendRepository = backendRepository; + this._logger = logger; + Configuration = configuration; + _webHostEnvironment = webHostEnvironment; + _converter = converter; } @@ -53,7 +75,7 @@ namespace FrontendWebApi.ApiControllers catch (Exception exception) { apiResult.Code = "9999"; - apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。" + exception.Message; //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } @@ -74,7 +96,7 @@ namespace FrontendWebApi.ApiControllers var created_at = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var sqlString = $"INSERT INTO {TenantListtable} (tenant_guid,list_id,tenant_name, bill_perKWH, bill_perRCV, created_by,created_at) " + - $"VALUES ('{tenant_guid}',{tl.list_id},'{tenant_name}', {bill_perKWH}, {bill_perRCV},'{tl.created_by}', '{created_at}')"; + $"VALUES ('{tenant_guid}','{tl.list_id}','{tenant_name}', {bill_perKWH}, {bill_perRCV},'{tl.created_by}', '{created_at}')"; await backendRepository.ExecuteSql(sqlString); @@ -85,6 +107,10 @@ namespace FrontendWebApi.ApiControllers { apiResult.Code = "9999"; apiResult.Msg = "系統內部錯誤,請聯絡管理者。" + exception.Message; + if (exception.Message.Contains($" for key 'PRIMARY'")) + { + apiResult.Msg = "已有相同使用者。"; + } //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } @@ -103,7 +129,6 @@ namespace FrontendWebApi.ApiControllers $"`tenant_name` = '{tl.tenant_name}', " + $"`bill_perKWH` = {tl.bill_perKWH}, " + $"`bill_perRCV` = {tl.bill_perRCV}, " + - $"`updated_by` = '{tl.updated_by}', " + $"`updated_at` = '{updated_at}' " + $"WHERE `tenant_guid` = '{tl.tenant_guid}'"; @@ -115,7 +140,11 @@ namespace FrontendWebApi.ApiControllers catch (Exception exception) { apiResult.Code = "9999"; - apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。" + exception.Message; + if (exception.Message.Contains($"a foreign key constraint")) + { + apiResult.Msg = "水電報表仍有該用戶,無法修改名稱。"; + } //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } @@ -138,18 +167,17 @@ namespace FrontendWebApi.ApiControllers catch (Exception exception) { apiResult.Code = "9999"; - apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。" + exception.Message; + if (exception.Message.Contains($"a foreign key constraint")) + { + apiResult.Msg = "水電報表仍有該用戶,無法刪除。"; + } //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } return apiResult; } - public class MyJsonData - { - public string Name { get; set; } - public int Age { get; set; } - } [HttpPost] public async Task>> GetTenantBill([FromBody] TenantBill tb) @@ -165,21 +193,21 @@ namespace FrontendWebApi.ApiControllers if (building_tag == "ALL") { sqlString = - $"SELECT bill_id,a.device_number,a.full_name,start_timestamp,end_timestamp,result,bill,tenant_name " + + $"SELECT bill_id,a.device_number,a.full_name,start_timestamp,end_timestamp,result,bill,tenant_name,tenant_guid " + $"from {TenantBilltable} a join device b on a.device_number =b.device_number" + $"where a.device_name_tag = '{ElecOrWater}' "; } else if (building_tag == "D2") { sqlString = - $"SELECT bill_id,a.device_number,a.full_name,start_timestamp,end_timestamp,result,bill,tenant_name " + + $"SELECT bill_id,a.device_number,a.full_name,start_timestamp,end_timestamp,result,bill,tenant_name,tenant_guid " + $"from {TenantBilltable} a join device b on a.device_number =b.device_number " + $"where device_building_tag = 'D1' and a.device_name_tag = '{ElecOrWater}' || device_building_tag = 'D2' and a.device_name_tag = '{ElecOrWater}'"; } else { sqlString = - $"SELECT bill_id,a.device_number,a.full_name,start_timestamp,end_timestamp,result,bill,tenant_name " + + $"SELECT bill_id,a.device_number,a.full_name,start_timestamp,end_timestamp,result,bill,tenant_name,tenant_guid " + $"from {TenantBilltable} a join device b on a.device_number =b.device_number " + $"where device_building_tag = '{building_tag}' and a.device_name_tag = '{ElecOrWater}' "; } @@ -194,7 +222,7 @@ namespace FrontendWebApi.ApiControllers catch (Exception exception) { apiResult.Code = "9999"; - apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。" + exception.Message; //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } @@ -213,14 +241,25 @@ namespace FrontendWebApi.ApiControllers var start_timestamp = tb.start_timestamp; var end_timestamp = tb.end_timestamp; string sqlString = null; + string startMonth = ""; + string endMonth = ""; + if (start_timestamp != "" && end_timestamp != "") + { + startMonth = tb.start_timestamp.Split("-")[0] + tb.start_timestamp.Split("-")[1]; + endMonth = tb.end_timestamp.Split("-")[0] + tb.end_timestamp.Split("-")[1]; + } + else + { + apiResult.Code = "9999"; + apiResult.Msg = "請選擇日期。"; + return apiResult; + } - string startMonth = tb.start_timestamp.Split("-")[0] + tb.start_timestamp.Split("-")[1]; - string endMonth = tb.end_timestamp.Split("-")[0] + tb.end_timestamp.Split("-")[1]; if (startMonth == endMonth) { sqlString = $"UPDATE {TenantBilltable} " + - $"set bill_id = {tb.bill_id} ,tenant_name = '{tb.tenant_name}', start_timestamp = '{start_timestamp}',end_timestamp = '{end_timestamp}' , " + + $"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= " + $"(select sum(sub_result) " + $"from archive_electric_water_meter_day_{startMonth} " + @@ -228,7 +267,6 @@ namespace FrontendWebApi.ApiControllers $"GROUP BY device_number) , " + $"bill = " + $"ROUND(result *(SELECT {bill_per} from {TenantListtable} WHERE tenant_guid = '{tb.tenant_guid}') ), " + - $"updated_by = '{tb.updated_by}', " + $"updated_at = '{updated_at}', " + $"tenant_guid = '{tb.tenant_guid}' " + $"WHERE device_number = '{tb.device_number}'"; @@ -237,7 +275,7 @@ namespace FrontendWebApi.ApiControllers { sqlString = $"UPDATE {TenantBilltable} " + - $"set bill_id = {tb.bill_id} ,tenant_name = '{tb.tenant_name}', start_timestamp = '{start_timestamp}',end_timestamp = '{end_timestamp}' , " + + $"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= " + $"(SELECT sum(sub_result) " + $"FROM ( " + @@ -253,7 +291,6 @@ namespace FrontendWebApi.ApiControllers $"GROUP BY device_number) ," + $"bill = " + $"ROUND(result *(SELECT {bill_per} from {TenantListtable} WHERE tenant_guid = '{tb.tenant_guid}') ), " + - $"updated_by = '{tb.updated_by}', " + $"updated_at = '{updated_at}', " + $"tenant_guid = '{tb.tenant_guid}' " + $"WHERE device_number = '{tb.device_number}'"; @@ -270,40 +307,187 @@ namespace FrontendWebApi.ApiControllers catch (Exception exception) { apiResult.Code = "9999"; - apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。" + exception.Message; //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); } return apiResult; } + [HttpPost] - public async Task>> OutputTenantBill() + public async Task OutputTenantBill() { - ApiResult> apiResult = new ApiResult>(); List outputBill = new List(); try { string sqlString = - $"SELECT distinct a.tenant_guid,b.tenant_name,start_timestamp,end_timestamp,bill_perKWH,bill_perRCV,sum(result) as name_result,sum(bill) as name_bill " + - $"from archive_electric_meter_tenant_bill a join archive_electric_meter_tenant_list b on a.tenant_guid = b.tenant_guid " + - $"WHERE a.tenant_guid = '37639e92-20ce-4064-956b-b6b0eaa7d7d2' " + - $"group by a.device_name_tag"; + $@"SELECT + a.tenant_name,a.start_timestamp,a.end_timestamp,bill_perKWH,bill_perRCV, + SUM(CASE WHEN device_name_tag = 'E4' THEN result ELSE 0 END) AS elec_result, + SUM(CASE WHEN device_name_tag = 'W1' THEN result ELSE 0 END) AS water_result, + SUM(CASE WHEN device_name_tag = 'E4' THEN bill ELSE 0 END) AS elec_bill, + SUM(CASE WHEN device_name_tag = 'W1' THEN bill ELSE 0 END) AS water_bill, + SUM(bill) AS total_bill + FROM archive_electric_meter_tenant_bill a + JOIN archive_electric_meter_tenant_list b on a.tenant_guid = b.tenant_guid + GROUP BY a.tenant_name + HAVING SUM(bill) != 0"; outputBill = await backendRepository.GetAllAsync(sqlString); + string filePath = CreateOutputForm(outputBill); - apiResult.Code = "0000"; - apiResult.Data = outputBill; + byte[] file = System.IO.File.ReadAllBytes(filePath); + + + return new FileContentResult(file, "application/pdf") + { + FileDownloadName = "水電報表.pdf" + }; } catch (Exception exception) + { + _logger.LogError(exception.ToString()); + } + return new FileContentResult(new byte[0], "application/pdf") { - apiResult.Code = "9999"; - apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; - //Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + FileDownloadName = "Empty.pdf" + }; + } + + public string CreateOutputForm(List outputBill) + { + try + { + string htmlStr = this.getOutputFormHtmlStr(outputBill); + + string filepath = Configuration.GetValue("FilePath:OutputForm"); + if (!Directory.Exists(filepath)) + { + Directory.CreateDirectory(filepath); + _logger.LogInformation("file CreateOutputForm path: " + filepath); + } + var nowString = DateTime.UtcNow.AddHours(8).ToString("yyyyMMdd_HHmmss"); + + //Random r1 = new System.Random(); + //string r2 = r1.Next(0, 999).ToString("0000"); + //string r2 = RandomNumberGenerator.GetInt32(0, 999).ToString("0000"); + + filepath += $"{nowString}_水電報表.pdf"; + + var doc = new HtmlToPdfDocument() + { + GlobalSettings = { + ColorMode = ColorMode.Color, + //Orientation = Orientation.Landscape, + PaperSize = PaperKind.A4, + Out = filepath, + Margins = new MarginSettings + { + Unit = Unit.Millimeters, + Top = 10, + Bottom = 10, + Right = 0, + Left = 0 + }, + }, + Objects = { + new ObjectSettings() { + HtmlContent=htmlStr, + WebSettings = { DefaultEncoding = "utf-8"}, + FooterSettings = new FooterSettings() { + Center = "第 [page] 頁 共 [topage] 頁", + FontName = "DFKai-sb", + }, + LoadSettings = new LoadSettings() { + JSDelay = 1000, + StopSlowScript = false, + BlockLocalFileAccess = false, + DebugJavascript = true + } + //HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true, Spacing = 2.812 } + } + } + }; + + // _converter.Warning += ConvertWarning; + + _converter.Convert(doc); + //IntPtr converter = _converter.CreateConverter(doc); + //_converter.Tools.DestroyConverter(); + return filepath; + } + catch (Exception ex) + { + throw new Exception(ex.ToString()); + } + } + + private string getOutputFormHtmlStr(List outputBill) + { + + try + { + string path = Configuration.GetValue("FilePath:OutputFormTemplate"); + //string path = _webHostEnvironment.ContentRootPath + "\\StaticFiles\\import.html"; + if (!File.Exists(path)) + { + return ""; + } + //string cssroot = _webHostEnvironment.ContentRootPath + "\\StaticFiles\\css\\"; + string htmlStr = System.IO.File.ReadAllText(path); + //string vendorscss = System.IO.File.ReadAllText(cssroot + "vendors.bundle.css"); + //string appBundelCss = System.IO.File.ReadAllText(cssroot + "app.bundle.css"); + //string skinmasterCss = System.IO.File.ReadAllText(cssroot + "skins\\skin-master.css"); + string bill = ""; + foreach (var item in outputBill) + { + bill += $"
" + + $"
" + + $" \"Taipei " + + $"

水電費用明細

" + + $"
" + + $"
" + + $"

費用資訊

" + + $"

用戶: {item.tenant_name}

" + + $"

起訖時間: {item.start_timestamp} ~ {item.end_timestamp}

" + + $" " + + $" " + + $" " + + $" " + + $" " + + $" " + + $" " + + $" " + + $" " + + $" " + + $" " + + $"
用電量: {item.elec_result}度單價: {item.bill_perKWH}元/度電費總計: {item.elec_bill}元
用水量: {item.water_result}度單價: {item.bill_perRCV}元/度水費總計: {item.water_bill}元
" + + $"
" + + $"
" + + $"
" + + $"

總計金額

" + + $"
" + + $" {item.total_bill}元 " + + $"
" + + $"
" + + $"
" + + $"
"; + + } + + + htmlStr = htmlStr.Replace("{{bill}}", bill); + + + return htmlStr; + } + catch (Exception ex) + { + throw new Exception(ex.ToString()); } - return apiResult; } } } \ No newline at end of file diff --git a/FrontendWebApi/Models/Bill.cs b/FrontendWebApi/Models/Bill.cs index d933d4d..298f933 100644 --- a/FrontendWebApi/Models/Bill.cs +++ b/FrontendWebApi/Models/Bill.cs @@ -7,7 +7,7 @@ namespace FrontendWebApi.Models public class TenantList { public string tenant_guid { get; set; } - public int list_id { get; set; } + public string list_id { get; set; } public string tenant_name { get; set; } public decimal bill_perKWH { get; set; } public decimal bill_perRCV { get; set; } @@ -42,15 +42,18 @@ namespace FrontendWebApi.Models public class OutputBill { public string tenant_name { get; set; } + public string device_name_tag { get; set; } public string start_timestamp { get; set; } public string end_timestamp { get; set; } - public decimal kwh_total { get; set; } + public decimal elec_result { get; set; } + public int elec_bill { get; set; } + public decimal water_result { get; set; } + public int water_bill { get; set; } public decimal bill_perKWH { get; set; } - public int electric_total { get; set; } - public decimal rcv_total { get; set; } public decimal bill_perRCV { get; set; } - public int water_total { get; set; } - public int all_total { get; set; } + public int total_bill { get; set; } + + } diff --git a/FrontendWebApi/StaticFiles/import.html b/FrontendWebApi/StaticFiles/import.html new file mode 100644 index 0000000..c8755e3 --- /dev/null +++ b/FrontendWebApi/StaticFiles/import.html @@ -0,0 +1,104 @@ + + + + + + + 費用明細 + + + + + {{bill}} + + + \ No newline at end of file diff --git a/FrontendWebApi/appsettings.Development.json b/FrontendWebApi/appsettings.Development.json index 0e905a9..fedd6f3 100644 --- a/FrontendWebApi/appsettings.Development.json +++ b/FrontendWebApi/appsettings.Development.json @@ -12,8 +12,12 @@ "SignKey": "TaipeiDome123456", //ñ��//�̤�16�r�� "JwtLifeSeconds": 3600 }, + "FilePath": { + "OutputForm": "D:\\jay.chang\\FrontendWebApi\\wwwroot\\upload\\OutputForm\\", //水電報表 檔案儲存位置 + "OutputFormTemplate": "D:\\jay.chang\\FrontendWebApi\\wwwroot\\upload\\OutputFormTemplate\\import.html" // 水電報表範本檔位置 + }, "DBConfig": { - "MySqlDBConfig": { + "MySqlDBConfig": { "Server": "CYGthbCeGtAXT4s1NOSJHQ==", //0.132 "Port": "mkF51jVbg40V5K5eTh2Ckw==", //"Database": "VJB2XC+lAtzuHObDGMVOAA==", //30 @@ -25,27 +29,27 @@ "Root": "SzdxEgaJJ7tcTCrUl2zKsA==", "Password": "FVAPxztxpY4gJJKQ/se4bQ==" } - //"MSSqlDBConfig": { - // "Server": "avZg8PA8C9GVgYZBgEKzCg==", - // "Port": "lJA0KPkG6RvFfTgWiXFyUw==", - // "Database": "VvfWH/59gQguY2eA2xBCug==", - // "Root": "sD8GZ9UPiIQGU6dU011/4A==", - // "Password": "2gi7rOmGha2VdXC5vtHxhg==" - //} + //"MSSqlDBConfig": { + // "Server": "avZg8PA8C9GVgYZBgEKzCg==", + // "Port": "lJA0KPkG6RvFfTgWiXFyUw==", + // "Database": "VvfWH/59gQguY2eA2xBCug==", + // "Root": "sD8GZ9UPiIQGU6dU011/4A==", + // "Password": "2gi7rOmGha2VdXC5vtHxhg==" + //} - //"MSSqlDBConfig": { //172.16.220.250 - // "Server": "zp3Nilx0PISEEC4caZWqCg==", - // "Port": "7puf4kd9qJ/q0fq2QASWeQ==", - // "Database": "VvfWH/59gQguY2eA2xBCug==", - // "Root": "sD8GZ9UPiIQGU6dU011/4A==", - // "Password": "Jue6jMFRi11meN6xbdKwDA==" - //} - //"MSSqlDBConfig": { - // "Server": "FPhyer7n0h/pw/yCMzKcPQ==", - // "Port": "7puf4kd9qJ/q0fq2QASWeQ==", - // "Database": "VvfWH/59gQguY2eA2xBCug==", - // "Root": "sD8GZ9UPiIQGU6dU011/4A==", - // "Password": "Jue6jMFRi11meN6xbdKwDA==" - //} - } + //"MSSqlDBConfig": { //172.16.220.250 + // "Server": "zp3Nilx0PISEEC4caZWqCg==", + // "Port": "7puf4kd9qJ/q0fq2QASWeQ==", + // "Database": "VvfWH/59gQguY2eA2xBCug==", + // "Root": "sD8GZ9UPiIQGU6dU011/4A==", + // "Password": "Jue6jMFRi11meN6xbdKwDA==" + //} + //"MSSqlDBConfig": { + // "Server": "FPhyer7n0h/pw/yCMzKcPQ==", + // "Port": "7puf4kd9qJ/q0fq2QASWeQ==", + // "Database": "VvfWH/59gQguY2eA2xBCug==", + // "Root": "sD8GZ9UPiIQGU6dU011/4A==", + // "Password": "Jue6jMFRi11meN6xbdKwDA==" + //} } +} diff --git a/FrontendWebApi/wwwroot/upload/OutputFormTemplate/import.html b/FrontendWebApi/wwwroot/upload/OutputFormTemplate/import.html new file mode 100644 index 0000000..fdb43b5 --- /dev/null +++ b/FrontendWebApi/wwwroot/upload/OutputFormTemplate/import.html @@ -0,0 +1,104 @@ + + + + + + + 費用明細 + + + + + {{bill}} + + + \ No newline at end of file