postgresql Laravel Transaction Not Working On Collection each()方法

cmssoen2  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(112)

我有一个类,通过Excel文件执行循环,并像这样插入每一个有效的行。

<?php

namespace App\Services\Factory\PayrollUpload\Impl;
use App\Helpers\Api\Facades\HrisOutbound;
use App\Helpers\Constants\ExcelFile;
use App\Models\Allowance;
use App\Models\Deduction;
use App\Models\Salary;
use App\Repository\Facades\AllowanceRepository;
use App\Repository\Facades\DeductionRepository;
use App\Repository\Facades\PeriodRepository;
use App\Repository\Facades\SalaryRepository;
use App\Services\Factory\PayrollUpload\Base\PayrollUploadBase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Spatie\SimpleExcel\SimpleExcelReader;
use Spatie\SimpleExcel\SimpleExcelWriter;

class EPayrollUpload implements PayrollUploadBase
{

    /**
     * Method process file to table
     *
     * @param $file $file xlsx
     * @param $companyCode $companyCode
     * @param $month $month
     * @param $year $year
     *
     * @return array
     */
    public function process(UploadedFile $file, $companyCode, $month, $year)
    {
        $result = [];
        $failedRows = [];
        $success = 0;
        $failed = 0;
        /** @var SimpleExcelReader $excelFile */
        $excelFile = SimpleExcelReader::create($file, 'xlsx');
        // Count Total Rows
        $totalRows = $excelFile->getRows()->count();
        $lowerCaseHeaders = array_map('strtolower', SimpleExcelReader::create($file, 'xlsx')->getHeaders());

        DB::beginTransaction();

        // Loop Through Excel File
        $excelFile
                  ->useHeaders($lowerCaseHeaders)
                  ->getRows()
                  ->each(function ($row, $index) use ($companyCode, $month, $year, $success, $failed, $failedRows)
                  {
                    try
                    {
                        // Get Employee Detail
                        $employeeDetail = HrisOutbound::getEmployeeDetail($row["nik"], $companyCode);
                        // Grouping Allowances
                        $allowances = self::getValuesByKeys($row, ExcelFile::ETHOS_ALLOWANCES);
                        // Grouping Deductions
                        $deductions = self::getValuesByKeys($row, ExcelFile::ETHOS_DEDUCTIONS);
                        // Grouping Tax
                        // Find base salary
                        $baseSalary = self::sumValuesByKeys($row, ["total gaji proporsional"]);
                        // Find Total Earning
                        $totalEarning = self::sumValuesByKeys($row, ["thp"]);
                        $totalAllowances = self::sumValuesByKeys($row, ExcelFile::ETHOS_ALLOWANCES);
                        $totalDeduction = self::sumValuesByKeys($row, ExcelFile::ETHOS_DEDUCTIONS);

                        // Find Or Create Period
                        DB::beginTransaction();

                        $period = PeriodRepository::getOrCreate($companyCode, $month, $year);

                        // Save to table salaries
                        $salary = new Salary();
                        $salary->employee_id = $employeeDetail["data"]["employee"]["id"];
                        $salary->company_id = $employeeDetail["data"]["employee"]["company_id"];
                        $salary->company_code = $companyCode;
                        $salary->base_salary = $baseSalary;
                        $salary->net_salary = $totalEarning;
                        $salary->deductions = $totalDeduction;
                        $salary->allowances = $totalAllowances;
                        $salary->period_id = $period->period_id;

                        $salary->save();

                        foreach($allowances as $key => $allowance)
                        {
                            $allow = new Allowance();
                            $allow->salary_id = $salary->salary_id;
                            $allow->allowance_name = $key;
                            $allow->amount = $allowance;
                            $allow->save();
                        }

                        foreach ($deductions as $key => $deduction)
                        {
                            $deduct = new Deduction();
                            $deduct->salary_id = $salary->salary_id;
                            $deduct->deduction_name = $key;
                            $deduct->amount = $deduction;
                            $deduct->save();
                        }

                        // Increment success count
                        $success++;

                        DB::commit();
                    }
                    catch (\Throwable $th)
                    {
                        // Add failed to collection failed
                        DB::rollBack();
                        $row["error"] = $th->getMessage();
                        $failedRows[] = $row;
                        $failed++;
                    }
                  });

        // If not empty store failed collection as excel file in S3
        // if(!empty($failedRows))
        // {
        //     /** @var SimpleExcelWriter $excel */
        //     $excel = SimpleExcelWriter::create($file->getFilename()."_result.xlsx");
        //     $excel->addRows($failedRows);

        //     Storage::disk('s3')->put('folder/example.xlsx', $excel->__destruct());
        // }

        $result["company_code"] = $companyCode;
        $result["month"] = $month;
        $result["year"] = $year;
        $result["total_row"] = $totalRows;
        $result["success_row"] = $success;
        $result["failed_row"] = $failed;
        // $result["file_result_url"] = Storage::disk('s3')->url('folder/example.xlsx');

        return $result;
    }

    /**
     * Method getValuesByKeys
     *
     * @param array $data array to proceed
     * @param array $keysToRetrieve keys to filter
     *
     * @return array
     */
    private function getValuesByKeys(array $data, array $keysToRetrieve)
    {
        $values = [];

        foreach ($keysToRetrieve as $key)
        {
            $values[$key] = Arr::get($data, $key);
        }

        return $values;
    }

    private function sumValuesByKeys(array $data, array $keysToRetrieve)
    {
        $sum = 0;

        foreach ($keysToRetrieve as $key)
        {
            $value = Arr::get($data, $key);

            if (is_numeric($value))
            {
                $sum += $value;
            }
            else
            {
                throw new \InvalidArgumentException("KEY_'{$key}'IS_NOT_NUMERIC");
            }
        }

        return $sum;
    }
}

字符串
我有一个测试,检查代码是否运行循环,并确保数据插入到数据库,测试通过,但如果我在开发模式下运行此代码,并尝试向API上传请求,它不会执行DB事务,并且没有发生错误,表salaries中的数据为空,表periods中的数据也为空
我的代码运行在Laravel(容器)上,它们也连接到容器内的postgresql数据库。这是我的docker-compose.yml

services:
  http:
    image: nginx:1.20
    ports:
      - '8881:80'
    volumes:
      - './:/app/'
      - './docker/nginx/nginx.conf:/etc/nginx/nginx.conf'
    depends_on:
      - php
    networks:
      - payroll_network
  php:
    build:
      context: ./docker/php/
      args:
        WWWUSER: 'laravel'
        WWWUID: '1000'
    volumes:
      - '.:/app/'
    # extra_hosts:
    #   - 'host.docker.internal:host-gateway'
    networks:
      - payroll_network
    depends_on:
      - pgsql
    links:
      - pgsql
      - mailhog
      - localstack
#   node:
#     image: node:16
#     volumes:
#         - './:/app/'
#     working_dir: '/app/'
  pgsql:
    container_name: 'payroll_db'
    image: postgres:14
    ports:
      - '${DB_PORT:-5432}:5432'
    environment:
      PGPASSWORD: '${DB_PASSWORD:-secret}'
      POSTGRES_DB: '${DB_DATABASE:-laravel}'
      POSTGRES_USER: '${DB_USERNAME:-laravel}'
      POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
      PGDATA: '/data/postgres'
    volumes:
      - 'pgsql:/data/postgres'
    networks:
      - payroll_network
    healthcheck:
      test: [ "CMD", "pg_isready", "-q", "-d", "${DB_DATABASE:-laravel}", "-U", "${DB_USERNAME:-laravel}" ]
  mailhog:
    image: 'mailhog/mailhog:latest'
    ports:
      - '${FORWARD_MAILHOG_PORT:-1025}:1025'
      - '${FORWARD_MAILHOG_DASHBOARD_PORT:-8025}:8025'
    networks:
      - payroll_network

  localstack:
    image: localstack/localstack
    environment:
      - SERVICES=s3
      - DEFAULT_REGION=${AWS_DEFAULT_REGION}
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
    ports:
      - "4566:4566"  # Port untuk LocalStack S3
    networks:
      - payroll_network

networks:
  payroll_network:
    driver: bridge

volumes:
  pgsql:


我错过什么了吗?因为数据库事务不能正常工作,没有异常发生,是不是集合each()方法有什么问题?

jaql4c8m

jaql4c8m1#

所以我弄清楚了在我的代码中持续存在的问题,在Hrislogy::getProblem Detail()中有一个由http请求抛出的throwable,这个代码不是由catch异常处理的,它应该添加更多的catch和Throwable,所以我这样修改了我的代码

// Loop Through Excel File
        $excelFile
                  ->useHeaders($lowerCaseHeaders)
                  ->getRows()
                  ->each(function ($row) use ($companyCode, $month, $year, &$success, &$failed, &$failedRows)
                  {
                    try
                    {
                        // Get Employee Detail
                        $employeeDetail = HrisOutbound::getEmployeeDetail($row["nik"], $companyCode);
                        // Grouping Allowances
                        $allowances = self::getValuesByKeys($row, ExcelFile::ETHOS_ALLOWANCES);
                        // Grouping Deductions
                        $deductions = self::getValuesByKeys($row, ExcelFile::ETHOS_DEDUCTIONS);
                        // Grouping Tax
                        // Find base salary
                        $baseSalary = self::sumValuesByKeys($row, ["total gaji proporsional"]);
                        // Find Total Earning
                        $totalEarning = self::sumValuesByKeys($row, ["thp"]);
                        $totalAllowances = self::sumValuesByKeys($row, ExcelFile::ETHOS_ALLOWANCES);
                        $totalDeduction = self::sumValuesByKeys($row, ExcelFile::ETHOS_DEDUCTIONS);

                        // Find Or Create Period
                        DB::beginTransaction();

                        $period = PeriodRepository::getOrCreate($companyCode, $month, $year);

                        // Save to table salaries
                        $salary = new Salary();
                        $salary->employee_id = $employeeDetail["data"]["employee"]["id"];
                        $salary->company_id = $employeeDetail["data"]["employee"]["company_id"];
                        $salary->company_code = $companyCode;
                        $salary->base_salary = $baseSalary;
                        $salary->net_salary = $totalEarning;
                        $salary->deductions = $totalDeduction;
                        $salary->allowances = $totalAllowances;
                        $salary->period_id = $period->period_id;

                        $salary->save();

                        foreach($allowances as $key => $allowance)
                        {
                            $allow = new Allowance();
                            $allow->salary_id = $salary->salary_id;
                            $allow->allowance_name = $key;
                            $allow->amount = $allowance;
                            $allow->save();
                        }

                        foreach ($deductions as $key => $deduction)
                        {
                            $deduct = new Deduction();
                            $deduct->salary_id = $salary->salary_id;
                            $deduct->deduction_name = $key;
                            $deduct->amount = $deduction;
                            $deduct->save();
                        }

                        // Increment success count
                        $success++;

                        DB::commit();
                    }
                    catch(\Throwable $th)
                    {
                        // Add failed to collection failed
                        DB::rollBack();
                        $row["error"] = $th->getMessage();
                        $failedRows[] = $row;
                        $failed++;
                    }
                    catch(\Exception $e)
                    {
                        // Add failed to collection failed
                        DB::rollBack();
                        $row["error"] = $e->getMessage();
                        $failedRows[] = $row;
                        $failed++;
                    }
                  });

字符串

相关问题