public async Task <IActionResult> Export(ExportEmpMonthlySalaryRequest request)
        {
            var fileType = HttpContext.Request?.Headers["file-type"];
            var result   = await Mediator.Send(request);

            if (result.Failure)
            {
                return new ContentResult()
                       {
                           Content    = JsonConvert.SerializeObject(result),
                           StatusCode = (int)HttpStatusCode.InternalServerError
                       }
            }
            ;

            var fileName = $"Monthly-employee-payroll-{request.YearMonth}.{fileType}";

            return(File(result.Data.CsvSalaries, $"text/{fileType}", fileName));
        }
        public async Task <Result <ExportEmpMonthlySalaryResponse> > Handle(ExportEmpMonthlySalaryRequest request, CancellationToken cancellationToken)
        {
            var salaryConfig = await _salaryConfigRepo.GetAsync();

            var previewResult = await _mediator.Send(new PreviewEmpMonthlySalaryRequest
            {
                Key       = request.Key,
                YearMonth = request.YearMonth
            });

            try
            {
                return(await salaryConfig.Map(() => previewResult).Map(x =>
                {
                    var salaries = x.Salaries.GroupBy(x => x.Email).Select((y, index) =>
                    {
                        var salary = y.FirstOrDefault();
                        return new ExportEmpMonthlySalary
                        {
                            No = $"{index + 1}",
                            Fullname = salary.Fullname,
                            Email = salary.Email,
                            EmployeeType = y.Count() == 2 ? $"{EmployeeTypeEnum.Probation}/{EmployeeTypeEnum.Permanent}"
                                                                                  : salary.EmployeeType,
                            Position = salary.Position,
                            StandardWorkingDays = salary.StandardWorkingDays,
                            ActualWorkingDays = y.Sum(z => z.ActualWorkingDays),
                            GrossContractSalary = salary.GrossContractSalary,
                            InsuranceSalary = salary.InsuranceSalary,
                            ActualGrossSalary = y.Sum(z => z.ActualGrossSalary),
                            NonTaxableAllowances = y.Sum(z => z.NonTaxableAllowances),
                            Taxable13MonthSalary = y.Sum(z => z.Taxable13MonthSalary),
                            TaxableAnnualLeave = y.Sum(z => z.TaxableAnnualLeave),
                            TaxableOthers = y.Sum(z => z.TaxableOthers),
                            TotalMonthlyIncome = y.Sum(z => z.TotalMonthlyIncome),
                            TaxableIncome = y.Sum(z => z.TaxableIncome),
                            EmployeeSocialInsurance = y.Sum(z => z.EmployeeSocialInsurance),
                            EmployeeHealthcareInsurance = y.Sum(z => z.EmployeeHealthcareInsurance),
                            EmployeeUnemploymentInsurance = y.Sum(z => z.EmployeeUnemploymentInsurance),
                            EmployeeUnionFee = y.Sum(z => z.EmployeeUnionFee),
                            EmployerSocialInsurance = y.Sum(z => z.EmployerSocialInsurance),
                            EmployerHealthcareInsurance = y.Sum(z => z.EmployerHealthcareInsurance),
                            EmployerUnemploymentInsurance = y.Sum(z => z.EmployerUnemploymentInsurance),
                            EmployerUnionFee = y.Sum(z => z.EmployerUnionFee),
                            PersonalDeduction = salary.PersonalDeduction,
                            NumberOfDependants = salary.NumberOfDependants,
                            DependantDeduction = salary.DependantDeduction,
                            AssessableIncome = y.Sum(z => z.AssessableIncome),
                            NetIncome = y.Sum(z => z.NetIncome),
                            PIT = y.Sum(z => z.PIT),
                            TotalSalaryCost = y.Sum(z => z.TotalSalaryCost),
                            PaymentAdvance = salary.PaymentAdvance,
                            AdjustmentDeduction = salary.AdjustmentDeduction,
                            AdjustmentAddition = salary.AdjustmentAddition,
                            NetPayment = y.Sum(z => z.NetPayment),
                        };
                    }).ToList();

                    salaries.Add(new ExportEmpMonthlySalary
                    {
                        No = "Grand Total",
                        StandardWorkingDays = salaries.Sum(y => y.StandardWorkingDays),
                        ActualWorkingDays = salaries.Sum(y => y.ActualWorkingDays),
                        GrossContractSalary = salaries.Sum(y => y.GrossContractSalary),
                        InsuranceSalary = salaries.Sum(y => y.InsuranceSalary),
                        ActualGrossSalary = salaries.Sum(y => y.ActualGrossSalary),
                        NonTaxableAllowances = salaries.Sum(y => y.NonTaxableAllowances),
                        Taxable13MonthSalary = salaries.Sum(y => y.Taxable13MonthSalary),
                        TaxableAnnualLeave = salaries.Sum(y => y.TaxableAnnualLeave),
                        TaxableOthers = salaries.Sum(y => y.TaxableOthers),
                        TotalMonthlyIncome = salaries.Sum(y => y.TotalMonthlyIncome),
                        TaxableIncome = salaries.Sum(y => y.TaxableIncome),
                        EmployeeSocialInsurance = salaries.Sum(y => y.EmployeeSocialInsurance),
                        EmployeeHealthcareInsurance = salaries.Sum(y => y.EmployeeHealthcareInsurance),
                        EmployeeUnemploymentInsurance = salaries.Sum(y => y.EmployeeUnemploymentInsurance),
                        EmployeeUnionFee = salaries.Sum(y => y.EmployeeUnionFee),
                        EmployerSocialInsurance = salaries.Sum(y => y.EmployerSocialInsurance),
                        EmployerHealthcareInsurance = salaries.Sum(y => y.EmployerHealthcareInsurance),
                        EmployerUnemploymentInsurance = salaries.Sum(y => y.EmployerUnemploymentInsurance),
                        EmployerUnionFee = salaries.Sum(y => y.EmployerUnionFee),
                        PersonalDeduction = salaries.Sum(y => y.PersonalDeduction),
                        NumberOfDependants = salaries.Sum(y => y.NumberOfDependants),
                        DependantDeduction = salaries.Sum(y => y.DependantDeduction),
                        AssessableIncome = salaries.Sum(y => y.AssessableIncome),
                        NetIncome = salaries.Sum(y => y.NetIncome),
                        PIT = salaries.Sum(y => y.PIT),
                        TotalSalaryCost = salaries.Sum(y => y.TotalSalaryCost),
                        PaymentAdvance = salaries.Sum(y => y.PaymentAdvance),
                        AdjustmentDeduction = salaries.Sum(y => y.AdjustmentDeduction),
                        AdjustmentAddition = salaries.Sum(y => y.AdjustmentAddition),
                        NetPayment = salaries.Sum(y => y.NetPayment)
                    });

                    return salaries;
                })
                       .MapAsync(x => _fileHelper.CreateCsvByteArrayAsync(x, salaryConfig.Data, request.YearMonth))
                       .MapAsync(x => new ExportEmpMonthlySalaryResponse
                {
                    CsvSalaries = x
                }));
            }
            catch (CsvHelperException ex)
            {
                _logger.LogError(ex, Errors.ExportEmpMonthlySalary.ExportWriteCSVError.Message);
                return(Errors.ExportEmpMonthlySalary.ExportWriteCSVError);
            }
        }