diff --git a/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderController.php b/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderController.php index f4d3dcf..b409f1e 100644 --- a/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderController.php +++ b/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderController.php @@ -3,6 +3,12 @@ namespace App\Http\Controllers\Web\SeasonTicketContract; use App\Http\Controllers\Web\WebController; +use App\Kintone\Models\Customer; +use App\Kintone\Models\Parking; +use App\Kintone\Models\SeasonTicketContract; +use App\Kintone\Models\SeasonTicketReOrderApplication; +use App\Kintone\Models\StickerReOrderApplication; +use App\Logic\GeneralApplicationManager; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -28,6 +34,25 @@ class StickerReOrderController extends WebController protected function run(Request $request): JsonResponse { + $param = $this->param; + + $parking = Parking::findByParkingName($param->parkingName); + $customer = Customer::getSelf(); + $seasonTicketContract = SeasonTicketContract::find($param->seasonTicketContractRecordNo); + + $application = new StickerReOrderApplication(); + $manager = new GeneralApplicationManager($application); + $manager + ->setCustomer($customer) + ->setSeasonTicketContract($seasonTicketContract) + ->setParking($parking) + ->makeApplication(); + + $application->reason = $param->reason; + $application->memo = $param->memo; + + $application->save(); + return $this->successResponse(); } } diff --git a/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderParams.php b/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderParams.php index e2e5189..bd69831 100644 --- a/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderParams.php +++ b/app/Http/Controllers/Web/SeasonTicketContract/StickerReOrderParams.php @@ -3,10 +3,12 @@ namespace App\Http\Controllers\Web\SeasonTicketContract; use App\Http\Controllers\Web\BaseParam; -use App\Kintone\Models\GeneralApplication; /** * @property string $seasonTicketContractRecordNo + * @property string $parkingName + * @property string $reason + * @property string $memo */ class StickerReOrderParams extends BaseParam { @@ -14,6 +16,9 @@ class StickerReOrderParams extends BaseParam { return [ 'season_ticket_contract_record_no' => $this->str(), + 'parking_name' => $this->str(), + 'reason' => $this->str(), + 'memo' => $this->str(true), ]; } } diff --git a/app/Kintone/KintoneAccessStore.php b/app/Kintone/KintoneAccessStore.php new file mode 100644 index 0000000..f570af1 --- /dev/null +++ b/app/Kintone/KintoneAccessStore.php @@ -0,0 +1,30 @@ +store[$modelName] = $access; + } + public function has(string $modelName): bool + { + return data_get($this->store, $modelName) !== null; + } + public function get(string $modelName): KintoneAccess + { + $accesss = data_get($this->store, $modelName); + if ($accesss === null) { + throw new LogicException(sprintf("KintoneAccessStore 未登録 %s", $modelName)); + } + return $accesss; + } +} diff --git a/app/Kintone/Models/Customer.php b/app/Kintone/Models/Customer.php index d9c635c..26af5a0 100644 --- a/app/Kintone/Models/Customer.php +++ b/app/Kintone/Models/Customer.php @@ -6,6 +6,11 @@ use Illuminate\Support\Facades\Auth; /** * アプリ名 顧客マスタ + * @property string $customerCode + * @property string $customerName + * @property string $customerNameKana + * @property string $email + * @property string $phone_number */ class Customer extends KintoneModel { diff --git a/app/Kintone/Models/GeneralApplication.php b/app/Kintone/Models/GeneralApplication.php index 50da49e..f536ba9 100644 --- a/app/Kintone/Models/GeneralApplication.php +++ b/app/Kintone/Models/GeneralApplication.php @@ -2,43 +2,52 @@ namespace App\Kintone\Models; +use App\Kintone\KintoneAccess; +use Illuminate\Support\Carbon; + /** * アプリ名 各種申請 + * @property string $applicationType + * @property Carbon $applicationDatetime + * @property string $status + * @property string $applicationNo + * @property string $customerCode + * @property string seasonTicketContractRecordNo + * @property string parkingName */ -class GeneralApplication extends KintoneModel +abstract class GeneralApplication extends KintoneModel { const CONFIG_KEY = "KINTONE_APP_GENERAL_APPLICATION"; - const FIELD_APPLICATION_TYPE = "申込内容"; - const FIELD_APPLICATIONJ_STATUS = "status"; - const FIELD_SEASON_TICKET_CONTRACT_RECORD_NO = "契約番号"; - const FIELD_CUSTOMER_NAME = "氏名"; - const FIELD_CUSTOMER_NAME_KANA = "フリガナ"; - const FIELD_CUSTOMER_EMAIL = "メールアドレス"; - const FIELD_CUSTOMER_PHONE_NUMBER = "電話番号"; - const FIELD_TERMINATE_DATE = "解約希望日"; - const FIELD_VEHICLE_NO = "変更後車両番号"; - const FIELD_REGISTER_NO = "変更後防犯登録番号"; - const FIELD_MEMO = "備考"; - const FIELD_APPLICATION_DATETIME = "受付日時"; + const BASE_MODEL = GeneralApplication::class; + + const FIELD_APPLICATION_TYPE = "申請種別"; + const FIELD_APPLICATION_DATETIME = "申請日時"; + + const FIELD_STATUS = "状況"; + const FIELD_APPLICATION_NO = "申請番号"; + const FIELD_CUSTOMER_CODE = "顧客コード"; + const FIELD_SEASON_TICKET_CONTRACT_RECORD_NO = "契約情報"; + const FIELD_PARKING_NAME = "駐車場名"; protected const FIELDS = [ ...parent::FIELDS, self::FIELD_APPLICATION_TYPE => FieldType::DROP_DOWN, - self::FIELD_APPLICATIONJ_STATUS => FieldType::DROP_DOWN, - self::FIELD_SEASON_TICKET_CONTRACT_RECORD_NO => FieldType::SINGLE_LINE_TEXT, - self::FIELD_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT, - self::FIELD_CUSTOMER_NAME_KANA => FieldType::SINGLE_LINE_TEXT, - self::FIELD_CUSTOMER_EMAIL => FieldType::SINGLE_LINE_TEXT, - self::FIELD_CUSTOMER_PHONE_NUMBER => FieldType::SINGLE_LINE_TEXT, - self::FIELD_TERMINATE_DATE => FieldType::DATE, - self::FIELD_VEHICLE_NO => FieldType::SINGLE_LINE_TEXT, - self::FIELD_REGISTER_NO => FieldType::SINGLE_LINE_TEXT, - self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, self::FIELD_APPLICATION_DATETIME => FieldType::DATETIME, + self::FIELD_STATUS => FieldType::DROP_DOWN, + self::FIELD_APPLICATION_NO => FieldType::SINGLE_LINE_TEXT, + self::FIELD_CUSTOMER_CODE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_SEASON_TICKET_CONTRACT_RECORD_NO => FieldType::SINGLE_LINE_TEXT, + self::FIELD_PARKING_NAME => FieldType::SINGLE_LINE_TEXT, ]; protected const FIELD_NAMES = [ ...parent::FIELD_NAMES, ]; + + protected const RELATIONS = [ + SeasonTicketContract::class, + Parking::class, + Customer::class, + ]; } diff --git a/app/Kintone/Models/KintoneModel.php b/app/Kintone/Models/KintoneModel.php index e7a3bc6..7d312c1 100644 --- a/app/Kintone/Models/KintoneModel.php +++ b/app/Kintone/Models/KintoneModel.php @@ -6,10 +6,12 @@ use App\Exceptions\AppCommonException; use App\Exceptions\ConfigException; use App\Kintone\File; use App\Kintone\KintoneAccess; +use App\Kintone\KintoneAccessStore; use App\Kintone\KintoneRecordQuery; use App\Util\DateUtil; use Illuminate\Support\Arr; use Illuminate\Support\Carbon; +use Illuminate\Support\Str; use LogicException; use stdClass; @@ -17,6 +19,8 @@ abstract class KintoneModel { const CONFIG_KEY = ""; + const BASE_MODEL = null; + static public function configKey(): string { if (!static::CONFIG_KEY) { @@ -51,8 +55,21 @@ abstract class KintoneModel */ static public function getAccess(): KintoneAccess { - $access = new KintoneAccess(static::class); + $target = static::BASE_MODEL ?? static::class; + + $store = KintoneAccessStore::instance(); + if ($store->has($target)) { + return $store->get($target); + } + + $access = new KintoneAccess($target); $access->setFields(array_keys(static::FIELDS)); + + foreach (static::RELATIONS as $relation) { + $access->addAppToken($relation); + } + + $store->set($target, $access); return $access; } @@ -61,8 +78,26 @@ abstract class KintoneModel */ static public function getQuery(): KintoneRecordQuery { - return new KintoneRecordQuery(static::class); + $target = static::BASE_MODEL ?? static::class; + return new KintoneRecordQuery($target); + } + + public static function find(string $recordId) + { + return static::getAccess()->find($recordId); + } + + public static function getDropDownOptions(string $fieldCode): array + { + $ret = []; + $properties = static::getAccess()->getAppFormFields(); + $options = Arr::get($properties, sprintf("%s.options", $fieldCode)); + $ret = Arr::pluck(Arr::sort($options, function ($option) { + return data_get($option, "index"); + }), "label"); + return $ret; } + protected ?string $recordId = null; protected ?int $revision = null; @@ -78,6 +113,8 @@ abstract class KintoneModel protected const FIELD_NAMES = []; + protected const RELATIONS = []; + private array $changed = []; public function __construct() @@ -85,6 +122,27 @@ abstract class KintoneModel $this->data = new stdClass(); } + public function __get($name) + { + $field = "FIELD_" . Str::of($name)->snake()->upper()->toString(); + $constantPath = sprintf("%s::%s", static::class, $field); + if (defined($constantPath)) { + return $this->get(constant($constantPath)); + } else { + throw new LogicException(sprintf("未定義のメンバアクセス %s %s", static::class, $field)); + } + } + public function __set($name, $value) + { + $field = "FIELD_" . Str::of($name)->snake()->upper()->toString(); + $constantPath = sprintf("%s::%s", static::class, $field); + if (defined($constantPath)) { + return $this->set(constant($constantPath), $value); + } else { + throw new LogicException(sprintf("未定義のメンバアクセス %s %s", static::class, $field)); + } + } + public function set(string $fieldCode, $value) { $field = Arr::get(static::FIELDS, $fieldCode); @@ -197,21 +255,7 @@ abstract class KintoneModel return $ret; } - public static function getDropDownOptions(string $fieldCode): array - { - $ret = []; - $properties = static::getAccess()->getAppFormFields(); - $options = Arr::get($properties, sprintf("%s.options", $fieldCode)); - $ret = Arr::pluck(Arr::sort($options, function ($option) { - return data_get($option, "index"); - }), "label"); - // foreach ($options as $option) { - // $index = data_get($option, "index"); - // $label = data_get($option, "label"); - // $ret[$index] = $label; - // } - return $ret; - } + /** * 変更前データを現在データで上書きする @@ -308,6 +352,16 @@ abstract class KintoneModel return $this->createdAt; } + public function save() + { + $access = static::getAccess(); + if ($this->recordId === null) { + $access->create($this); + } else { + $access->update($this); + } + } + public function toArray($column = ['*']): array { if ($this->recordId === null) { diff --git a/app/Kintone/Models/Paking.php b/app/Kintone/Models/Parking.php similarity index 63% rename from app/Kintone/Models/Paking.php rename to app/Kintone/Models/Parking.php index 03fc016..5e1a609 100644 --- a/app/Kintone/Models/Paking.php +++ b/app/Kintone/Models/Parking.php @@ -4,8 +4,9 @@ namespace App\Kintone\Models; /** * アプリ名 駐車場マスタ + * @property string $parkingName */ -class Paking extends KintoneModel +class Parking extends KintoneModel { const CONFIG_KEY = "KINTONE_APP_PARKING"; @@ -20,4 +21,9 @@ class Paking extends KintoneModel ...parent::FIELD_NAMES, self::FIELD_PARKING_NAME => 'parking_name', ]; + + static function findByParkingName(string $parkingName) + { + return static::getAccess()->first(static::getQuery()->where(static::FIELD_PARKING_NAME, $parkingName)); + } } diff --git a/app/Kintone/Models/ParkingCertificateApplication.php b/app/Kintone/Models/ParkingCertificateApplication.php new file mode 100644 index 0000000..ef8c9e9 --- /dev/null +++ b/app/Kintone/Models/ParkingCertificateApplication.php @@ -0,0 +1,32 @@ + FieldType::DROP_DOWN, + self::FIELD_VEHICLE_NO => FieldType::SINGLE_LINE_TEXT, + self::FIELD_CHASSIS_NO => FieldType::SINGLE_LINE_TEXT, + self::FIELD_MAIL_NAME => FieldType::SINGLE_LINE_TEXT, + self::FIELD_MAIL_ZIP_CODE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_MAIL_ADDRESS => FieldType::SINGLE_LINE_TEXT, + self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, + ]; + + protected const FIELD_NAMES = [ + ...parent::FIELD_NAMES, + ]; +} diff --git a/app/Kintone/Models/SeasonTicketContract.php b/app/Kintone/Models/SeasonTicketContract.php index 43ee421..9e52d42 100644 --- a/app/Kintone/Models/SeasonTicketContract.php +++ b/app/Kintone/Models/SeasonTicketContract.php @@ -6,6 +6,7 @@ use LogicException; /** * アプリ名 車室情報管理 + * @property string seasonTicketSeqNo */ class SeasonTicketContract extends KintoneModel { diff --git a/app/Kintone/Models/SeasonTicketReOrderApplication.php b/app/Kintone/Models/SeasonTicketReOrderApplication.php new file mode 100644 index 0000000..96e1058 --- /dev/null +++ b/app/Kintone/Models/SeasonTicketReOrderApplication.php @@ -0,0 +1,24 @@ + FieldType::MULTI_LINE_TEXT, + self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, + ]; + + protected const FIELD_NAMES = [ + ...parent::FIELD_NAMES, + ]; +} diff --git a/app/Kintone/Models/StickerReOrderApplication.php b/app/Kintone/Models/StickerReOrderApplication.php new file mode 100644 index 0000000..8efe74d --- /dev/null +++ b/app/Kintone/Models/StickerReOrderApplication.php @@ -0,0 +1,22 @@ + FieldType::MULTI_LINE_TEXT, + self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, + ]; + + protected const FIELD_NAMES = [ + ...parent::FIELD_NAMES, + ]; +} diff --git a/app/Kintone/Models/TerminateApplication.php b/app/Kintone/Models/TerminateApplication.php new file mode 100644 index 0000000..f91b5aa --- /dev/null +++ b/app/Kintone/Models/TerminateApplication.php @@ -0,0 +1,28 @@ + FieldType::DATETIME, + self::FIELD_REASON => FieldType::CHECK_BOX, + self::FIELD_REASON_DETAIL => FieldType::MULTI_LINE_TEXT, + self::FIELD_OPINION => FieldType::MULTI_LINE_TEXT, + self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, + ]; + + protected const FIELD_NAMES = [ + ...parent::FIELD_NAMES, + ]; +} diff --git a/app/Kintone/Models/UserInfoUpdateApplication.php b/app/Kintone/Models/UserInfoUpdateApplication.php new file mode 100644 index 0000000..697b890 --- /dev/null +++ b/app/Kintone/Models/UserInfoUpdateApplication.php @@ -0,0 +1,36 @@ + FieldType::SINGLE_LINE_TEXT, + self::FIELD_NAME_BEFORE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_ZIP_CODE_BEFORE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_ZIP_CODE_AFTER => FieldType::SINGLE_LINE_TEXT, + self::FIELD_ADDRESS_BEFORE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_ADDRESS_AFTER => FieldType::SINGLE_LINE_TEXT, + self::FIELD_PHONE_NO_BEFORE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_PHONE_NO_AFTER => FieldType::SINGLE_LINE_TEXT, + self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, + ]; + + protected const FIELD_NAMES = [ + ...parent::FIELD_NAMES, + ]; +} diff --git a/app/Kintone/Models/VehicleInfoUpdateApplication.php b/app/Kintone/Models/VehicleInfoUpdateApplication.php new file mode 100644 index 0000000..33e824b --- /dev/null +++ b/app/Kintone/Models/VehicleInfoUpdateApplication.php @@ -0,0 +1,30 @@ + FieldType::DATE, + self::FIELD_VEHICLE_NO_BEFORE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_VEHICLE_NO_AFTER => FieldType::SINGLE_LINE_TEXT, + self::FIELD_REGISTER_NO_BEFORE => FieldType::SINGLE_LINE_TEXT, + self::FIELD_REGISTER_NO_AFTER => FieldType::SINGLE_LINE_TEXT, + self::FIELD_MEMO => FieldType::MULTI_LINE_TEXT, + ]; + + protected const FIELD_NAMES = [ + ...parent::FIELD_NAMES, + ]; +} diff --git a/app/Logic/GeneralApplicationManager.php b/app/Logic/GeneralApplicationManager.php index e0fba22..82267c1 100644 --- a/app/Logic/GeneralApplicationManager.php +++ b/app/Logic/GeneralApplicationManager.php @@ -2,80 +2,116 @@ namespace App\Logic; -use App\Features\InstanceAble; use App\Kintone\Models\Customer; use App\Kintone\Models\GeneralApplication; +use App\Kintone\Models\Parking; +use App\Kintone\Models\ParkingCertificateApplication; +use App\Kintone\Models\SeasonTicketContract; +use App\Kintone\Models\SeasonTicketReOrderApplication; +use App\Kintone\Models\StickerReOrderApplication; +use App\Kintone\Models\TerminateApplication; +use App\Kintone\Models\UserInfoUpdateApplication; +use App\Kintone\Models\VehicleInfoUpdateApplication; use App\Util\DateUtil; -use Illuminate\Support\Carbon; use LogicException; +/** + * @template T of GeneralApplication + */ class GeneralApplicationManager { + private ?Customer $customer = null; - use InstanceAble; + private ?SeasonTicketContract $seasonTicketContract = null; - private Customer|null $customer = null; + private ?Parking $parking = null; + + /** + * @param T $model + */ public function __construct(private GeneralApplication $model) { + if ($model instanceof TerminateApplication) { + $this->setType("解約申請"); + return; + } + if ($model instanceof ParkingCertificateApplication) { + $this->setType("車庫証明発行申請"); + return; + } + if ($model instanceof StickerReOrderApplication) { + $this->setType("シール再発行申請"); + return; + } + if ($model instanceof SeasonTicketReOrderApplication) { + $this->setType("定期券再発行申請"); + return; + } + if ($model instanceof VehicleInfoUpdateApplication) { + $this->setType("車両番号・防犯登録番号変更"); + return; + } + if ($model instanceof UserInfoUpdateApplication) { + $this->setType("利用者情報変更"); + return; + } + if ($model instanceof UserInfoUpdateApplication) { + $this->setType("振替頻度変更"); + return; + } } public function setCustomer(Customer $customer): static { - $this->customer = $customer; return $this; } - - public function forTerminate(array $attr): static + public function setSeasonTicketContract(SeasonTicketContract $seasonTicketContract): static { - $terminateDate = data_get($attr, GeneralApplication::FIELD_TERMINATE_DATE); - if (!($terminateDate instanceof Carbon)) throw new LogicException("解約予定日不正"); - $this->model->set(GeneralApplication::FIELD_TERMINATE_DATE, $terminateDate); - - return $this->setType("解約申請") - ->setMemo($attr); + $this->seasonTicketContract = $seasonTicketContract; + return $this; } - - public function forParkingCertificate(array $attr = []): static + public function setParking(Parking $parking): static { - return $this->setType("車庫証明発行申請") - ->setMemo($attr); + $this->parking = $parking; + return $this; } - public function register() + /** + * @return T + */ + public function makeApplication() { + $this->model->applicationDatetime = DateUtil::now(); + $this->model->status = "新規登録"; + $this->model->applicationNo = $this->getApplicationNo(); + if ($this->customer === null) { - throw new LogicException("顧客NULL"); + throw new LogicException("顧客未設定のため失敗"); } - if (!$this->model->getStr(GeneralApplication::FIELD_APPLICATION_TYPE)) { - throw new LogicException("申請タイプ未設定"); + $this->model->customerCode = $this->customer->customerCode; + + if ($this->seasonTicketContract !== null) { + $this->model->seasonTicketContractRecordNo = $this->seasonTicketContract->seasonTicketSeqNo; } - $this->model->set(GeneralApplication::FIELD_APPLICATION_DATETIME, DateUtil::now()); - $this->model->set(GeneralApplication::FIELD_APPLICATIONJ_STATUS, "申込"); - $this->model->set(GeneralApplication::FIELD_CUSTOMER_EMAIL, $this->customer->get(Customer::FIELD_EMAIL)); - $this->model->set(GeneralApplication::FIELD_CUSTOMER_NAME, $this->customer->get(Customer::FIELD_CUSTOMER_NAME)); - $this->model->set(GeneralApplication::FIELD_CUSTOMER_NAME_KANA, $this->customer->get(Customer::FIELD_CUSTOMER_NAME_KANA)); - $this->model->set(GeneralApplication::FIELD_CUSTOMER_PHONE_NUMBER, $this->customer->get(Customer::FIELD_PHONE_NUMBER)); + if ($this->parking !== null) { + $this->model->parkingName = $this->parking->parkingName; + } - $access = $this->model->getAccess(); - $access->create($this->model); + return $this->model; } private function setType(string $type): static { - $this->model->set(GeneralApplication::FIELD_APPLICATION_TYPE, $type); + $this->model->applicationType = $type; return $this; } - private function setMemo(array $attr): static + private function getApplicationNo(): string { - $memo = data_get($attr, GeneralApplication::FIELD_MEMO); - if ($memo) { - $this->model->set(GeneralApplication::FIELD_MEMO, $memo); - } - return $this; + return sprintf("%s-%06d", DateUtil::now()->format('Ymd'), rand(1, 999999)); } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 1f41fa1..e820d69 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -44,5 +44,8 @@ class AppServiceProvider extends ServiceProvider // DB関連 $this->app->singleton(\App\Util\DBUtil::class); + + // KINTONE関連 + $this->app->singleton(\App\Kintone\KintoneAccessStore::class); } }