From 057e27c226c231df92785bdc919b12a33439a896 Mon Sep 17 00:00:00 2001 From: mashfiq Date: Wed, 12 Feb 2025 18:02:49 +0600 Subject: [PATCH] multiple letter generation --- .../letter-request/letter-request.service.ts | 5 + .../adhoc-feature-routing.module.ts | 2 + .../app/adhoc-feature/adhoc-feature.module.ts | 3 +- .../exception-letter-generate.component.html | 58 +++++++ .../exception-letter-generate.component.scss | 0 .../exception-letter-generate.component.ts | 162 ++++++++++++++++++ .../letter-generate.component.html | 1 + .../letter-generate.component.ts | 1 + .../LetterRequest/LetterRequestController.cs | 84 +++++++++ 9 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.html create mode 100644 HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.scss create mode 100644 HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.ts diff --git a/HRM.UI/ClientApp/src/app/_services/letter-request/letter-request.service.ts b/HRM.UI/ClientApp/src/app/_services/letter-request/letter-request.service.ts index df63f04..bc4fabe 100644 --- a/HRM.UI/ClientApp/src/app/_services/letter-request/letter-request.service.ts +++ b/HRM.UI/ClientApp/src/app/_services/letter-request/letter-request.service.ts @@ -11,6 +11,7 @@ import { EnumLetterOrganizationType } from '../../_models/enums'; import { LetterRequest } from '../../_models/Letter-Request/Letter-Request'; import { AuthorizedPerson } from '../../adhoc-feature/authorized-persons/authorizedPerson'; import { WFMovementTran } from '../../_models/Work-Flow/wFMovementTran'; +import { SearchEmployee } from 'src/app/_models/Employee/searchEmployee'; @Injectable({ providedIn: 'root' @@ -233,6 +234,10 @@ export class LetterRequestService { getImage(id: number) { return this.apiService.httpGet('/LetterRequest/getImage' + '/' + id); } + generatedExceptiinLetter(type: number, param: SearchEmployee[]) { + return this.apiService.httpPost('/LetterRequest/generatedExceptiinLetter/' + type , param); + // return this.apiService.httpDownloadFile('/LetterRequest/generatedExceptiinLetter/' + type , param); + } } diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature-routing.module.ts b/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature-routing.module.ts index 6fa10ca..be0ae26 100644 --- a/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature-routing.module.ts +++ b/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature-routing.module.ts @@ -19,6 +19,7 @@ import {LetterRequestByAdminApprovalComponent} from './letter-request-by-admin-a import {ApproveFinancialDataComponent} from './approve-financial-data/approve-financial-data.component'; import {AuthorizedPersonsComponent} from './authorized-persons/authorized-persons.component'; import { LetterGenerateComponent } from './letter-generate/letter-generate.component'; +import { ExceptionLetterGenerateComponent } from './exception-letter-generate/exception-letter-generate.component'; const routes: Routes = [ @@ -31,6 +32,7 @@ const routes: Routes = [ {path: 'letter-generate', component: LetterGenerateComponent, canActivate: [AuthGuard]}, {path: 'workflow-delegation-by-employee', component: WorkflowDelegationByEmployeeComponent, canActivate: [AuthGuard]}, {path: 'delegation-from-admin-panel', component: DelegationFromAdminPanelComponent, canActivate: [AuthGuard]}, + {path: 'exception-letter-generate', component: ExceptionLetterGenerateComponent, canActivate: [AuthGuard]}, //{path: 'letter-request-by-employee-and-approval', component: LetterRequestByEmployeeAndApprovalComponent, canActivate: [AuthGuard]}, //{path: 'letter-request-approval', component: LetterRequestApprovalComponent, canActivate: [AuthGuard]}, //{path: 'letter-print-by-admin-panel', component: LetterPrintByAdminPanelComponent, canActivate: [AuthGuard]}, diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature.module.ts b/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature.module.ts index e5e9843..88055b1 100644 --- a/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature.module.ts +++ b/HRM.UI/ClientApp/src/app/adhoc-feature/adhoc-feature.module.ts @@ -49,13 +49,14 @@ import { ApproveFinancialDataComponent } from './approve-financial-data/approve- import { AuthorizedPersonsComponent } from './authorized-persons/authorized-persons.component'; import { AuthorizedPersonComponent } from './authorized-persons/authorized-person/authorized-person.component'; import { LetterGenerateComponent } from './letter-generate/letter-generate.component'; +import { ExceptionLetterGenerateComponent } from './exception-letter-generate/exception-letter-generate.component'; @NgModule({ declarations: [workflowRuleComponent, WorkFlowSetupComponent, WorkFlowSetupNewComponent, WorkFlowAdministrativeStatusComponent, WorkFlowAdminComponent, WorkflowDelegationByEmployeeComponent, DelegationFromAdminPanelComponent, LetterRequestApprovalComponent, LetterPrintByAdminPanelComponent, - LetterRequestByAdminApprovalComponent, ApproveFinancialDataComponent, AuthorizedPersonsComponent, AuthorizedPersonComponent, LetterGenerateComponent + LetterRequestByAdminApprovalComponent, ApproveFinancialDataComponent, AuthorizedPersonsComponent, AuthorizedPersonComponent, LetterGenerateComponent, ExceptionLetterGenerateComponent ], imports: [ diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.html b/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.html new file mode 100644 index 0000000..abff192 --- /dev/null +++ b/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.html @@ -0,0 +1,58 @@ + +
+
+
+
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ + + + + + + + + + + + + + +
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.scss b/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.ts b/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.ts new file mode 100644 index 0000000..4812a15 --- /dev/null +++ b/HRM.UI/ClientApp/src/app/adhoc-feature/exception-letter-generate/exception-letter-generate.component.ts @@ -0,0 +1,162 @@ +import { error } from 'console'; +import { Component, OnInit } from '@angular/core'; +import { DynamicPicker, EnumDynamicpickerType } from '../../picker/dynamic-picker/Dynamic-Picker'; +import { SearchEmployee } from 'src/app/_models/Employee/searchEmployee'; +import { Router } from '@angular/router'; +import { ApiService } from 'src/app/app.api.service'; +import { HRMNotificationService } from 'src/app/app.notification.service'; +import { loadingPanelService } from 'src/app/hrm-loding panel/loding.panel.service'; +import { BasicService } from 'src/app/_services/Basic/basic.service'; +import { Department } from 'src/app/_models/Basic/department'; +import { Grade } from 'src/app/_models/Basic/grade'; +import { EnumStatus } from '../../_models/enums'; +import { Employee } from 'src/app/_models/Employee/employee'; +import { LetterRequestService } from 'src/app/_services/letter-request/letter-request.service'; +import { saveAs } from 'file-saver'; + +@Component({ + selector: 'app-exception-letter-generate', + templateUrl: './exception-letter-generate.component.html', + styleUrls: ['./exception-letter-generate.component.scss'] +}) +export class ExceptionLetterGenerateComponent implements OnInit { + + public selectedEmps: SearchEmployee[] = []; + public mySelection: number[] = []; + + public selectedreportType: EnumExceptionLetterTemplateType; + public reportTypes = Object.keys(EnumExceptionLetterTemplateType) + .filter(key => !isNaN(Number(EnumExceptionLetterTemplateType[key]))) + .map(key => ({ + text: key.replace(/_/g, ' '), + value: EnumExceptionLetterTemplateType[key] + })); + public allDepartments: Department[]; + public allGrades: Grade[]; + + constructor( + public router: Router, public loadingPanel: loadingPanelService, + public notificationService: HRMNotificationService, + public apiService: ApiService, + public basicService: BasicService, public letterRequestService: LetterRequestService) { + this.apiService.selectedMenuName = 'Employee Letter Generation'; + } + + ngOnInit(): void { + // this.basicService.getAllDepartment(EnumStatus.Active).subscribe( + // (resp) => { + // this.allDepartments = resp; + // }, + // (err: any) => { + // this.notificationService.showError(err.error); + // } + // ); + // this.basicService.getAllGrade(EnumStatus.Active).subscribe( + // (resp) => { + // this.allGrades = resp; + // }, + // (err: any) => { + // this.notificationService.showError(err.error); + // } + // ); + } + public GetSelectedEmployee(childData) { + this.selectedEmps = childData; + // this.selectedEmps.forEach(element => { + // element.departmentName = this.allDepartments.find(d => d.id == element.departmentID).name; + // element.gradeName = this.allDepartments.find(g => g.id == element.gradeID).name; + // }); + } + + public onSelectReport(value: any) { + debugger; + } + generateLetter() { + let employeeDataToGenerate: SearchEmployee[] = []; + this.selectedEmps.forEach(element => { + this.mySelection.forEach(item => { + if (element.employeeID == item) employeeDataToGenerate.push(element); + }); + }); + this.selectedreportType; + if (this.selectedreportType == undefined || this.selectedreportType['value'] == null) { + this.notificationService.showWarning("Please select a Letter to Generate"); + return; + } + if (employeeDataToGenerate.length <= 0) { + this.notificationService.showWarning("Please select Employee to Generate Letter"); + return; + } + this.loadingPanel.ShowLoadingPanel = true; + this.letterRequestService.generatedExceptiinLetter(this.selectedreportType['value'], employeeDataToGenerate).subscribe( + (resp: any[]) => { + debugger + if (resp.length > 0) { + resp.forEach(fileData => { + // this.downloadBlob(new Blob([fileData.fileContents], { type: 'application/msword' }), 'application/msword', fileData.fileDownloadName); + this.downloadFileWord(fileData.fileContents, fileData.fileDownloadName); + }); + } + + this.loadingPanel.ShowLoadingPanel = false; + }, + (err: any) => { + this.notificationService.showError(err.error); + this.loadingPanel.ShowLoadingPanel = false; + } + ); + } + + + private downloadBlob(data: any, type: string, fileName: string): void { + const blob: Blob = new Blob([data], { type: type }); + // const fileName: string = this.workOrderBillReceive.UploadAttachment[0].OriginalFileName; + // const fileName: string = fileName; + const objectUrl: string = URL.createObjectURL(blob); + const a: HTMLAnchorElement = document.createElement('a') as HTMLAnchorElement; + + a.href = objectUrl; + a.download = fileName; + document.body.appendChild(a); + a.click(); + + document.body.removeChild(a); + URL.revokeObjectURL(objectUrl); + } + + + + downloadFileWord(blobContent, fileName) { + // const blob = new Blob([this.b64toBlob(blobContent, 'application/data:application/vnd.openxmlformats-officedocument.wordprocessingml.document', 1024)], {}); + // saveAs(blob, fileName + '.docx'); + const blob = new Blob([this.b64toBlob(blobContent, 'application/msword', 1024)], {}); + saveAs(blob, fileName); + } + + b64toBlob(b64Data, contentType, sliceSize) { + const byteCharacters = atob(b64Data); + const byteArrays = []; + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + const slice = byteCharacters.slice(offset, offset + sliceSize); + + const byteNumbers = new Array(slice.length); + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + const byteArray = new Uint8Array(byteNumbers); + byteArrays.push(byteArray); + } + + const blob = new Blob(byteArrays, { type: contentType }); + return blob; + } + +} + + +export enum EnumExceptionLetterTemplateType { + Letter_Template_Staff = 1, + Letter_Template_Worker = 2 +} diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.html b/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.html index 1d48442..bf85a57 100644 --- a/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.html +++ b/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.html @@ -55,6 +55,7 @@
+
diff --git a/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.ts b/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.ts index bbed72a..cabdf45 100644 --- a/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.ts +++ b/HRM.UI/ClientApp/src/app/adhoc-feature/letter-generate/letter-generate.component.ts @@ -60,6 +60,7 @@ export class LetterGenerateComponent implements OnInit { }; } this.showPopUp = true; + this.loadingPanelService.ShowLoadingPanel = true; this.reportService.getAppointmentLetter(data).subscribe( (resp: any) => { if (this.reportType === 'PDF'){ diff --git a/HRM.UI/Controllers/LetterRequest/LetterRequestController.cs b/HRM.UI/Controllers/LetterRequest/LetterRequestController.cs index e529a78..d39409e 100644 --- a/HRM.UI/Controllers/LetterRequest/LetterRequestController.cs +++ b/HRM.UI/Controllers/LetterRequest/LetterRequestController.cs @@ -11,11 +11,13 @@ using AutoMapper.Configuration; using Google.Protobuf.WellKnownTypes; using HRM.BO; using HRM.DA; +using HRM.Report; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Configuration; +using NPOI.HPSF; using NPOI.SS.Formula.Functions; using Org.BouncyCastle.Ocsp; using static HRM.Report.PayrollDataSet.PayrollDataSet; @@ -783,6 +785,88 @@ namespace HRM.UI.Controllers } + [HttpPost("generatedExceptiinLetter/{letterType}")] + public ActionResult generatedExceptiinLetter(int letterType, List employees) + { + CurrentUser currentUser = CurrentUser.GetCurrentUser(HttpContext.User); + int payrollTypeId = currentUser.PayrollTypeID.GetValueOrDefault(); + //string downloadPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\Downloads"; + string downloadPath = System.Environment.CurrentDirectory + "\\Documents\\LetterTempFolder\\"; + string lFileName = string.Empty; + + + //List sFilePaths = new List(); + List> filesWithContents = new List>(); + List files = new List(); + + LetterTemplte ltemplate = new LetterTemplte(); + + byte[] bytes = null; + + try + { + + if (letterType == 1) + { + ltemplate.SetObjectID(FixedLetterTemplte.Staff_Appointment_Letter); + + ltemplate.ID = 2; + ltemplate.Description = "Letter Template Staff"; + ltemplate.Subject = "Letter Template Staff"; + ltemplate.Type = EnumDocType.Desktop_Letter; + ltemplate.TypeID = (int)EnumDocType.Desktop_Letter; + + lFileName = "Staff.doc"; + } + else + { + ltemplate.SetObjectID(FixedLetterTemplte.Worker_Appointment_Letter); + + ltemplate.ID = 3; + ltemplate.Description = "Letter Template Worker"; + ltemplate.Subject = "Letter Template Worker"; + ltemplate.Type = EnumDocType.Desktop_Letter; + ltemplate.TypeID = (int)EnumDocType.Desktop_Letter; + + lFileName = "Worker.doc"; + + } + + if (employees != null && employees.Count > 0) + { + foreach (var emp in employees) + { + string sFilePath = new rptEmployee().Generate(ltemplate, emp.EmployeeID, payrollTypeId, downloadPath, lFileName); + byte[] buffer = new byte[16 * 1024]; + buffer = System.IO.File.ReadAllBytes(sFilePath); + string contentType = GetFileType(sFilePath); + var name = lFileName; + if (System.IO.File.Exists(sFilePath)) + { + System.IO.File.Delete(sFilePath); + } + + //sFilePaths.Add(sFilePath); + filesWithContents.Add(new Tuple(buffer, emp.EmployeeNo + "_" + name, contentType)); + + var file = File(buffer, contentType, emp.EmployeeNo + "_" + name); + //return file; + files.Add(file); + } + } + + + + //return Ok(filesWithContents); + return Ok(files); + } + catch (Exception e) + { + return StatusCode(StatusCodes.Status500InternalServerError, e.Message); + } + + return Ok(); + } } } \ No newline at end of file