diff --git a/app/Email/BaseEmailer.php b/app/Email/BaseEmailer.php index f97320f..26a19f5 100644 --- a/app/Email/BaseEmailer.php +++ b/app/Email/BaseEmailer.php @@ -8,6 +8,7 @@ use App\Models\Email; use App\Models\EmailAttachment; use App\Models\User; use App\Util\DateUtil; +use App\Util\UrlUtil; use Illuminate\Bus\Queueable; use Illuminate\Database\Eloquent\Collection; use Illuminate\Mail\Mailable; @@ -180,24 +181,6 @@ abstract class BaseEmailer extends Mailable */ protected function getAppUrl(array|string $path, array $query = []): string { - $elements = [config("app.url")]; - if (is_array($path)) { - $elements = array_merge($elements, $path); - } else { - $elements[] = $path; - } - - $url = implode("/", $elements); - - if (!!$query) { - $url .= "?"; - $queryStrList = []; - foreach ($query as $key => $value) { - $queryStrList[] = sprintf("%s=%s", $key, $value); - } - $url .= implode("&", $queryStrList); - } - - return $url; + return UrlUtil::getAppUrl($path, $query); } } diff --git a/app/Http/Controllers/Web/Receipt/ReceiptDownloadController.php b/app/Http/Controllers/Web/Receipt/ReceiptDownloadController.php new file mode 100644 index 0000000..8e66be3 --- /dev/null +++ b/app/Http/Controllers/Web/Receipt/ReceiptDownloadController.php @@ -0,0 +1,49 @@ +middleware('auth:sanctum'); + } + + protected function run(Request $request): Response + { + $param = $this->param; + $manager = new ReceiptManager($param->recordNo); + + if ($manager->getReceipt()->receiptNo !== $param->receiptNo) { + throw new AppCommonException("パラメータ不正"); + } + + $customerCode = $manager->getReceipt()->customerCode; + $customerCodeAuth = Auth::user()->kintone_customer_code; + if ($customerCode != $customerCodeAuth) { + throw new AppCommonException("パラメータ不正"); + } + + return $manager->getPdf(); + } +} diff --git a/app/Http/Controllers/Web/Receipt/ReceiptDownloadParam.php b/app/Http/Controllers/Web/Receipt/ReceiptDownloadParam.php new file mode 100644 index 0000000..c45a1d5 --- /dev/null +++ b/app/Http/Controllers/Web/Receipt/ReceiptDownloadParam.php @@ -0,0 +1,20 @@ + $this->str(), + 'receipt_no' => $this->str(), + ]; + } +} diff --git a/app/Http/Controllers/Web/Receipt/ReceiptsController.php b/app/Http/Controllers/Web/Receipt/ReceiptsController.php new file mode 100644 index 0000000..ba1c5c9 --- /dev/null +++ b/app/Http/Controllers/Web/Receipt/ReceiptsController.php @@ -0,0 +1,46 @@ +middleware('auth:sanctum'); + } + + protected function run(Request $request): JsonResponse + { + $user = Auth::user(); + + $list = ReceiptRepository::get($user->kintone_customer_code); + + $result = []; + + foreach ($list as $ele) { + $result[] = $ele->toArray(); + } + + return $this->successResponse($result); + } +} diff --git a/app/Http/Controllers/Web/Receipt/ReceiptsParam.php b/app/Http/Controllers/Web/Receipt/ReceiptsParam.php new file mode 100644 index 0000000..45511e9 --- /dev/null +++ b/app/Http/Controllers/Web/Receipt/ReceiptsParam.php @@ -0,0 +1,9 @@ + 'receipt_date', + self::FIELD_RECEIPT_NAME => 'receipt_name', + self::FIELD_RECEIPT_TOTAL_AMOUNT => 'total_amount', ]; protected const SUB_TABLES = [ @@ -98,4 +103,11 @@ class Receipt extends KintoneModel Customer::class, ModelsPaymentPlan::class, ]; + + protected function toArrayCustom(): array + { + return [ + 'pdf_url' => RouteHelper::getPath(ReceiptDownloadController::class, ['receipt_no' => $this->receiptNo, 'record_no' => $this->getRecordId()]), + ]; + } } diff --git a/app/Kintone/Repositories/ReceiptRepository.php b/app/Kintone/Repositories/ReceiptRepository.php new file mode 100644 index 0000000..4092953 --- /dev/null +++ b/app/Kintone/Repositories/ReceiptRepository.php @@ -0,0 +1,28 @@ + + */ + static function get(int $customerCode): Collection + { + + $ret = collect(); + $query = Receipt::getQuery()->where(Receipt::FIELD_CUSTOMER_CODE, $customerCode)->orderByDesc(Receipt::FIELD_RECEIPT_DATE); + $all = Receipt::getAccess()->all($query); + + $all->map(function (Receipt $receipt) use ($ret) { + $ret->push(new ReceiptRepositoryData($receipt)); + }); + + return $ret; + } +} diff --git a/app/Kintone/Repositories/ReceiptRepositoryData.php b/app/Kintone/Repositories/ReceiptRepositoryData.php new file mode 100644 index 0000000..40698f7 --- /dev/null +++ b/app/Kintone/Repositories/ReceiptRepositoryData.php @@ -0,0 +1,20 @@ +receipt->toArray(), + ]; + } +} diff --git a/app/Logic/ReceiptManager.php b/app/Logic/ReceiptManager.php index 17a3c49..d704455 100644 --- a/app/Logic/ReceiptManager.php +++ b/app/Logic/ReceiptManager.php @@ -181,9 +181,9 @@ class ReceiptManager public function makePdf(): ReceiptReceipt { $pdf = PDF::loadView("pdf/receipt", $this->getPdfData()) - // ->setPaper("A4") - ->setOption('page-width', 210) - ->setOption('page-height', 148) + ->setPaper("A4") + // ->setOption('page-width', 210) + // ->setOption('page-height', 148) ->setOrientation("Portrait") ->setOption('encoding', 'utf-8'); @@ -195,6 +195,23 @@ class ReceiptManager return $file; } + public function getPdf() + { + $pdf = PDF::loadView("pdf/receipt", $this->getPdfData()) + ->setPaper("A4") + // ->setOption('page-width', 210) + // ->setOption('page-height', 148) + ->setOrientation("Portrait") + ->setOption('encoding', 'utf-8'); + + return $pdf->inline(); + } + + public function getHtml() + { + return response()->view("pdf/receipt", ["forHtml" => true, ...$this->getPdfData()]); + } + private function makeFileName(ReceiptReceipt $file) { return sprintf( @@ -209,14 +226,23 @@ class ReceiptManager private function getPdfData() { return [ - 'receiptDate' => "2023/10/17", + 'receiptDate' => $this->receipt->receiptDate->format('Y/m/d'), 'receiptCustomerName' => $this->receipt->receiptCustomerName, 'receiptTotalAmount' => number_format($this->receipt->receiptTotalAmount), - 'taxTotalAmount' => number_format(100), - 'receiptPurpose' => $this->receipt->receiptPurpose, + '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 { diff --git a/app/Util/RouteHelper.php b/app/Util/RouteHelper.php index 39cd4cf..ec50a5e 100644 --- a/app/Util/RouteHelper.php +++ b/app/Util/RouteHelper.php @@ -34,6 +34,11 @@ class RouteHelper return $routeName; } + static public function getPath(string $controllerClassName, array $param = []) + { + return route(self::routeName($controllerClassName), $param); + } + static public function webRoute(string $route) { return Str::replaceFirst('/api', '', $route); diff --git a/app/Util/UrlUtil.php b/app/Util/UrlUtil.php new file mode 100644 index 0000000..83ee5c7 --- /dev/null +++ b/app/Util/UrlUtil.php @@ -0,0 +1,36 @@ + $value) { + $queryStrList[] = sprintf("%s=%s", $key, $value); + } + $url .= implode("&", $queryStrList); + } + + return $url; + } +} diff --git a/resources/views/pdf/common.css b/resources/views/pdf/common.css new file mode 100644 index 0000000..1ac8975 --- /dev/null +++ b/resources/views/pdf/common.css @@ -0,0 +1,32 @@ +.flex { + display: flex; + display: -webkit-box; +} + +.flex-start { + display: flex; + display: -webkit-box; + justify-content: start; + -webkit-box-pack: start; +} + +.flex-center { + display: flex; + display: -webkit-box; + justify-content: center; + -webkit-box-pack: center; +} + +.flex-end { + display: flex; + display: -webkit-box; + justify-content: end; + -webkit-box-pack: end; +} + +.flex-space-between { + display: flex; + display: -webkit-box; + justify-content: space-between; + -webkit-box-pack: justify; +} \ No newline at end of file diff --git a/resources/views/pdf/receipt.blade.php b/resources/views/pdf/receipt.blade.php index 9f5f2ff..219499b 100644 --- a/resources/views/pdf/receipt.blade.php +++ b/resources/views/pdf/receipt.blade.php @@ -4,30 +4,98 @@ 領収証 - + + -
- 領収証 -
-
{{ $receiptCustomerName }}様
-
領収日 {{ $receiptDate }}
-
金額{{ $receiptTotalAmount }}(税込)
-
税率10% ¥{{ $taxTotalAmount }}
-
-

- 但し {{ $receiptPurpose }} として -

-

- 上記正に領収いたしました -

-
-
-

一般財団法人 京都市都市整備公社

-

〒600-8421

-

京都市下京区小道通烏丸西入童侍者町167番

-

登録番号 T7 1300 0501 2806

+
+ +
+
+ 領収書 +
+
+ + + +
+ +
+ {{ $receiptCustomerName }}様 +
+
+ 領収日 {{ $receiptDate }} +
+ +
+
+ + + +
+ 金額 +
+
+ ¥{{ $receiptTotalAmount }}- +
+
+ (税込) + +
+
+ +
+
+
+ + 税率10% +
+
+ ¥{{ number_format($taxTotalAmount) }} +
+
+
+ + +
+ + + + + + + + + + @foreach($detail as $ele) + + + + + + + @endforeach + +
駐車場名金額対象月備考
{{ $ele->parkingName }}¥{{ number_format($ele->amount) }}{{ sprintf("%d月分", $ele->targetMonth) }}{{ $ele->memo }}
+
+ +
+ 上記正に領収いたしました。 +
+ + +
+
+

一般財団法人 京都市都市整備公社

+

〒600-8421

+

京都市下京区小道通烏丸西入童侍者町167番

+

登録番号 T7 1300 0501 2806

+
+ +
+ +
diff --git a/resources/views/pdf/receipt.css b/resources/views/pdf/receipt.css index a0a82e8..2997ef2 100644 --- a/resources/views/pdf/receipt.css +++ b/resources/views/pdf/receipt.css @@ -1,67 +1,109 @@ - body { - position: relative; - font-size: 5mm + font-size: 3.5mm } -body div { - position: absolute; +#content { + padding: 20mm; + padding-top: 10mm } + #title { - top : 10mm; - left: 100mm; - font-size: 10mm; + font-size: 7mm; font-weight: bold; - letter-spacing: 10mm; + letter-spacing: 5mm; } -.receiptCustomerName { - top : 30mm; -} #receiptCustomerName { - left: 100mm; + font-size: 5mm; + padding-top: 10mm; } + #receiptDate { - left: 150mm; + margin-left: 50mm; } #receiptTotalAmount { border-top: solid 1px; border-bottom: solid 1px; - padding-top: 2mm;; + padding-top: 2mm; padding-bottom: 2mm; + margin-top: 10mm; + margin-bottom: 2mm; + + font-size: 5mm; + font-weight: bold; + + width: 150mm; - top: 50mm; - left: 20mm; - width: 170mm; +} + +#receiptTotalAmount :nth-of-type(1) { + margin-left: 10mm; +} + +#receiptTotalAmount :nth-last-of-type(1) { + margin-right: 6mm; } #taxTotalAmount { - border-bottom: solid 1px; - padding-bottom: 2mm; + width: 150mm; +} + +#taxTotalAmount>div { + width: 60mm; + border-bottom: solid 0.5px; +} - top: 65mm; - left: 140mm; - width: 50mm; +#taxTotalAmount>div :nth-of-type(1) { + margin-left: 10mm; } -#receiptPurpose { - top: 70mm; - left: 20mm; +#taxTotalAmount>div :nth-of-type(2) { + margin-right: 10mm; } + +#detailTable { + margin-top: 5mm; +} + +#detailTable table { + border-collapse: collapse; + /* セルの線を重ねる */ + width: 150mm; + text-align: left; +} + +#detailTable th, +td { + border: solid 0.5px; + /* 枠線指定 */ +} + +#detailTable th.amount { + width: 20mm; +} + +#detailTable th.targetMonth { + width: 15mm; +} + + #company { - top: 130mm; - left: 150mm; font-size: 4mm; + margin-top: 5mm; } + + #company p { margin: 1mm; } + #company .name { font-size: 5mm; } - - +#stamp { + top: 100mm; +} \ No newline at end of file diff --git a/resources/views/pdf/stamp.png b/resources/views/pdf/stamp.png new file mode 100644 index 0000000..20f19c1 Binary files /dev/null and b/resources/views/pdf/stamp.png differ diff --git a/routes/api.php b/routes/api.php index 8c34437..1ef64fa 100644 --- a/routes/api.php +++ b/routes/api.php @@ -36,6 +36,10 @@ RouteHelper::post('/season-ticket-contract/entry/cancel', App\Http\Controllers\W RouteHelper::get('/season-ticket-contract/selection/info', App\Http\Controllers\Web\SeasonTicketContract\Selection\SelectionInfoController::class); RouteHelper::post('/season-ticket-contract/selection/entry', App\Http\Controllers\Web\SeasonTicketContract\Selection\EntryController::class); +RouteHelper::get('/receipts', App\Http\Controllers\Web\Receipt\ReceiptsController::class); +RouteHelper::get('/receipt/download', App\Http\Controllers\Web\Receipt\ReceiptDownloadController::class); + + RouteHelper::get('/faq', App\Http\Controllers\Web\FAQ\FAQsController::class); RouteHelper::get('/faq/genres', App\Http\Controllers\Web\FAQ\FAQGenresController::class); RouteHelper::post('/ask', App\Http\Controllers\Web\FAQ\AskController::class);