php 如果模型已经在数据库中,如何跳过而不创建新模型

c3frrgcw  于 2023-02-03  发布在  PHP
关注(0)|答案(1)|浏览(118)

大家好,我正在做一件事,我们通过laravel-excel读取上传到excel上的客户账单。我现在遇到的问题是,每次有人上传一个新账单,它都会覆盖同一年的前一个账单。在某个特定的时间点之前,这是可以的。在billngs表中有一个字段是“billing_points_reward”因此,我想要的是,一旦Excel被读取,如果该字段上有点不做新的计费等...计费表上的字段是“id”,“client_id”,“amount”,“billing_date”,“付费积分”、“创建时间”、“更新时间”。
因此,如果在“billing_points_reward”中有积分,则不要进行新的计费等...只需更新已经有积分的计费上的金额和计费日期,但不要将积分重置为NULL。
现在我正在做一个新的计费每次,为什么它重置字段,我应该怎么做,而不是如果我想首先检查数据库上的记录有点,如果有,不做新的计费,只是更新现有的一个.

public function model(array $row)
    {
        $date = Carbon::now();
        $date->year = $this->year;
        $date->day = 1;

        $clientCode = $row['id_client'];
        $totalAmount = $row['total'];
        $client = Client::where('code', $clientCode)->first();

        foreach ($row as $key => $dirtyAmount) {
            if (!$client) {
                continue;
            }
            $excludeColumn = false;

            switch ($key) {
                case 'january':
                    $date->month = 1;
                    break;
                case 'february':
                    $date->month = 2;
                    break;
                case 'march':
                    $date->month = 3;
                    break;
                case 'april':
                    $date->month = 4;
                    break;
                case 'may':
                    $date->month = 5;
                    break;
                case 'june':
                    $date->month = 6;
                    break;
                case 'july':
                    $date->month = 7;
                    break;
                case 'august':
                    $date->month = 8;
                    break;
                case 'september':
                    $date->month = 9;
                    break;
                case 'october':
                    $date->month = 10;
                    break;
                case 'november':
                    $date->month = 11;
                    break;
                case 'december':
                    $date->month = 12;
                    break;
                default:
                    $excludeColumn = true;
                    break;
            }

            if ($excludeColumn) {
                continue;
            }

            if (is_null($dirtyAmount)) {
                $billing = new Billing([
                    'amount' => 0,
                    'billing_date' => $date,
                ]);

                $client->billings()->save($billing);
            } else {
                $billing = new Billing([
                    'amount' => Money::parse($dirtyAmount),
                    'billing_date' => $date,
                ]);

                $client->billings()->save($billing);
            }

            if ($date->month == 12) {
                if (is_null($row['total'])) {
                    $billingTotal = new Billing([
                        'amount' => 0,
                        'billing_date' => $date->year . '-12-31 23:59:59',
                    ]);
                    $client->billings()->save($billingTotal);
                } else {
                
                    $billingTotal = new Billing([
                        'amount' => Money::parse($totalAmount),
                        'billing_date' => $date->year . '-12-31 23:59:59',
                    ]);
                    $client->billings()->save($billingTotal);
                }
            } else {
                continue;
            }
        }

        $billingYear = $date->year;

        

        if (!is_null($client)) {
            if ($client->kpis->count() > 0) {
                $this->completeKpibyBilling($billingYear, $client);
            }
        }

        return;
    }

尝试更新账单,而不是创建一个新的,但我做错了,它留给我的是检查该记录是否有'billing* pointsreward'所以,如果它有他们,而不是创建一个新的账单只是更新'amount'和'billing_date'和不接触点.*

vddsk6oq

vddsk6oq1#

让我们尝试改进您的代码。
对于现有客户的现有账单,要检查哪些内容的条件是按其billing_date

public function model(array $row): void
{
    $date = Carbon::now();
    $date->year = $this->year;
    $date->day = 1;

    $clientCode = $row['id_client'];
    $totalAmount = is_null($row['total']) ? 0 : $row['total'];

    $client = Client::query()
        ->with('billings')
        ->where('code', $clientCode)
        ->first();

    if (empty($client)) {
        // do something here ?
        throw new Exception("Unknown client code {$clientCode}", 401);
    }

    // get all billing belongs to client
    // filtered only has billing points reward above 0 (NO MORE)
    // in current requested billing year
    $billings = Billing::query()
        ->where('client_id', $client->id)
        ->whereYear('billing_date', $date->year)
        // ->where('billing_points_rewarded', '>', 0)
        ->where('is_closing', false)
        ->get()
        ->keyBy(fn ($data) => $data->billing_date->format('Y-m-d'));

    // I remove check billing_points_rewarded because
    // what if found a billing with billing_points_rewarded 0 or null
    // in this case best to just update the existing billing

    // dd($billings['2023-10-01']->toArray(), count($billings));

    // get months in array with int as key 
    $months = $this->getMonths();

    // key can be month name or id_client or total
    foreach ($row as $key => $dirtyAmount) {
        // if (!$client) {
        //    continue;
        // }

        // when key == id_client or total
        if (!isset($months[$key])) {
            continue;
        }

        if (is_null($dirtyAmount)) {
            $dirtyAmount = 0;
        }

        // do this instead of using switch
        $date->month = $months[$key];

        // check if there is already billing with same date
        if (isset($billings[$date->format('Y-m-d')])) {
            // skip update and create if reward point is 0
            if ($billings[$date->format('Y-m-d')]->billing_points_rewarded == 0) {
                continue;
            }
            // update it
            $billings[$date->format('Y-m-d')]->update([
                'billing_date' => $date,
                // 'amount' => Money::parse($dirtyAmount),
                'amount' => $dirtyAmount,
            ]);
            continue;
        }

        Billing::create([
            'client_id'     => $client->id,
            'amount'        => $dirtyAmount,
            'billing_date'  => $date,
        ]);

        if ($date->month == 12) {
            Billing::updateOrCreate(
                [
                   'client_id'     =>  $client->id,
                   'billing_date'  => $date->year . '-12-31 23:59:59',
                   'is_closing'    => true,
                ],
                [
                   'amount' => $totalAmount,
                ]
            );
        }
    }

    $billingYear = $date->year;

    if (!is_null($client)) {
        if ($client->kpis->count() > 0) {
            $this->completeKpibyBilling($billingYear, $client);
        }
    }

    return;
}

这是硬编码的数组中的月份列表。

public function getMonths() 
{
   // you might have this hardcoded like this
   // can store it inside Billing model as static method
   return [
     'january' => 1,
     'february' => 2,
     ...
     'december' => 12,
   ]; 
}

数据示例

$row = [
    'id_client'     => 4,
    'january'       => 100,
    'february'      => 100,
    'march'         => 100,
    'april'         => 0,
    'may'           => 100,
    'june'          => 100,
    'july'          => 100,
    'august'        => 100,
    'september'     => 100,
    'october'       => 100,
    'november'      => 100,
    'december'      => 100,
    'total'         => 1100,
 ];

 $row = [
    'id_client'     => 4,
    'january'       => 100,
    'february'      => 100,
    'march'         => 100,
    'april'         => 100, // should updated from 0 to 100
    'may'           => 100,
    'june'          => 100,
    'july'          => 100,
    'august'        => 100,
    'september'     => 100,
    'october'       => 100,
    'november'      => 100,
    'december'      => 100,
    'total'         => 1200, // should updated from 1100 to 1200
 ];

相关问题