| @@ -0,0 +1,47 @@ | |||||
| <?php | |||||
| namespace App\Files\PDF; | |||||
| use App\Files\TmpFile; | |||||
| abstract class PDFFile extends TmpFile | |||||
| { | |||||
| protected const DIR = ['pdf']; | |||||
| private string $appFileName = ""; | |||||
| public function __construct(?string $id = null) | |||||
| { | |||||
| parent::__construct($id); | |||||
| } | |||||
| /** | |||||
| * @override | |||||
| */ | |||||
| public function getFileExtension(): string | |||||
| { | |||||
| return "pdf"; | |||||
| } | |||||
| /** | |||||
| * @override | |||||
| */ | |||||
| public function getMimeType(): string | |||||
| { | |||||
| return "application/pdf"; | |||||
| } | |||||
| /** | |||||
| * @override | |||||
| */ | |||||
| public function getAppFileName() | |||||
| { | |||||
| return $this->appFileName; | |||||
| } | |||||
| public function setAppFileName(string $fileName) | |||||
| { | |||||
| $this->appFileName = $fileName; | |||||
| return $this; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| <?php | |||||
| namespace App\Files\PDF; | |||||
| class Receipt extends PDFFile | |||||
| { | |||||
| protected const DIR = [ | |||||
| ...parent::DIR, | |||||
| 'receipt' | |||||
| ]; | |||||
| /** | |||||
| * @override | |||||
| */ | |||||
| protected function getFileTypeName(): string | |||||
| { | |||||
| return "ReceiptPDF"; | |||||
| } | |||||
| } | |||||
| @@ -35,6 +35,8 @@ class TmpFile | |||||
| protected string $uuid; | protected string $uuid; | ||||
| protected string $content; | |||||
| public function __construct(?string $id = null) | public function __construct(?string $id = null) | ||||
| { | { | ||||
| @@ -59,16 +61,26 @@ class TmpFile | |||||
| return "tmp"; | return "tmp"; | ||||
| } | } | ||||
| protected function getFileExtension(): string | |||||
| public function getFileExtension(): string | |||||
| { | { | ||||
| return "tmp"; | return "tmp"; | ||||
| } | } | ||||
| final protected function getFileName(): string | |||||
| public function getMimeType(): string | |||||
| { | |||||
| return "txt/plain"; | |||||
| } | |||||
| final public function getFileName(): string | |||||
| { | { | ||||
| return sprintf("%s_%s.%s", $this->getFileTypeName(), $this->uuid, $this->getFileExtension()); | return sprintf("%s_%s.%s", $this->getFileTypeName(), $this->uuid, $this->getFileExtension()); | ||||
| } | } | ||||
| public function getAppFileName() | |||||
| { | |||||
| return $this->getFileName(); | |||||
| } | |||||
| public function getId(): string | public function getId(): string | ||||
| { | { | ||||
| return $this->uuid; | return $this->uuid; | ||||
| @@ -93,16 +105,25 @@ class TmpFile | |||||
| public function put(string $content) | public function put(string $content) | ||||
| { | { | ||||
| Storage::put($this->getPath(), $content); | Storage::put($this->getPath(), $content); | ||||
| $this->content = $content; | |||||
| return $this; | |||||
| } | } | ||||
| public function get() | |||||
| public function load() | |||||
| { | { | ||||
| return Storage::get($this->getPath()); | |||||
| $this->content = Storage::get($this->getPath()); | |||||
| return $this; | |||||
| } | } | ||||
| public function append(string $content) | public function append(string $content) | ||||
| { | { | ||||
| Storage::append($this->getPath(), $content); | Storage::append($this->getPath(), $content); | ||||
| $this->content .= $content; | |||||
| return $this; | |||||
| } | |||||
| public function get(): string | |||||
| { | |||||
| return $this->content; | |||||
| } | } | ||||
| public function download(string $name = "download") | public function download(string $name = "download") | ||||
| @@ -122,6 +143,7 @@ class TmpFile | |||||
| if ($ret) info(sprintf("ファイル削除:%s ", $this->getFullPath())); | if ($ret) info(sprintf("ファイル削除:%s ", $this->getFullPath())); | ||||
| return; | return; | ||||
| } else { | } else { | ||||
| $this->content = ""; | |||||
| DeleteFile::dispatch($this) | DeleteFile::dispatch($this) | ||||
| ->delay($delay); | ->delay($delay); | ||||
| return; | return; | ||||
| @@ -4,6 +4,7 @@ namespace App\Kintone; | |||||
| use App\Exceptions\AppCommonException; | use App\Exceptions\AppCommonException; | ||||
| use App\Exceptions\ConfigException; | use App\Exceptions\ConfigException; | ||||
| use App\Files\TmpFile; | |||||
| use App\Kintone\Models\KintoneModel; | use App\Kintone\Models\KintoneModel; | ||||
| use Exception; | use Exception; | ||||
| use Illuminate\Database\Eloquent\ModelNotFoundException; | use Illuminate\Database\Eloquent\ModelNotFoundException; | ||||
| @@ -403,16 +404,25 @@ class KintoneAccess | |||||
| /** | /** | ||||
| * ファイルアップロード | * ファイルアップロード | ||||
| * | * | ||||
| * @param UploadedFile $file | |||||
| * @param UploadedFile|TmpFile $file | |||||
| * @return string fileKey | * @return string fileKey | ||||
| */ | */ | ||||
| public function filePut(UploadedFile $file): string | |||||
| public function filePut(UploadedFile|TmpFile $file): string | |||||
| { | { | ||||
| $content = file_get_contents($file); | |||||
| $content = ""; | |||||
| $sendFileName = ""; | |||||
| if ($file instanceof UploadedFile) { | |||||
| $content = file_get_contents($file); | |||||
| $sendFileName = sprintf("file.%s", $file->extension()); | |||||
| } else if ($file instanceof TmpFile) { | |||||
| $content = $file->get(); | |||||
| $sendFileName = $file->getAppFileName(); | |||||
| } | |||||
| $response = Http::withHeaders([ | $response = Http::withHeaders([ | ||||
| "X-Cybozu-API-Token" => $this->apiToken, | "X-Cybozu-API-Token" => $this->apiToken, | ||||
| ]) | ]) | ||||
| ->attach("file", $content, sprintf("file.%s", $file->extension())) | |||||
| ->attach("file", $content, $sendFileName) | |||||
| ->post($this->getFileUrl()); | ->post($this->getFileUrl()); | ||||
| if ($response->failed()) { | if ($response->failed()) { | ||||
| @@ -2,15 +2,18 @@ | |||||
| namespace App\Kintone\Models; | namespace App\Kintone\Models; | ||||
| use App\Exceptions\AppCommonException; | |||||
| use App\Exceptions\ConfigException; | use App\Exceptions\ConfigException; | ||||
| use App\Files\TmpFile; | |||||
| use App\Kintone\File; | use App\Kintone\File; | ||||
| use App\Kintone\KintoneAccess; | use App\Kintone\KintoneAccess; | ||||
| use App\Kintone\KintoneAccessStore; | use App\Kintone\KintoneAccessStore; | ||||
| use App\Kintone\KintoneRecordQuery; | use App\Kintone\KintoneRecordQuery; | ||||
| use App\Kintone\Models\SubTable\SubTableData; | |||||
| use App\Util\DateUtil; | use App\Util\DateUtil; | ||||
| use Illuminate\Http\UploadedFile; | |||||
| use Illuminate\Support\Arr; | use Illuminate\Support\Arr; | ||||
| use Illuminate\Support\Carbon; | use Illuminate\Support\Carbon; | ||||
| use Illuminate\Support\Collection; | |||||
| use Illuminate\Support\Str; | use Illuminate\Support\Str; | ||||
| use LogicException; | use LogicException; | ||||
| use stdClass; | use stdClass; | ||||
| @@ -89,6 +92,13 @@ abstract class KintoneModel | |||||
| { | { | ||||
| return static::getAccess()->find($recordId); | return static::getAccess()->find($recordId); | ||||
| } | } | ||||
| /** | |||||
| * @return static | |||||
| */ | |||||
| public static function first(?KintoneRecordQuery $query = null) | |||||
| { | |||||
| return static::getAccess()->first($query); | |||||
| } | |||||
| public static function getDropDownOptions(string $fieldCode): array | public static function getDropDownOptions(string $fieldCode): array | ||||
| { | { | ||||
| @@ -112,8 +122,12 @@ abstract class KintoneModel | |||||
| protected ?stdClass $dataOrigin = null; | protected ?stdClass $dataOrigin = null; | ||||
| protected stdClass $data; | protected stdClass $data; | ||||
| const FIELD_RECORD_NO = "レコード番号"; | |||||
| protected const FIELDS = []; | protected const FIELDS = []; | ||||
| protected const SUB_TABLES = []; | |||||
| protected const FIELD_NAMES = []; | protected const FIELD_NAMES = []; | ||||
| protected const RELATIONS = []; | protected const RELATIONS = []; | ||||
| @@ -148,36 +162,15 @@ abstract class KintoneModel | |||||
| public function set(string $fieldCode, $value) | public function set(string $fieldCode, $value) | ||||
| { | { | ||||
| $field = Arr::get(static::FIELDS, $fieldCode); | |||||
| if ($field instanceof FieldType) { | |||||
| $this->setData($fieldCode, $field, $value); | |||||
| } else if (is_array($field)) { | |||||
| $this->setTable($fieldCode, $value); | |||||
| $type = $this->getFieldType($fieldCode); | |||||
| if ($type) { | |||||
| $this->setData($fieldCode, $value); | |||||
| data_set($this->changed, $fieldCode, true); | |||||
| } | } | ||||
| data_set($this->changed, $fieldCode, true); | |||||
| return $this; | return $this; | ||||
| } | } | ||||
| private function setTable(string $fieldCode, array $table) | |||||
| { | |||||
| foreach ($table as $index => $row) { | |||||
| $row = data_get($row, "value"); | |||||
| $this->setTableRow($fieldCode, $index, $row); | |||||
| } | |||||
| } | |||||
| private function setTableRow(string $fieldCode, int $index, array $row) | |||||
| { | |||||
| foreach ($row as $columnFieldCode => $column) { | |||||
| $value = $column["value"]; | |||||
| $type = static::FIELDS[$fieldCode][$columnFieldCode]; | |||||
| $insertKey = sprintf("%s.%d.%s", $fieldCode, $index, $columnFieldCode); | |||||
| $this->setData($insertKey, $type, $value); | |||||
| } | |||||
| } | |||||
| private function setData(string $path, FieldType $type, $value) | |||||
| private function setData(string $path, $value) | |||||
| { | { | ||||
| data_set($this->data, $path, $value); | data_set($this->data, $path, $value); | ||||
| @@ -207,43 +200,73 @@ abstract class KintoneModel | |||||
| continue; | continue; | ||||
| } | } | ||||
| $type = FieldType::tryFrom($type); | |||||
| if ($type === null) continue; | |||||
| data_set($this->data, $fieldCode, $this->readData($ele, $fieldCode)); | |||||
| } | |||||
| if ($this->recordId === null) { | |||||
| throw new LogicException(sprintf("レコード番号取得失敗 :%s", static::class)); | |||||
| } | |||||
| $ret = $this->setDataCustom($data); | |||||
| if ($ret) { | |||||
| $this->clean(); | |||||
| } | |||||
| return $ret; | |||||
| } | |||||
| private function readData(array $data, string $fieldCode = "") | |||||
| { | |||||
| $type = data_get($data, "type"); | |||||
| $value = data_get($data, "value"); | |||||
| if ($type === null || $value === null) { | |||||
| return null; | |||||
| } | |||||
| $type = FieldType::tryFrom($type); | |||||
| if ($type !== null) { | |||||
| if (in_array($type, [FieldType::DATETIME, FieldType::DATE])) { | if (in_array($type, [FieldType::DATETIME, FieldType::DATE])) { | ||||
| if ($value) { | if ($value) { | ||||
| data_set($this->data, $fieldCode, DateUtil::parse($value)); | |||||
| return DateUtil::parse($value); | |||||
| } else { | } else { | ||||
| data_set($this->data, $fieldCode, null); | |||||
| return null; | |||||
| } | } | ||||
| continue; | |||||
| } | |||||
| if ($type === FieldType::NUMBER) { | |||||
| return intval($value); | |||||
| } | } | ||||
| if ($type === FieldType::FILE) { | if ($type === FieldType::FILE) { | ||||
| $ret = []; | $ret = []; | ||||
| foreach ($value as $f) { | foreach ($value as $f) { | ||||
| $ret[] = new File($f); | $ret[] = new File($f); | ||||
| } | } | ||||
| data_set($this->data, $fieldCode, $ret); | |||||
| continue; | |||||
| return $ret; | |||||
| } | } | ||||
| if ($type === FieldType::SUBTABLE) { | |||||
| continue; | |||||
| if ($type === FieldType::SUBTABLE && $this->getFieldType($fieldCode)) { | |||||
| $ret = collect(); | |||||
| foreach ($value as $v) { | |||||
| $rowRet = | |||||
| $rowArray = data_get($v, 'value'); | |||||
| foreach ($rowArray as $subFieldCode => $ele) { | |||||
| $rowRet[$subFieldCode] = $this->readData($ele); | |||||
| } | |||||
| $ret->push($this->getSubTableData($fieldCode, $rowRet)); | |||||
| } | |||||
| return $ret; | |||||
| } | } | ||||
| // 以外はそのまま格納 | |||||
| data_set($this->data, $fieldCode, $value); | |||||
| return $value; | |||||
| } | } | ||||
| if ($this->recordId === null) { | |||||
| throw new LogicException(sprintf("レコード番号取得失敗 :%s", static::class)); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| $ret = $this->setDataCustom($data); | |||||
| if ($ret) { | |||||
| $this->clean(); | |||||
| private function getSubTableData(string $fieldCode, array $data): SubTableData | |||||
| { | |||||
| $className = data_get(static::SUB_TABLES, $fieldCode, ""); | |||||
| if (class_exists($className)) { | |||||
| return new $className($data); | |||||
| } | } | ||||
| return $ret; | |||||
| throw new LogicException("キントーン設定不備"); | |||||
| } | } | ||||
| @@ -273,28 +296,54 @@ abstract class KintoneModel | |||||
| } | } | ||||
| $path = sprintf("%s.value", $fieldCode); | $path = sprintf("%s.value", $fieldCode); | ||||
| if ($type === FieldType::DATETIME) { | |||||
| $data = $this->getDate($fieldCode); | |||||
| if ($data) { | |||||
| data_set($ret, $path, $data->toIso8601ZuluString()); | |||||
| } else { | |||||
| data_set($ret, $path, ""); | |||||
| } | |||||
| continue; | |||||
| data_set($ret, $path, $this->getApiLayoutValue($fieldCode)); | |||||
| } | |||||
| return array_merge($ret, $this->getApiLayoutCustom()); | |||||
| } | |||||
| private function getApiLayoutValue(string $fieldCode) | |||||
| { | |||||
| $ret = []; | |||||
| $data = $this->get($fieldCode); | |||||
| $type = $this->getFieldType($fieldCode); | |||||
| if ($type === FieldType::DATETIME) { | |||||
| $data = $this->getDate($fieldCode); | |||||
| if ($data) { | |||||
| return $data->toIso8601ZuluString(); | |||||
| } else { | |||||
| return ""; | |||||
| } | } | ||||
| if ($type === FieldType::DATE) { | |||||
| $data = $this->getDate($fieldCode); | |||||
| if ($data) { | |||||
| data_set($ret, $path, $data->toDateString()); | |||||
| } else { | |||||
| data_set($ret, $path, ""); | |||||
| } | |||||
| if ($type === FieldType::DATE) { | |||||
| $data = $this->getDate($fieldCode); | |||||
| if ($data) { | |||||
| return $data->toDateString(); | |||||
| } else { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| if ($data instanceof Collection) { | |||||
| $ret = []; | |||||
| foreach ($data as $ele) { | |||||
| if ($ele instanceof SubTableData) { | |||||
| $obj = []; | |||||
| $obj['value'] = $ele->toArray(); | |||||
| $ret[] = $obj; | |||||
| } | } | ||||
| continue; | |||||
| } | } | ||||
| data_set($ret, $path, data_get($this->data, $fieldCode)); | |||||
| return $ret; | |||||
| } | } | ||||
| return data_get($this->data, $fieldCode); | |||||
| } | |||||
| return array_merge($ret, $this->getApiLayoutCustom()); | |||||
| private function getFieldType(string $fieldCode): ?FieldType | |||||
| { | |||||
| return data_get(static::FIELDS, $fieldCode); | |||||
| } | } | ||||
| public function get(string $key) | public function get(string $key) | ||||
| @@ -346,6 +395,46 @@ abstract class KintoneModel | |||||
| return $this->createdAt; | return $this->createdAt; | ||||
| } | } | ||||
| /** | |||||
| * @param string $fieldCode | |||||
| * @param Collection<int, UploadedFile|TmpFile> $files | |||||
| * @param bool $override | |||||
| * @return static | |||||
| */ | |||||
| public function setFiles(string $fieldCode, Collection $files, bool $override = true): static | |||||
| { | |||||
| if ($override) { | |||||
| $this->set($fieldCode, []); | |||||
| } | |||||
| foreach ($files as $file) { | |||||
| $this->addFile($fieldCode, $file); | |||||
| } | |||||
| return $this; | |||||
| } | |||||
| public function addFile(string $fieldCode, UploadedFile|TmpFile $file) | |||||
| { | |||||
| if ($file instanceof UploadedFile) { | |||||
| $name = sprintf("image_%d.%s", Str::uuid(), $file->extension()); | |||||
| $contentType = $file->getClientMimeType(); | |||||
| } else { | |||||
| $name = $file->getAppFileName(); | |||||
| $contentType = $file->getMimeType(); | |||||
| } | |||||
| $access = $this->getAccess(); | |||||
| $field = $this->get($fieldCode); | |||||
| array_push($field, [ | |||||
| 'fileKey' => $access->filePut($file), | |||||
| 'name' => $name, | |||||
| 'contentType' => $contentType, | |||||
| ]); | |||||
| $this->set($fieldCode, $field); | |||||
| return $this; | |||||
| } | |||||
| public function save() | public function save() | ||||
| { | { | ||||
| $access = static::getAccess(); | $access = static::getAccess(); | ||||
| @@ -0,0 +1,51 @@ | |||||
| <?php | |||||
| namespace App\Kintone\Models; | |||||
| use App\Kintone\Models\SubTable\SeasonTicketContractReserve\TargetRoom; | |||||
| use Illuminate\Support\Collection; | |||||
| /** | |||||
| * アプリ名 領収証 | |||||
| * @property string receiptNo | |||||
| * @property int customerCode | |||||
| * @property string customerName | |||||
| * @property string parkingName | |||||
| * @property string receiptCustomerName | |||||
| * @property string receiptPurpose | |||||
| * @property int receiptTotalAmount | |||||
| */ | |||||
| class Receipt extends KintoneModel | |||||
| { | |||||
| const CONFIG_KEY = "KINTONE_APP_RECEIPT"; | |||||
| const FIELD_RECEIPT_NO = "領収証番号"; | |||||
| const FIELD_CUSTOMER_CODE = "顧客コード"; | |||||
| const FIELD_CUSTOMER_NAME = "顧客名"; | |||||
| const FIELD_RECEIPT_CUSTOMER_NAME = "宛名"; | |||||
| const FIELD_RECEIPT_PURPOSE = "但し書き"; | |||||
| const FIELD_RECEIPT_TOTAL_AMOUNT = "合計"; | |||||
| const FIELD_RECEIPT_PDF_FILE = "領収証PDF"; | |||||
| protected const FIELDS = [ | |||||
| ...parent::FIELDS, | |||||
| self::FIELD_RECEIPT_NO => FieldType::SINGLE_LINE_TEXT, | |||||
| self::FIELD_CUSTOMER_CODE => FieldType::NUMBER, | |||||
| self::FIELD_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT, | |||||
| self::FIELD_RECEIPT_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT, | |||||
| self::FIELD_RECEIPT_PURPOSE => FieldType::SINGLE_LINE_TEXT, | |||||
| self::FIELD_RECEIPT_TOTAL_AMOUNT => FieldType::NUMBER, | |||||
| self::FIELD_RECEIPT_PDF_FILE => FieldType::FILE, | |||||
| ]; | |||||
| protected const FIELD_NAMES = [ | |||||
| ...parent::FIELD_NAMES, | |||||
| ]; | |||||
| protected const RELATIONS = [ | |||||
| Customer::class, | |||||
| PaymentPlan::class, | |||||
| ]; | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| <?php | |||||
| namespace App\Kintone\Models\SubTable; | |||||
| abstract class SubTableData | |||||
| { | |||||
| public function __construct(protected array $data) | |||||
| { | |||||
| } | |||||
| abstract public function toArray(): array; | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| <?php | |||||
| namespace App\Logic; | |||||
| use App\Files\PDF\Receipt as ReceiptReceipt; | |||||
| use App\Kintone\Models\Receipt; | |||||
| use PDF; | |||||
| class ReceiptManager | |||||
| { | |||||
| private ?Receipt $receipt = null; | |||||
| public function __construct(?int $recordNo = null) | |||||
| { | |||||
| if ($recordNo) { | |||||
| $this->load($recordNo); | |||||
| } else { | |||||
| $this->receipt = new Receipt(); | |||||
| } | |||||
| } | |||||
| private function load(int $recordNo) | |||||
| { | |||||
| $this->receipt = Receipt::find($recordNo); | |||||
| } | |||||
| public function getReceipt(): Receipt | |||||
| { | |||||
| return $this->receipt; | |||||
| } | |||||
| 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, | |||||
| ]; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| <!DOCTYPE html> | |||||
| <html lang="ja"> | |||||
| <head> | |||||
| <meta charset="utf-8"> | |||||
| <title>領収証</title> | |||||
| <link rel="stylesheet" href="{{ resource_path('views/pdf/receipt.css') }}"> | |||||
| </head> | |||||
| <body> | |||||
| <div id="title"> | |||||
| 領収証 | |||||
| </div> | |||||
| <div id="receiptCustomerName" class="receiptCustomerName">{{ $receiptCustomerName }}様</div> | |||||
| <div id="receiptDate" class="receiptCustomerName">領収日 {{ $receiptDate }}</div> | |||||
| <div id="receiptTotalAmount">金額{{ $receiptTotalAmount }}(税込)</div> | |||||
| <div id="taxTotalAmount">税率10% ¥{{ $taxTotalAmount }}</div> | |||||
| <div id="receiptPurpose"> | |||||
| <p> | |||||
| 但し {{ $receiptPurpose }} として | |||||
| </p> | |||||
| <p> | |||||
| 上記正に領収いたしました | |||||
| </p> | |||||
| </div> | |||||
| <div id="company"> | |||||
| <p class="name">一般財団法人 京都市都市整備公社</p> | |||||
| <p class="zipCode">〒600-8421</p> | |||||
| <p class="address1">京都市下京区小道通烏丸西入童侍者町167番</p> | |||||
| <p class="invoiceNo">登録番号 T7 1300 0501 2806</p> | |||||
| </div> | |||||
| </body> | |||||
| </html> | |||||
| @@ -0,0 +1,67 @@ | |||||
| body { | |||||
| position: relative; | |||||
| font-size: 5mm | |||||
| } | |||||
| body div { | |||||
| position: absolute; | |||||
| } | |||||
| #title { | |||||
| top : 10mm; | |||||
| left: 100mm; | |||||
| font-size: 10mm; | |||||
| font-weight: bold; | |||||
| letter-spacing: 10mm; | |||||
| } | |||||
| .receiptCustomerName { | |||||
| top : 30mm; | |||||
| } | |||||
| #receiptCustomerName { | |||||
| left: 100mm; | |||||
| } | |||||
| #receiptDate { | |||||
| left: 150mm; | |||||
| } | |||||
| #receiptTotalAmount { | |||||
| border-top: solid 1px; | |||||
| border-bottom: solid 1px; | |||||
| padding-top: 2mm;; | |||||
| padding-bottom: 2mm; | |||||
| top: 50mm; | |||||
| left: 20mm; | |||||
| width: 170mm; | |||||
| } | |||||
| #taxTotalAmount { | |||||
| border-bottom: solid 1px; | |||||
| padding-bottom: 2mm; | |||||
| top: 65mm; | |||||
| left: 140mm; | |||||
| width: 50mm; | |||||
| } | |||||
| #receiptPurpose { | |||||
| top: 70mm; | |||||
| left: 20mm; | |||||
| } | |||||
| #company { | |||||
| top: 130mm; | |||||
| left: 150mm; | |||||
| font-size: 4mm; | |||||
| } | |||||
| #company p { | |||||
| margin: 1mm; | |||||
| } | |||||
| #company .name { | |||||
| font-size: 5mm; | |||||
| } | |||||