|
- <?php
-
- namespace App\Logic;
-
- use App\Exceptions\AppCommonException;
- use App\Exceptions\GeneralErrorMessageException;
- use App\Files\PDF\Receipt as ReceiptReceipt;
- use App\Kintone\Models\Customer;
- use App\Kintone\Models\DropDown\PaymentPlan\PaymentType;
- use App\Kintone\Models\PaymentPlan;
- use App\Kintone\Models\Receipt;
- use App\Kintone\Models\SubTable\Receipt\PaymentPlan as ReceiptPaymentPlan;
- use App\Kintone\Models\SubTable\Receipt\ReceiptDetail;
- use App\Kintone\Models\SubTable\Receipt\TaxDetail;
- use App\Util\DateUtil;
- use App\Util\TaxUtil;
- use Exception;
- use Illuminate\Support\Collection;
- use PDF;
-
- class ReceiptManager
- {
- private ?Receipt $receipt = null;
-
- public function __construct(?int $recordNo = null)
- {
- if ($recordNo) {
- $this->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<int, PaymentPlan> $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<int, PaymentPlan> $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 = $this->pdf();
-
-
- $file = new ReceiptReceipt();
- $file->setAppFileName($this->makeFileName($file))
- ->put($pdf->output());
-
- return $file;
- }
-
- public function savePdf()
- {
- if ($this->receipt === null) {
- throw new Exception("領収証不正");
- }
-
- $file = $this->makePdf();
- $access = Receipt::getAccess();
-
- $data = [];
- $data[] = [
- 'fileKey' => $access->filePut($file),
- 'name' => sprintf("領収証_%s.pdf", $this->receipt->receiptNo),
- 'contentType' => $file->getMimeType(),
- ];
-
- $this->receipt->set(Receipt::FIELD_RECEIPT_PDF_FILE, $data);
-
- $this->receipt->save();
- }
-
- public function getPdf()
- {
- $pdf = $this->pdf();
-
- if ($this->receipt->receiptPdfFileDownloadDatetime === null) {
- $this->receipt->receiptPdfFileDownloadDatetime = DateUtil::now();
- $this->savePdf();
- }
-
- return $pdf->inline();
- }
-
- private function pdf()
- {
- return PDF::loadView("pdf/receipt", $this->getPdfData())
- ->setPaper("A4")
- // ->setOption('page-width', 210)
- // ->setOption('page-height', 148)
- ->setOrientation("Portrait")
- ->setOption('encoding', 'utf-8');
- }
-
- public function getHtml()
- {
- return response()->view("pdf/receipt", ["forHtml" => true, ...$this->getPdfData()]);
- }
-
- private function makeFileName(ReceiptReceipt $file)
- {
- return sprintf(
- "領収証_%s_%s.%s",
- $this->receipt->receiptNo,
- $this->receipt->customerName,
- $file->getFileExtension(),
- );
- }
-
- private function getPdfData()
- {
- return [
- 'receiptDate' => $this->receipt->receiptDate->format('Y/m/d'),
- 'receiptCustomerName' => $this->receipt->receiptCustomerName,
- 'receiptTotalAmount' => number_format($this->receipt->receiptTotalAmount),
- 'taxTotalAmount' => $this->getTaxAmount10(),
- 'detail' => $this->receipt->receiptDetail,
- ];
- }
-
- private function getTaxAmount10(): int
- {
- $receipt = $this->receipt->taxDetail->first(function (TaxDetail $tax) {
- return $tax->taxRate === 10;
- });
-
- return $receipt ? $receipt->taxAmount : 0;
- }
-
- 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('申請番号取得失敗');
- }
- }
|