Esempio n. 1
0
        public async Task <Result <GetSalaryConfigResponse> > Handle(GetSalaryConfigRequest request, CancellationToken cancellationToken)
        {
            var salaryConfig = await _salaryConfigRepository.GetAsync();

            return(salaryConfig.Map(x => new GetSalaryConfigResponse(
                                        salarySetting: new SalarySettingResponse(
                                            id: x.Id,
                                            commonMinimumWage: x.CommonMinimumWage,
                                            regionalMinimumWage: x.RegionalMinimumWage,
                                            coefficientSocialCare: x.CoefficientSocialCare,
                                            employerSocialInsuranceRate: x.EmployerSocialInsuranceRate,
                                            employeeSocialInsuranceRate: x.EmployeeSocialInsuranceRate,
                                            employerHealthCareInsuranceRate: x.EmployerHealthCareInsuranceRate,
                                            employeeHealthCareInsuranceRate: x.EmployeeHealthCareInsuranceRate,
                                            employeeUnemploymentInsuranceRate: x.EmployeeUnemploymentInsuranceRate,
                                            employerUnemploymentInsuranceRate: x.EmployerUnemploymentInsuranceRate,
                                            foreignEmployerSocialInsuranceRate: x.ForeignEmployerSocialInsuranceRate,
                                            foreignEmployeeSocialInsuranceRate: x.ForeignEmployeeSocialInsuranceRate,
                                            foreignHealthCareInsuranceEmployeeRate: x.ForeignEmployeeHealthCareInsuranceRate,
                                            foreignHealthCareInsuranceEmployerRate: x.ForeignEmployerHealthCareInsuranceRate,
                                            foreignUnemploymentInsuranceEmployeeRate: x.ForeignEmployeeUnemploymentInsuranceRate,
                                            foreignUnemploymentInsuranceEmployerRate: x.ForeignEmployerUnemploymentInsuranceRate,
                                            employeeUnionFeeRate: x.EmployeeUnionFeeRate,
                                            employerUnionFeeRate: x.EmployerUnionFeeRate,
                                            maximumUnionFeeRate: x.MaximumUnionFeeRate,
                                            defaultProbationTaxRate: x.DefaultProbationTaxRate,
                                            isInsurancePaidFullSalary: x.IsInsurancePaidFullSalary,
                                            insurancePaidAmount: x.InsurancePaidAmount,
                                            personalDeduction: x.PersonalDeduction,
                                            dependantDeduction: x.DependantDeduction,
                                            currency: x.CommonMinimumWage.Currency,
                                            minimumNonWorkingDay: x.MinimumNonWorkingDay),
                                        progressiveTaxRates: x.ProgressiveTaxRateLookUpTable.AsReadOnlyCollection()
                                        .Select(x => new ProgressiveTaxRateResponse(
                                                    lowerBound: x.LowerBound,
                                                    upperBound: x.UpperBound,
                                                    taxRateLevel: x.ProgressiveTaxRateLevel,
                                                    rate: x.Rate)).ToList()
                                        )));
        }
        public async Task <Result <PreviewEmpMonthlySalaryResponse> > Handle(
            PreviewEmpMonthlySalaryRequest request,
            CancellationToken cancellationToken)
        {
            // get calculated salary
            var calculatedSalaries = await _salaryRepo.GetAsync(request.Key, request.YearMonth);

            if (calculatedSalaries.Failure)
            {
                return(calculatedSalaries.Error);
            }

            if (calculatedSalaries.Data.Length > 0)
            {
                return(Result <PreviewEmpMonthlySalaryResponse> .Ok(new PreviewEmpMonthlySalaryResponse(
                                                                        calculatedSalaries.Data.Select(x => new PreviewEmpMonthlySalary(
                                                                                                           fullname: x.Fullname,
                                                                                                           email: x.Email,
                                                                                                           employeeType: x.EmployeeType,
                                                                                                           position: x.Position,
                                                                                                           numberOfDependants: x.NumberOfDependants,
                                                                                                           standardWorkingDays: x.StandardWorkingDays,
                                                                                                           actualWorkingDays: x.ActualWorkingDays,
                                                                                                           grossContractSalary: x.GrossContractSalary,
                                                                                                           insuranceSalary: x.InsuranceSalary,
                                                                                                           actualGrossSalary: x.ActualGrossSalary,
                                                                                                           taxableIncome: x.TaxableIncome,
                                                                                                           totalMonthlyIncome: x.TotalMonthlyIncome,
                                                                                                           employeeSocialInsurance: x.EmployeeSocialInsurance,
                                                                                                           employeeHealthcareInsurance: x.EmployeeHealthcareInsurance,
                                                                                                           employeeUnemploymentInsurance: x.EmployeeUnemploymentInsurance,
                                                                                                           employeeUnionFee: x.EmployeeUnionFee,
                                                                                                           employerSocialInsurance: x.EmployerSocialInsurance,
                                                                                                           employerHealthcareInsurance: x.EmployerHealthcareInsurance,
                                                                                                           employerUnemploymentInsurance: x.EmployerUnemploymentInsurance,
                                                                                                           employerUnionFee: x.EmployerUnionFee,
                                                                                                           personalDeduction: x.PersonalDeduction,
                                                                                                           dependantDeduction: x.DependantDeduction,
                                                                                                           assessableIncome: x.AssessableIncome,
                                                                                                           netIncome: x.NetIncome,
                                                                                                           pit: x.PIT,
                                                                                                           totalSalaryCost: x.TotalSalaryCost,
                                                                                                           paymentAdvance: x.PaymentAdvance,
                                                                                                           taxableAllowances: x.TaxableAllowances,
                                                                                                           nonTaxableAllowances: x.NonTaxableAllowances.Select(x => x.Amount.Value).Sum(),
                                                                                                           netPayment: x.NetPayment,
                                                                                                           adjustmentAddition: x.AdjustmentAddition,
                                                                                                           adjustmentDeduction: x.AdjustmentDeduction)).OrderBy(x => x.Fullname).ToArray())));
            }

            var salaryConfig = await _configRepo.GetAsync();

            var recordsRepo = await _recordRepo.GetAsync(request.YearMonth, request.Key);

            var profilesRepo = await _profileRepo.GetAsync(request.YearMonth);

            var records = salaryConfig.Map(() => profilesRepo).Map(() => recordsRepo)
                          .Map(x => recordsRepo.Data.records.Where(y => profilesRepo.Data.Any(z =>
                                                                                              y.Email == z.Email)).ToList());

            var result = await records.Map(x => MapModelToCalculateSalary(x, profilesRepo.Data,
                                                                          recordsRepo.Data.standardWorkingDays))
                         .Map(x => Main.GeneratePayRollRecord(x.ToArray(), salaryConfig.Data))
                         // add new month records if there is no current month records.
                         .ExecuteAsync(x => _recordRepo.SaveAsync(records.Data, request.YearMonth, request.Key,
                                                                  recordsRepo.Data.standardWorkingDays))
                         // save calculated salary to db
                         .ExecuteAsync(x => _salaryRepo.SaveAsync(x, request.Key, request.YearMonth));

            return(result.Map(x => new PreviewEmpMonthlySalaryResponse(
                                  x.Select(y => new PreviewEmpMonthlySalary(
                                               fullname: y.Fullname,
                                               email: y.Email,
                                               employeeType: y.EmployeeType,
                                               position: y.Position,
                                               numberOfDependants: y.NumberOfDependants,
                                               standardWorkingDays: y.StandardWorkingDays,
                                               actualWorkingDays: y.ActualWorkingDays,
                                               grossContractSalary: y.GrossContractSalary,
                                               insuranceSalary: y.InsuranceSalary,
                                               actualGrossSalary: y.ActualGrossSalary,
                                               taxableIncome: y.TaxableIncome,
                                               totalMonthlyIncome: y.TotalMonthlyIncome,
                                               employeeSocialInsurance: y.EmployeeSocialInsurance,
                                               employeeHealthcareInsurance: y.EmployeeHealthcareInsurance,
                                               employeeUnemploymentInsurance: y.EmployeeUnemploymentInsurance,
                                               employeeUnionFee: y.EmployeeUnionFee,
                                               employerSocialInsurance: y.EmployerSocialInsurance,
                                               employerHealthcareInsurance: y.EmployerHealthcareInsurance,
                                               employerUnemploymentInsurance: y.EmployerUnemploymentInsurance,
                                               employerUnionFee: y.EmployerUnionFee,
                                               personalDeduction: y.PersonalDeduction,
                                               dependantDeduction: y.DependantDeduction,
                                               assessableIncome: y.AssessableIncome,
                                               netIncome: y.NetIncome,
                                               pit: y.PIT,
                                               totalSalaryCost: y.TotalSalaryCost,
                                               paymentAdvance: y.PaymentAdvance,
                                               taxableAllowances: y.TaxableAllowances,
                                               nonTaxableAllowances: y.NonTaxableAllowances.Select(z => z.Amount.Value).Sum(),
                                               netPayment: y.NetPayment,
                                               adjustmentAddition: y.AdjustmentAddition,
                                               adjustmentDeduction: y.AdjustmentDeduction)).ToArray())));
        }
        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);
            }
        }