diff --git a/FrontendWebApi/ApiControllers/TenantBillController.cs b/FrontendWebApi/ApiControllers/TenantBillController.cs new file mode 100644 index 0000000..e62d20c --- /dev/null +++ b/FrontendWebApi/ApiControllers/TenantBillController.cs @@ -0,0 +1,497 @@ +using FrontendWebApi.Models; +using Microsoft.AspNetCore.Mvc; +using Repository.BackendRepository.Interface; +using Repository.FrontendRepository.Interface; +using System.Collections.Generic; +using System.Threading.Tasks; +using System; +using System.IO; +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 + +namespace FrontendWebApi.ApiControllers +{ + //[Route("api/[controller]")] + //[ApiController] + //public class TenantBillController + 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, ILogger logger, + IConfiguration configuration, + IWebHostEnvironment webHostEnvironment, + IConverter converter) + { + this.backendRepository = backendRepository; + this._logger = logger; + Configuration = configuration; + _webHostEnvironment = webHostEnvironment; + _converter = converter; + + } + + [HttpPost] + public async Task>> GetTenantList() + { + ApiResult> apiResult = new ApiResult>(); + List tenantList = new List(); + try + { + var sqlString = $"SELECT tenant_guid,list_id,tenant_name,bill_perKWH,bill_perRCV " + + $"from {TenantListtable} order by created_at"; + + tenantList = await backendRepository.GetAllAsync(sqlString); + + + apiResult.Code = "0000"; + apiResult.Data = tenantList; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + + return apiResult; + } + + [HttpPost] + public async Task> AddOneTenantList([FromBody] TenantList tl) + { + ApiResult apiResult = new ApiResult(); + + try + { + var tenant_guid = Guid.NewGuid(); + var tenant_name = tl.tenant_name; + var bill_perKWH = tl.bill_perKWH; + var bill_perRCV = tl.bill_perRCV; + 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}')"; + + + await backendRepository.ExecuteSql(sqlString); + apiResult.Code = "0000"; + apiResult.Data = "新增成功"; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + if (exception.Message.Contains($" for key 'PRIMARY'")) + { + apiResult.Msg = "已有相同使用者。"; + } + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + + return apiResult; + } + + [HttpPost] + public async Task> UpdateOneTenantList([FromBody] TenantList tl) + { + ApiResult apiResult = new ApiResult(); + + try + { + var updated_at = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + var sqlString = $"UPDATE {TenantListtable} SET " + + $"`tenant_name` = '{tl.tenant_name}', " + + $"`bill_perKWH` = {tl.bill_perKWH}, " + + $"`bill_perRCV` = {tl.bill_perRCV}, " + + $"`updated_at` = '{updated_at}' " + + $"WHERE `tenant_guid` = '{tl.tenant_guid}'"; + + + await backendRepository.ExecuteSql(sqlString); + apiResult.Code = "0000"; + apiResult.Data = "修改成功"; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + if (exception.Message.Contains($"a foreign key constraint")) + { + apiResult.Msg = "水電報表仍有該用戶,無法修改名稱。"; + } + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + + return apiResult; + } + + [HttpPost] + public async Task> DelOneTenantList([FromBody] TenantList tl) + { + ApiResult apiResult = new ApiResult(); + + try + { + var sqlString = $"delete from {TenantListtable} WHERE tenant_guid = '{tl.tenant_guid}' "; + + await backendRepository.ExecuteSql(sqlString); + apiResult.Code = "0000"; + apiResult.Data = "刪除成功"; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + if (exception.Message.Contains($"a foreign key constraint")) + { + apiResult.Msg = "水電報表仍有該用戶,無法刪除。"; + } + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + + return apiResult; + } + + + [HttpPost] + public async Task>> GetTenantBill([FromBody] TenantBill tb) + { + ApiResult> apiResult = new ApiResult>(); + List tenantBill = new List(); + try + { + string tableType = tb.tableType; + string building_tag = tb.building_tag; + string ElecOrWater = tableType == "elec" ? "E4" : "W1"; + string sqlString = null; + if (building_tag == "ALL") + { + sqlString = + $"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,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,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}' "; + } + + + tenantBill = await backendRepository.GetAllAsync(sqlString); + + + apiResult.Code = "0000"; + apiResult.Data = tenantBill; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + + return apiResult; + } + + [HttpPost] + public async Task> UpdateTenantBill([FromBody] TenantBill tb) + { + ApiResult apiResult = new ApiResult(); + + try + { + string bill_per = tb.tableType == "elec" ? "bill_perKWH" : "bill_perRCV"; + var updated_at = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + 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; + } + + if (startMonth == endMonth) + { + 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= " + + $"(select sum(sub_result) " + + $"from archive_electric_water_meter_day_{startMonth} " + + $"WHERE device_number = '{tb.device_number}' and start_timestamp BETWEEN '{start_timestamp}' and '{end_timestamp}' " + + $"GROUP BY device_number) , " + + $"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}'"; + } + else + { + //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= " + + // $"(SELECT sum(sub_result) " + + // $"FROM ( " + + // $" SELECT start_timestamp,device_number, sub_result " + + // $" FROM archive_electric_water_meter_day_{startMonth} " + + // $" WHERE device_number = '{tb.device_number}' " + + // $" UNION ALL " + + // $" SELECT start_timestamp,device_number, sub_result " + + // $" FROM archive_electric_water_meter_day_{endMonth} " + + // $" WHERE device_number = '{tb.device_number}' " + + // $") combined_result " + + // $"WHERE start_timestamp BETWEEN '{start_timestamp}' and '{end_timestamp}' " + + // $"GROUP BY device_number) ," + + // $"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}'"; + apiResult.Code = "9999"; + apiResult.Msg = "請選擇同一個月份"; + + } + + + await backendRepository.ExecuteSql(sqlString); + + + apiResult.Code = "0000"; + apiResult.Data = "修改成功"; + } + catch (Exception exception) + { + apiResult.Code = "9999"; + apiResult.Msg = "系統內部錯誤,請聯絡管理者。"; + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + + return apiResult; + } + + + [HttpPost] + public async Task OutputTenantBill() + { + List outputBill = new List(); + + try + { + string sqlString = + $@"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); + + byte[] file = System.IO.File.ReadAllBytes(filePath); + + + return new FileContentResult(file, "application/pdf") + { + FileDownloadName = "水電報表.pdf" + }; + } + catch (Exception exception) + { + Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message); + } + return new FileContentResult(new byte[0], "application/pdf") + { + 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 image = Configuration.GetValue("FilePath:Image"); + + //string path = _webHostEnvironment.ContentRootPath + "\\StaticFiles\\import.html"; + if (!System.IO.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()); + } + + } + } +} \ No newline at end of file diff --git a/FrontendWebApi/FrontendWebApi.csproj b/FrontendWebApi/FrontendWebApi.csproj index fe797d3..8ca452a 100644 --- a/FrontendWebApi/FrontendWebApi.csproj +++ b/FrontendWebApi/FrontendWebApi.csproj @@ -11,6 +11,7 @@ + diff --git a/FrontendWebApi/Models/Bill.cs b/FrontendWebApi/Models/Bill.cs new file mode 100644 index 0000000..298f933 --- /dev/null +++ b/FrontendWebApi/Models/Bill.cs @@ -0,0 +1,61 @@ +using System; + +namespace FrontendWebApi.Models +{ + public class Bill + { + public class TenantList + { + public string tenant_guid { 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; } + public string created_by { get; set; } + public DateTime created_at { get; set; } + public string updated_by { get; set; } + public DateTime? updated_at { get; set; } + + } + + public class TenantBill + { + public int bill_id { get; set; } + public string tenant_name { get; set; } + public string device_number { get; set; } + public string full_name { get; set; } + public string start_timestamp { get; set; } + public string end_timestamp { get; set; } + public string device_name_tag { get; set; } + public decimal result { get; set; } + public int bill { get; set; } + public string created_by { get; set; } + public DateTime created_at { get; set; } + public string updated_by { get; set; } + public DateTime? updated_at { get; set; } + public string tenant_guid { get; set; } + public string tableType { get; set; } + public string building_tag { get; set; } + + } + + 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 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 decimal bill_perRCV { get; set; } + public int total_bill { get; set; } + + + + } + + } +} \ No newline at end of file diff --git a/FrontendWebApi/Startup.cs b/FrontendWebApi/Startup.cs index 7ae8075..f2c656e 100644 --- a/FrontendWebApi/Startup.cs +++ b/FrontendWebApi/Startup.cs @@ -24,6 +24,8 @@ using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Text; using System.Threading.Tasks; +using WkHtmlToPdfDotNet.Contracts; +using WkHtmlToPdfDotNet; using static FrontendWebApi.Jwt.JwtHelpers; namespace FrontendWebApi @@ -81,6 +83,11 @@ namespace FrontendWebApi .AddConsole(); }); + #region htmlPDF `J + services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools())); + #endregion + + #region DBHelper `J services.Configure(Configuration.GetSection("DBConfig")); services.AddTransient(); diff --git a/FrontendWebApi/appsettings.Development.json b/FrontendWebApi/appsettings.Development.json index 8798a2e..84e653e 100644 --- a/FrontendWebApi/appsettings.Development.json +++ b/FrontendWebApi/appsettings.Development.json @@ -12,6 +12,11 @@ "SignKey": "TaipeiDome123456", //ñ��//�̤�16�r�� "JwtLifeSeconds": 3600 }, + "FilePath": { + "OutputForm": "D:\\jay.chang\\dome\\FrontendWebApi\\wwwroot\\upload\\OutputForm\\", //水電報表 檔案儲存位置 + "OutputFormTemplate": "D:\\jay.chang\\dome\\FrontendWebApi\\wwwroot\\upload\\OutputFormTemplate\\import.html", // 水電報表範本檔位置 + "Image": "D:\\jay.chang\\dome\\FrontendWebApi\\wwwroot\\upload\\OutputFormTemplate\\dome.png" // 明細的圖片 + }, "DBConfig": { "MySqlDBConfig": { "Server": "FYlY+w0XDIz+jmF2rlZWJw==", //0.201 diff --git a/FrontendWebApi/appsettings.json b/FrontendWebApi/appsettings.json index 56ec028..81a3162 100644 --- a/FrontendWebApi/appsettings.json +++ b/FrontendWebApi/appsettings.json @@ -11,6 +11,11 @@ "SignKey": "TaipeiDome123456", //ñ��//�̤�16�r�� "JwtLifeSeconds": 86400 }, + "FilePath": { + "OutputForm": "D:\\jay.chang\\dome\\FrontendWebApi\\wwwroot\\upload\\OutputForm\\", //水電報表 檔案儲存位置 + "OutputFormTemplate": "D:\\jay.chang\\dome\\FrontendWebApi\\wwwroot\\upload\\OutputFormTemplate\\import.html", // 水電報表範本檔位置 + "Image": "D:\\jay.chang\\dome\\FrontendWebApi\\wwwroot\\upload\\OutputFormTemplate\\dome.png" // 明細的圖片 + }, "DBConfig": { //"MySqlDBConfig": { // "Server": "avZg8PA8C9GVgYZBgEKzCg==", 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