ソースを参照

SMBCポーリング関連 対応

master
sosuke.iwabuchi 2年前
コミット
d99699ebda
25個のファイルの変更896行の追加2行の削除
  1. +1
    -0
      app/Codes/EnvironmentName.php
  2. +186
    -0
      app/Console/Commands/SMBCPoll.php
  3. +1
    -0
      app/Console/Kernel.php
  4. +17
    -0
      app/Console/Schedules/SMBCPoll.php
  5. +147
    -0
      app/Http/API/SMBC/PollResult.php
  6. +98
    -0
      app/Http/API/SMBC/PollResultRecord.php
  7. +100
    -0
      app/Http/API/SMBC/SMBC.php
  8. +11
    -0
      app/Http/API/SMBC/SMBCStatus.php
  9. +40
    -0
      app/Http/Controllers/Web/Customer/BankAccountRegisterStartController.php
  10. +15
    -0
      app/Http/Controllers/Web/Customer/BankAccountRegisterStartParam.php
  11. +8
    -1
      app/Http/Controllers/Web/WebController.php
  12. +1
    -1
      app/Kintone/KintoneRecordQuery.php
  13. +13
    -0
      app/Kintone/Models/Bank.php
  14. +93
    -0
      app/Kintone/Models/BankAccountUpdateApplication.php
  15. +3
    -0
      app/Kintone/Models/Customer.php
  16. +1
    -0
      app/Kintone/Models/GeneralApplication.php
  17. +9
    -0
      app/Logic/GeneralApplicationManager.php
  18. +22
    -0
      app/Models/SmbcPollStatus.php
  19. +16
    -0
      app/Util/EncodingUtil.php
  20. +1
    -0
      config/kintone.php
  21. +20
    -0
      config/smbc.php
  22. +30
    -0
      database/migrations/2023_10_06_182600_create_smbc_poll_statuses_table.php
  23. +1
    -0
      routes/api.php
  24. +21
    -0
      tests/Feature/Http/API/SMBC/SMBCTest.php
  25. +41
    -0
      tests/Feature/Kintone/BankAccountUpdateApplicationTest.php

+ 1
- 0
app/Codes/EnvironmentName.php ファイルの表示

@@ -4,6 +4,7 @@ namespace App\Codes;

enum EnvironmentName: string
{
case TEST = 'testing';
case LOCAL = 'local';
case STAGING = 'staging';
case PRODUCTOIN = 'production';


+ 186
- 0
app/Console/Commands/SMBCPoll.php ファイルの表示

@@ -0,0 +1,186 @@
<?php

namespace App\Console\Commands;

use App\Http\API\SMBC\PollResultRecord;
use App\Http\API\SMBC\SMBC;
use App\Http\API\SMBC\SMBCStatus;
use App\Kintone\Models\BankAccountUpdateApplication;
use App\Kintone\Models\Customer;
use App\Logic\GeneralApplicationManager;
use App\Models\SmbcPollStatus;
use App\Util\DateUtil;
use App\Util\DBUtil;
use Exception;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class SMBCPoll extends BaseCommand
{

const COMMAND = "smbc:poll";


/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = self::COMMAND;

/**
* The console command description.
*
* @var string
*/
protected $description = 'SMBCへ口座振替登録申請結果を取得する';

static public function getCommand()
{
return self::COMMAND;
}


/**
* @var Collection<int, BankAccountUpdateApplication>
*/
private Collection $applications;


/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->applications = collect();
}

/**
* Execute the console command.
*
* @return int
*/
public function service(): int
{
try {
$db = DBUtil::instance();
$db->beginTransaction();

// 検索範囲の取得
[$from, $to] = $this->getFromTo();
$this->outputInfo(sprintf("検索範囲 %s-%s", $from->format('Y/m/d H:i:s'), $to->format('Y/m/d H:i:s')));

// 検索実行
$result = SMBC::poll($from, $to);

// 検索結果の確認
if (!$result->ok()) {
$this->outputError($result->getMessage());
return self::RESULTCODE_FAILED;
}
$this->outputInfo(sprintf("取得対象 %d件", $result->getCount()));

// データハンドリング
foreach ($result->getRecord() as $data) {
$this->handleData($data);
}

// 検索実績の登録
$this->saveFromTo($from, $to);

// キントーンへ各種申請登録
foreach ($this->applications as $app) {
$this->outputInfo(sprintf("申請登録 顧客コード:%s 申請番号:%s", $app->customerCode, $app->applicationNo));
$app->save();
}
$this->outputInfo(sprintf("申請登録件数:%d件", $this->applications->count()));

$db->commit();
} catch (Exception $e) {
$db->rollBack();
throw $e;
}

return self::RESULTCODE_SUCCESS;
}

/**
* @return Carbon[]
*/
private function getFromTo()
{

$status = SmbcPollStatus::all()->first();
$now = DateUtil::now();
if ($status === null) {
$this->outputInfo("検索範囲初期化");
return [
$now->clone()->addDays(-5),
$now->clone(),
];
}

return [
$status->condition_datetime_to->clone()->addSecond(),
$now->clone(),
];
}

private function handleData(PollResultRecord $data)
{
if ($data->status === SMBCStatus::SUCCESS) {
$customer = Customer::findByCustomerCode($data->getCustomerCode());

$application = new BankAccountUpdateApplication();
$manager = new GeneralApplicationManager($application);
$manager
->setCustomer($customer)
->makeApplication();

$application->bankBranchIdBefore = $customer->bankBranchId;

$application->bankBranchIdAfter = $data->bankBranchCode;
$application->bankCodeAfter = $data->bankCode;
$application->bankNameAfter = $data->bankName;
$application->branchCodeAfter = $data->branchCode;
$application->branchNameAfter = $data->branchName;
$application->accountTypeAfter = $data->accountType;
$application->accountNameKanaAfter = $data->accountName;
$application->accountNoAfter = $data->accountNo;
$application->accountYuchoSignAfter = $data->yuchoSign;
$application->accountYuchoNoAfter = $data->yuchoAccountNo;
$application->smbcApplicationDatetime = $data->applicationDatetime;
$application->smbcAcceptNo = $data->acceptNo;
$application->smbcResult = $data->all;

$this->applications->push($application);
return;
}
if ($data->status === SMBCStatus::ERROR || $data->status === SMBCStatus::CANCEL) {
// TODOエラーメール送信

return;
}
if ($data->status === SMBCStatus::PROCESSING) {
$this->outputInfo(sprintf("処理中のためスキップ 受付番号%s", $data->acceptNo));
return;
}
if ($data->address5 !== SMBC::CONDITION_ADDR5_FROM_MY_PAGE) {
$this->outputInfo(sprintf("MyPage以外からの申請のためスキップ 受付番号%s", $data->acceptNo));
return;
}
}

private function saveFromTo(Carbon $from, Carbon $to)
{
DB::table(SmbcPollStatus::getTableName())->delete();

$status = new SmbcPollStatus();
$status->condition_datetime_to = $to;
$status->save();
}
}

+ 1
- 0
app/Console/Kernel.php ファイルの表示

@@ -13,6 +13,7 @@ class Kernel extends ConsoleKernel
protected function schedule(Schedule $schedule): void
{
Schedules\HeartBeat::register($schedule);
Schedules\SMBCPoll::register($schedule);
}

/**


+ 17
- 0
app/Console/Schedules/SMBCPoll.php ファイルの表示

@@ -0,0 +1,17 @@
<?php

namespace App\Console\Schedules;

use App\Console\Commands\SMBCPoll as CommandsSMBCPoll;
use Illuminate\Console\Scheduling\Schedule;

class SMBCPoll extends BaseSchedule
{

static public function register(Schedule $schedule)
{
$schedule->command(CommandsSMBCPoll::class)
->everyThreeMinutes()
->description("SMBC口座振替申請結果取得");
}
}

+ 147
- 0
app/Http/API/SMBC/PollResult.php ファイルの表示

@@ -0,0 +1,147 @@
<?php

namespace App\Http\API\SMBC;

use App\Codes\EnvironmentName;
use App\Util\EncodingUtil;
use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

class PollResult
{
// 共通
private const IDX_RECORD_CODE = 0;
// ヘッダー
private const IDX_HEADER_RESULT = 1;
private const IDX_HEADER_MESSAGE = 2;
// ボディー
private const IDX_FOOTER_COUNT = 1;
// フッター

private const RECORD_CODE_HEADER = "10";
private const RECORD_CODE_BODY = "20";
private const RECORD_CODE_FOOTER = "80";
private const RESULT_CODE_SUCCESS = ["000000", "943037"];


/**
* @var Collection<int, Collection<int, string>>
*/
private Collection $lines;

/**
* @var Collection<int, PollResultRecord>
*/
private Collection $body;

private bool $success = false;
private string $message = "";
private int $count = 0;

public function __construct(string $data)
{
$this->lines = collect();
$lines = Str::of($data)->replace('"', '')->explode("\r\n");
foreach ($lines as $lineStr) {
if ($lineStr) {
$lineStr = EncodingUtil::toUtf8FromSjis($lineStr);
$this->lines->push(Str::of($lineStr)->explode(','));
}
}

if (!$this->parseHeader()) {
return;
}
if (!$this->parseBody()) {
return;
}
if (!$this->parseFooter()) {
return;
}

$this->success = true;
}

public function ok(): bool
{
return $this->success;
}
public function getMessage(): string
{
return $this->message;
}

public function getRecord()
{
return $this->body;
}

public function getCount(): int
{
return $this->count;
}

private function parseHeader(): bool
{
$header = $this->lines->first();
if (!$header) {
$this->success = false;
$this->message = "ヘッダーなし";
return false;
}

$resultCode = $header->get(self::IDX_HEADER_RESULT);
if (!in_array($resultCode, self::RESULT_CODE_SUCCESS)) {
$this->success = false;
$this->message = sprintf("結果コードNG %s", $resultCode);
$readMessage = EncodingUtil::toUtf8FromSjis($header->get(self::IDX_HEADER_MESSAGE));
return false;
}
return true;
}

private function parseBody(): bool
{
$this->body = collect();

try {
foreach ($this->lines as $line) {
if ($line[self::IDX_RECORD_CODE] === self::RECORD_CODE_BODY) {
$this->body->push(new PollResultRecord($line));
}
}
} catch (Exception $e) {
$this->success = false;
$this->message = sprintf("Bodyパース失敗 %s", $e->getMessage());
return false;
}

return true;
}

private function parseFooter(): bool
{
$footer = $this->lines->last();

if (!$footer) {
$this->success = false;
$this->message = "フッターなし";
return false;
}

$count = intval($footer->get(self::IDX_FOOTER_COUNT));

if ($count !== $this->body->count()) {
$this->success = false;
$this->message = sprintf("読込件数に差異あり %d : %d", $count, $this->body->count());
return false;
}
$this->count = $count;

return true;
}
}

+ 98
- 0
app/Http/API/SMBC/PollResultRecord.php ファイルの表示

@@ -0,0 +1,98 @@
<?php

namespace App\Http\API\SMBC;

use App\Util\DateUtil;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class PollResultRecord
{
private const IDX_ACCEPT_NO = 11;
private const IDX_APPLICATION_DATE = 12;
private const IDX_APPLICATION_TIME = 13;
private const IDX_CUSTOMER_NO = 22;
private const IDX_ADDRESS5 = 33;
private const IDX_STATUS = 40;
private const IDX_BANK_CODE = 60;
private const IDX_BANK_NAME = 61;
private const IDX_BRANCH_CODE = 62;
private const IDX_BRANCH_NAME = 63;
private const IDX_ACCOUNT_TYPE = 64;
private const IDX_ACCOUNT_NO = 66;
private const IDX_ACCOUNT_NAME = 67;

private const BANK_CODE_YUCHO = "9900";

public string $acceptNo = ""; // 口座振替受付番号
public Carbon $applicationDatetime; // 申込日時
public string $customerNo = ""; // 顧客番号
public SMBCStatus $status;
public string $bankCode = ""; // 金融機関コード
public string $bankName = "";
public string $branchCode = ""; // 支店コード
public string $branchName = "";
public string $accountType = ""; // 預金種目
public string $accountNo = ""; // 口座番号
public string $accountName = ""; // 口座名義カナ

public string $yuchoSign = ""; // ゆうちょ口座記号
public string $yuchoAccountNo = ""; // ゆうちょ口座番号

public string $bankBranchCode = ""; // 銀行支店コード

public string $address5 = ""; // 住所5

public string $all = "";

/**
*
* @param Collection<int, string> $data
*/
public function __construct(Collection $data)
{
$this->acceptNo = $data[self::IDX_ACCEPT_NO];
$this->applicationDatetime = DateUtil::parse($data[self::IDX_APPLICATION_DATE] . $data[self::IDX_APPLICATION_TIME]);
$this->customerNo = $data[self::IDX_CUSTOMER_NO];
$this->address5 = $data[self::IDX_ADDRESS5];
$this->status = SMBCStatus::from($data[self::IDX_STATUS]);
$this->bankCode = $data[self::IDX_BANK_CODE];
$this->bankName = $data[self::IDX_BANK_NAME];
$this->branchCode = $data[self::IDX_BRANCH_CODE];
$this->branchName = $data[self::IDX_BRANCH_NAME];
$this->accountType = $data[self::IDX_ACCOUNT_TYPE];
$this->accountNo = $data[self::IDX_ACCOUNT_NO];
$this->accountName = $data[self::IDX_ACCOUNT_NAME];

// ゆうちょの場合、
// 支店コードに記号5桁のうちの3桁
// 口座番号に記号8桁のうちの7桁が入っているので
// 調整する
if ($this->bankCode === self::BANK_CODE_YUCHO) {

$branchCode = $this->branchCode;
$accountNo = $this->accountNo;
$this->branchCode = "";
$this->accountNo = "";

// 記号には前後に1,0を付与する
$this->yuchoSign = sprintf("1%s0", $branchCode);

// 口座番号には末尾に1を付与する
$this->yuchoAccountNo = sprintf("%s1", $accountNo);

// 支店コードは記号の前2桁に8を付与する
$this->branchCode = sprintf("%s8", Str::of($branchCode)->substr(2));
}

$this->bankBranchCode = sprintf("%d%s", intval($this->bankCode), $this->branchCode);

$this->all = $data->implode(",");
}

public function getCustomerCode(): int
{
return intval($this->customerNo);
}
}

+ 100
- 0
app/Http/API/SMBC/SMBC.php ファイルの表示

@@ -0,0 +1,100 @@
<?php

namespace App\Http\API\SMBC;

use App\Exceptions\ConfigException;
use App\Kintone\Models\Customer;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Http;

class SMBC
{
const CONDITION_ADDR5_FROM_MY_PAGE = "マイページからの申請";


public static function poll(Carbon $from, Carbon $to)
{
$url = config('smbc.searchUrl');
if (!$url) {
throw new ConfigException("smbc.searchUrl", $url);
}

$password = config('smbc.searchPassword');
if (!$password) {
throw new ConfigException("smbc.searchPassword", $password);
}

$sendData = [
'version' => "213",
'shori_kbn' => "2001",
'shop_cd' => "7694156",
'syuno_co_cd' => "58763",
'shop_pwd' => $password,

// 口座振替受付ステータス更新日時のFROM-TO検索条件
'kfr_utk_status_upd_date_from' => $from->format('Ymd'),
'kfr_utk_status_upd_time_from' => $from->format('His'),
'kfr_utk_status_upd_date_to' => $to->format('Ymd'),
'kfr_utk_status_upd_time_to' => $to->format('His'),

// ソート指定
'sort_list' => "11", // 口座振替受付ステータス更新日時
'sort_jun' => "2" // 降順
];

$res = Http::withHeaders([
'Content-Type' => 'application/x-www-form-urlencoded',
'Content-Encoding' => 'Shift_JIS'
])->asForm()->post(
$url,
$sendData
);

if ($res->failed()) {
throw $res->toException();
}

return new PollResult($res->body());
}

public static function getRegisterStartParam(Customer $customer)
{

$password = config('smbc.systemPassword');
if (!$password) {
throw new ConfigException('smbc.systemPassword', $password);
}

$url = config('smbc.registerUrl');
if (!$url) {
throw new ConfigException('smbc.registerUrl', $url);
}

$param = [
'bill_no' => sprintf("%012d", $customer->customerCode),
'bill_name' => $customer->customerName,
'bill_kana' => mb_convert_kana($customer->customerNameKana, "ks"),

'version' => "130",
'bill_method' => "01",
'shop_cd' => "7694156",
'syuno_co_cd' => "58763",
'shop_pwd' => $password,
'shoporder_no' => "",
'koushin_kbn' => "1",
'shop_phon_hyoji_kbn' => "1",
'shop_mail_hyoji_kbn' => "1",
'kessai_id' => "0101",

'bill_adr_5' => self::CONDITION_ADDR5_FROM_MY_PAGE,
];
$param['fs'] = hash('sha256', $param['shop_cd'] . $param['syuno_co_cd'] . $param['bill_no'] . $param['shoporder_no'] . $param['shop_pwd']);

$data = [
'url' => $url,
'param' => $param,
];

return $data;
}
}

+ 11
- 0
app/Http/API/SMBC/SMBCStatus.php ファイルの表示

@@ -0,0 +1,11 @@
<?php

namespace App\Http\API\SMBC;

enum SMBCStatus: string
{
case PROCESSING = "01";
case SUCCESS = "02";
case ERROR = "03";
case CANCEL = "04";
}

+ 40
- 0
app/Http/Controllers/Web/Customer/BankAccountRegisterStartController.php ファイルの表示

@@ -0,0 +1,40 @@
<?php

namespace App\Http\Controllers\Web\Customer;

use App\Exceptions\ConfigException;
use App\Http\API\SMBC\SMBC;
use App\Http\Controllers\Web\WebController;
use App\Kintone\Models\Customer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class BankAccountRegisterStartController extends WebController
{

public function name(): string
{
return "利用者口座変更申請開始";
}

public function description(): string
{
return "利用者口座変更申請開始用のパラメータを取得する";
}


public function __construct(protected BankAccountRegisterStartParam $param)
{
parent::__construct();
$this->middleware('auth:sanctum');
}

protected function run(Request $request): JsonResponse
{
$customer = Customer::getSelf();

$data = SMBC::getRegisterStartParam($customer);

return $this->successResponse($data);
}
}

+ 15
- 0
app/Http/Controllers/Web/Customer/BankAccountRegisterStartParam.php ファイルの表示

@@ -0,0 +1,15 @@
<?php

namespace App\Http\Controllers\Web\Customer;

use App\Http\Controllers\Web\BaseParam;

/**
*/
class BankAccountRegisterStartParam extends BaseParam
{
public function rules(): array
{
return [];
}
}

+ 8
- 1
app/Http/Controllers/Web/WebController.php ファイルの表示

@@ -2,6 +2,7 @@

namespace App\Http\Controllers\Web;

use App\Codes\EnvironmentName;
use App\Codes\HTTPResultCode as ResultCode;
use App\Codes\UserRole;
use App\Exceptions\AppCommonException;
@@ -301,7 +302,13 @@ abstract class WebController extends BaseController
->json($ret)
->withHeaders($this->makeHeader());
} else {
abort(500);

if (app()->environment([EnvironmentName::PRODUCTOIN->value])) {
abort(500);
}
return response()
->json($ret)
->withHeaders($this->makeHeader());
}
}



+ 1
- 1
app/Kintone/KintoneRecordQuery.php ファイルの表示

@@ -28,7 +28,7 @@ class KintoneRecordQuery
$ret .= " ";
}
$ret .= $this->order;
logger(sprintf("QUERY[%s]:%s", $this->appName, $ret));
// logger(sprintf("QUERY[%s]:%s", $this->appName, $ret));
return $ret;
}



+ 13
- 0
app/Kintone/Models/Bank.php ファイルの表示

@@ -0,0 +1,13 @@
<?php

namespace App\Kintone\Models;

use Illuminate\Support\Facades\Auth;

/**
* アプリ名 銀行マスタ
*/
class Bank extends KintoneModel
{
const CONFIG_KEY = "KINTONE_APP_BANK";
}

+ 93
- 0
app/Kintone/Models/BankAccountUpdateApplication.php ファイルの表示

@@ -0,0 +1,93 @@
<?php

namespace App\Kintone\Models;

use Illuminate\Support\Carbon;

/**
* アプリ名 各種申請 [口座変更申請]
*
* @property string bankBranchIdBefore
* @property string bankCodeBefore
* @property string bankNameBefore
* @property string branchCodeBefore
* @property string branchNameBefore
* @property int accountTypeBefore
* @property string accountNameKanaBefore
* @property int accountNoBefore
* @property int accountYuchoSignBefore
* @property int accountYuchoNoBefore
* @property string bankBranchIdAfter
* @property string bankCodeAfter
* @property string bankNameAfter
* @property string branchCodeAfter
* @property string branchNameAfter
* @property int accountTypeAfter
* @property string accountNameKanaAfter
* @property int accountNoAfter
* @property int accountYuchoSignAfter
* @property int accountYuchoNoAfter
* @property Carbon smbcApplicationDatetime
* @property string smbcAcceptNo
* @property string smbcResult
*/
class BankAccountUpdateApplication extends GeneralApplication
{
const FIELD_BANK_BRANCH_ID_BEFORE = "口座変更申請_変更前_銀行支店ID";
const FIELD_BANK_CODE_BEFORE = "口座変更申請_変更前_金融機関コード";
const FIELD_BANK_NAME_BEFORE = "口座変更申請_変更前_金融機関名";
const FIELD_BRANCH_CODE_BEFORE = "口座変更申請_変更前_支店コード";
const FIELD_BRANCH_NAME_BEFORE = "口座変更申請_変更前_支店名";
const FIELD_ACCOUNT_TYPE_BEFORE = "口座変更申請_変更前_口座種目";
const FIELD_ACCOUNT_NAME_KANA_BEFORE = "口座変更申請_変更前_口座名義カナ";
const FIELD_ACCOUNT_NO_BEFORE = "口座変更申請_変更前_口座番号";
const FIELD_ACCOUNT_YUCHO_SIGN_BEFORE = "口座変更申請_変更前_ゆうちょ口座記号";
const FIELD_ACCOUNT_YUCHO_NO_BEFORE = "口座変更申請_変更前_ゆうちょ口座番号";
const FIELD_BANK_BRANCH_ID_AFTER = "口座変更申請_変更後_銀行支店ID";
const FIELD_BANK_CODE_AFTER = "口座変更申請_変更後_金融機関コード";
const FIELD_BANK_NAME_AFTER = "口座変更申請_変更後_金融機関名";
const FIELD_BRANCH_CODE_AFTER = "口座変更申請_変更後_支店コード";
const FIELD_BRANCH_NAME_AFTER = "口座変更申請_変更後_支店名";
const FIELD_ACCOUNT_TYPE_AFTER = "口座変更申請_変更後_口座種目";
const FIELD_ACCOUNT_NAME_KANA_AFTER = "口座変更申請_変更後_口座名義カナ";
const FIELD_ACCOUNT_NO_AFTER = "口座変更申請_変更後_口座番号";
const FIELD_ACCOUNT_YUCHO_SIGN_AFTER = "口座変更申請_変更後_ゆうちょ口座記号";
const FIELD_ACCOUNT_YUCHO_NO_AFTER = "口座変更申請_変更後_ゆうちょ口座番号";
const FIELD_APPLICATION_CUSTOMER_CODE = "口座変更申請_顧客コード";
const FIELD_SMBC_APPLICATION_DATETIME = "口座変更申請_SMBC申請日時";
const FIELD_SMBC_ACCEPT_NO = "口座変更申請_SMBC受付番号";
const FIELD_SMBC_RESULT = "口座変更申請_SMBC結果";

protected const FIELDS = [
...parent::FIELDS,
self::FIELD_BANK_BRANCH_ID_BEFORE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BANK_CODE_BEFORE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BANK_NAME_BEFORE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BRANCH_CODE_BEFORE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BRANCH_NAME_BEFORE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_ACCOUNT_TYPE_BEFORE => FieldType::NUMBER,
self::FIELD_ACCOUNT_NAME_KANA_BEFORE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_ACCOUNT_NO_BEFORE => FieldType::NUMBER,
self::FIELD_ACCOUNT_YUCHO_SIGN_BEFORE => FieldType::NUMBER,
self::FIELD_ACCOUNT_YUCHO_NO_BEFORE => FieldType::NUMBER,
self::FIELD_BANK_BRANCH_ID_AFTER => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BANK_CODE_AFTER => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BANK_NAME_AFTER => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BRANCH_CODE_AFTER => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BRANCH_NAME_AFTER => FieldType::SINGLE_LINE_TEXT,
self::FIELD_ACCOUNT_TYPE_AFTER => FieldType::NUMBER,
self::FIELD_ACCOUNT_NAME_KANA_AFTER => FieldType::SINGLE_LINE_TEXT,
self::FIELD_ACCOUNT_NO_AFTER => FieldType::NUMBER,
self::FIELD_ACCOUNT_YUCHO_SIGN_AFTER => FieldType::NUMBER,
self::FIELD_ACCOUNT_YUCHO_NO_AFTER => FieldType::NUMBER,
self::FIELD_APPLICATION_CUSTOMER_CODE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_SMBC_APPLICATION_DATETIME => FieldType::DATETIME,
self::FIELD_SMBC_ACCEPT_NO => FieldType::SINGLE_LINE_TEXT,
self::FIELD_SMBC_RESULT => FieldType::SINGLE_LINE_TEXT,

];

protected const FIELD_NAMES = [
...parent::FIELD_NAMES,
];
}

+ 3
- 0
app/Kintone/Models/Customer.php ファイルの表示

@@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Auth;
* @property string phoneNumber
* @property string zipCode
* @property string address
* @property string bankBranchId
*/
class Customer extends KintoneModel
{
@@ -25,6 +26,7 @@ class Customer extends KintoneModel
const FIELD_PHONE_NUMBER = "電話番号";
const FIELD_ZIP_CODE = "契約者_郵便番号";
const FIELD_ADDRESS = "住所";
const FIELD_BANK_BRANCH_ID = "ChargedBankBranchCode";

protected const FIELDS = [
...parent::FIELDS,
@@ -35,6 +37,7 @@ class Customer extends KintoneModel
self::FIELD_PHONE_NUMBER => FieldType::LINK,
self::FIELD_ZIP_CODE => FieldType::SINGLE_LINE_TEXT,
self::FIELD_ADDRESS => FieldType::SINGLE_LINE_TEXT,
self::FIELD_BANK_BRANCH_ID => FieldType::SINGLE_LINE_TEXT,
];

protected const FIELD_NAMES = [


+ 1
- 0
app/Kintone/Models/GeneralApplication.php ファイルの表示

@@ -47,6 +47,7 @@ abstract class GeneralApplication extends KintoneModel
protected const RELATIONS = [
SeasonTicketContract::class,
Customer::class,
Bank::class,
];

public static function findByApplicationNo(string $applicationNo): static


+ 9
- 0
app/Logic/GeneralApplicationManager.php ファイルの表示

@@ -3,6 +3,7 @@
namespace App\Logic;

use App\Exceptions\AppCommonException;
use App\Kintone\Models\BankAccountUpdateApplication;
use App\Kintone\Models\Customer;
use App\Kintone\Models\GeneralApplication;
use App\Kintone\Models\Parking;
@@ -61,6 +62,10 @@ class GeneralApplicationManager
$this->setType("振替頻度変更");
return;
}
if ($model instanceof BankAccountUpdateApplication) {
$this->setType("口座変更申請");
return;
}
}

public function setCustomer(Customer $customer): static
@@ -102,6 +107,10 @@ class GeneralApplicationManager
$this->model->parkingName = $this->parking->parkingName;
}

if ($this->model instanceof BankAccountUpdateApplication) {
$this->model->applicationCustomerCode = $this->customer->customerCode;
}

return $this->model;
}



+ 22
- 0
app/Models/SmbcPollStatus.php ファイルの表示

@@ -0,0 +1,22 @@
<?php

namespace App\Models;

class SmbcPollStatus extends AppModel
{
const COL_NAME_CONDITION_DATETIME_TO = 'condition_datetime_to';

protected $casts = [
self::COL_NAME_CONDITION_DATETIME_TO => 'datetime',
];

public function getHistory(): ?HistoryModel
{
return null;
}

public function getModelName(): string
{
return "SMBC口座振替登録依頼確認ステータス";
}
}

+ 16
- 0
app/Util/EncodingUtil.php ファイルの表示

@@ -0,0 +1,16 @@
<?php

namespace App\Util;

class EncodingUtil
{

public static function toUtf8FromSjis(string $source)
{
return mb_convert_encoding($source, "UTF8", 'SJIS');
}
public static function toSjisFromUtf8(string $source)
{
return mb_convert_encoding($source, "SJIS", 'UTF8');
}
}

+ 1
- 0
config/kintone.php ファイルの表示

@@ -27,6 +27,7 @@ return [

'applications' => [
...App\Kintone\Models\Customer::setConfig(),
...App\Kintone\Models\Bank::setConfig(),
...App\Kintone\Models\Parking::setConfig(),
...App\Kintone\Models\SeasonTicketContract::setConfig(),
...App\Kintone\Models\SeasonTicketContractEntry::setConfig(),


+ 20
- 0
config/smbc.php ファイルの表示

@@ -0,0 +1,20 @@
<?php

return [


/*
|--------------------------------------------------------------------------
| SMBCのパスワード管理
|--------------------------------------------------------------------------
|
| キントーンAPIのホストを定義
*/

'systemPassword' => env("SMBC_SYSTEM_PASSWORD"),
'searchPassword' => env("SMBC_SEARCH_PASSWORD"),

'registerUrl' => env("SMBC_URL_REGISTER"),
'searchUrl' => env("SMBC_URL_SEARCH"),

];

+ 30
- 0
database/migrations/2023_10_06_182600_create_smbc_poll_statuses_table.php ファイルの表示

@@ -0,0 +1,30 @@
<?php

use App\Util\MigrationHelper;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('smbc_poll_statuses', function (Blueprint $table) {
$helper = new MigrationHelper($table);
$helper->baseColumn();

$table->dateTime('condition_datetime_to')->comment('前回検索条件_TO時刻');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('smbc_poll_statuses');
}
};

+ 1
- 0
routes/api.php ファイルの表示

@@ -37,6 +37,7 @@ RouteHelper::post('/ask', App\Http\Controllers\Web\FAQ\AskController::class);
RouteHelper::post('/email/change/start', App\Http\Controllers\Web\Customer\ChangeEmailStartController::class);
RouteHelper::post('/email/change/verify', App\Http\Controllers\Web\Customer\ChangeEmailVerifyController::class);
RouteHelper::post('/customer/update-info-order', App\Http\Controllers\Web\Customer\UpdateUserInfoOrderController::class);
RouteHelper::get('/customer/bank-account-register/start', App\Http\Controllers\Web\Customer\BankAccountRegisterStartController::class);

RouteHelper::post('/password/setting/start', App\Http\Controllers\Web\Auth\PasswordSettingStartController::class);
RouteHelper::post('/password/setting/verify', App\Http\Controllers\Web\Auth\PasswordSettingVerifyController::class);

+ 21
- 0
tests/Feature/Http/API/SMBC/SMBCTest.php ファイルの表示

@@ -0,0 +1,21 @@
<?php

namespace Tests\Feature\Http\API\SMBC;

use App\Http\API\SMBC\SMBC;
use App\Util\DateUtil;
use Tests\TestCase;

class SMBCTest extends TestCase
{

public function test_poll(): void
{
$from = DateUtil::now()->setDate(2023, 10, 5);
$to = DateUtil::now()->setDate(2023, 10, 7);
$result = SMBC::poll($from, $to);

$this->assertEquals("", $result->getMessage());
$this->assertTrue($result->ok());
}
}

+ 41
- 0
tests/Feature/Kintone/BankAccountUpdateApplicationTest.php ファイルの表示

@@ -0,0 +1,41 @@
<?php

namespace Tests\Feature\Kintone;

use App\Kintone\Models\BankAccountUpdateApplication;
use App\Kintone\Models\Customer;
use App\Logic\GeneralApplicationManager;
use Tests\TestCase;

class BankAccountUpdateApplicationTest extends TestCase
{

public function test_simple(): void
{
$customer = Customer::findByCustomerCode("171");


$application = new BankAccountUpdateApplication();
$manager = new GeneralApplicationManager($application);
$manager
->setCustomer($customer)
->makeApplication();

$application->bankBranchIdBefore = $customer->bankBranchId;

$application->bankBranchIdAfter = "1004";
$application->bankCodeAfter = "1";
$application->bankNameAfter = "みずほー";
$application->branchCodeAfter = "4";
$application->branchNameAfter = "まるのうち";
$application->accountTypeAfter = "1";
$application->accountNameKanaAfter = "テストタロウ";
$application->accountNoAfter = "1234567";
$application->accountYuchoSignAfter = "01234";
$application->accountYuchoNoAfter = "12345678";

$application->save();

$this->assertTrue(true);
}
}

読み込み中…
キャンセル
保存