load($recordNo); } else { $this->receipt = new Receipt(); } } public function getReceipt(): Receipt { return $this->receipt; } public function create(array $paymentPlanRecordNoList) { // 支払予定データの取得 $payments = $this->getPayments($paymentPlanRecordNoList); $this->checkPayments($payments, count($paymentPlanRecordNoList)); // 顧客取得 $customer = Customer::findByCustomerCode($payments->first()->customerCode); $receipt = $this->receipt; $receipt->receiptNo = $this->getReceiptNo(); $receipt->receiptDate = DateUtil::now(); $receipt->invoiceNo = config("business.invoiceNo", ""); $receipt->receiptName = $this->getReceiptName($payments); $receipt->customerCode = $customer->customerCode; $receipt->taxType = "内税"; $receipt->receiptCustomerName = $customer->customerName; $receipt->receiptTotalAmount = 0; // 明細------------ foreach ($payments as $payment) { $detail = new ReceiptDetail(); $detail->name = $payment->paymentType; $detail->parkingName = $payment->parkingName; $detail->unitPrice = $payment->appropriationAmount; $detail->quantity = 1; $detail->amount = $detail->unitPrice * $detail->quantity; $detail->targetMonth = $payment->targetMonth ? sprintf("%d月分", $payment->targetMonth) : ""; $detail->taxRate = config("business.taxRate.normal", 0); $detail->memo = "memo"; $receipt->receiptDetail->push($detail); $receipt->receiptTotalAmount += $payment->appropriationAmount; } // 内税明細-------------- foreach ($receipt->receiptDetail as $detail) { $tax = $receipt->taxDetail->first(function (TaxDetail $ele) use ($detail) { return $ele->taxRate === $detail->taxRate; }); if ($tax === null) { $tax = new TaxDetail(); $tax->taxRate = $detail->taxRate; $receipt->taxDetail->push($tax); } if ($tax instanceof TaxDetail) { $tax->totalAmount += $detail->amount; } } // 税率の昇順に並び替え $receipt->taxDetail->sort(function (TaxDetail $a, TaxDetail $b) { return $a->taxRate < $b->taxRate ? -1 : 1; }); // 内税計算 foreach ($receipt->taxDetail as $detail) { $detail->taxAmount = TaxUtil::calcInnerTaxAmount($detail->totalAmount, $detail->taxRate); } // 入金実績--------------- foreach ($payments as $payment) { $detail = new ReceiptPaymentPlan(); $detail->recordNo = $payment->getRecordId(); $receipt->paymentPlans->push($detail); } $receipt->save(); return $this; } private function getPayments(array $paymentPlanRecordNoList) { $query = PaymentPlan::getQuery()->whereIn(PaymentPlan::FIELD_RECORD_NO, $paymentPlanRecordNoList); $ret = PaymentPlan::getAccess()->all($query); return $ret; } /** * @param Collection $payments * @return void */ private function checkPayments(Collection $payments, int $expectCount) { // データチェック if ($payments->isEmpty()) { throw new AppCommonException("支払予定検索0件"); } if ($payments->count() !== $expectCount) { throw new AppCommonException(sprintf("件数不正 %d件 期待値:%d件 ", $payments->count(), $expectCount)); } $customerCode = $payments->first()->customerCode; foreach ($payments as $payment) { if (!$payment->donePayment()) { throw new AppCommonException(sprintf("支払済みでない支払 %d ", $payment->getRecordId())); } if ($payment->customerCode !== $customerCode) { throw new AppCommonException(sprintf("単一の顧客コードのみ設定可能 %d or %d", $customerCode, $payment->customerCode)); } } } /** * @param Collection $payments * @return void */ private function getReceiptName(Collection $payments): string { $seasonTicketCount = 0; $otherCount = 0; $otherName = ""; foreach ($payments as $payment) { if ($payment->paymentType === PaymentType::SEASON_TICKET) { $seasonTicketCount++; } else { $otherCount++; $otherName = $payment->paymentType; } } if (0 < $seasonTicketCount && $otherCount === 0) { return "定期料金"; } if (0 < $seasonTicketCount && 0 < $otherCount) { return "定期料金ほか"; } return $otherName; } private function load(int $recordNo) { $this->receipt = Receipt::find($recordNo); } public function makePdf(): ReceiptReceipt { $pdf = PDF::loadView("pdf/receipt", $this->getPdfData()) // ->setPaper("A4") ->setOption('page-width', 210) ->setOption('page-height', 148) ->setOrientation("Portrait") ->setOption('encoding', 'utf-8'); $file = new ReceiptReceipt(); $file->setAppFileName($this->makeFileName($file)) ->put($pdf->output()); return $file; } private function makeFileName(ReceiptReceipt $file) { return sprintf( "領収証_%s_%s_%s.%s", $this->receipt->receiptNo, $this->receipt->customerName, $this->receipt->receiptPurpose, $file->getFileExtension(), ); } private function getPdfData() { return [ 'receiptDate' => "2023/10/17", 'receiptCustomerName' => $this->receipt->receiptCustomerName, 'receiptTotalAmount' => number_format($this->receipt->receiptTotalAmount), 'taxTotalAmount' => number_format(100), 'receiptPurpose' => $this->receipt->receiptPurpose, ]; } private function getReceiptNo(): string { /** * 申請番号を発番する。重複チェックを一定回数行う。 */ for ($i = 0; $i < 10; $i++) { $no = sprintf("%s-R%06d", DateUtil::now()->format('Ymd'), rand(1, 999999)); $check = Receipt::getAccess()->some(Receipt::getQuery()->where(Receipt::FIELD_RECEIPT_NO, $no)); if ($check->isEmpty()) { return $no; } } throw new AppCommonException('申請番号取得失敗'); } }