sosuke.iwabuchi 1 год назад
Родитель
Сommit
6816f626e3
23 измененных файлов: 885 добавлений и 6 удалений
  1. +1
    -0
      app/Console/Commands/DataPatch/FillPaymentPlan.php
  2. +129
    -0
      app/Console/Commands/PoolTransfer/AttachToPaymentPlan.php
  3. +124
    -0
      app/Console/Commands/PoolTransfer/MoveToPool.php
  4. +1
    -0
      app/Console/Kernel.php
  5. +22
    -0
      app/Console/Schedules/PoolTransfer.php
  6. +1
    -1
      app/Console/Schedules/SMBCBankAccountRegisterPoll.php
  7. +2
    -2
      app/Console/Schedules/SMBCPaymentPoll.php
  8. +0
    -1
      app/Email/Members/EntryPaymentComplete.php
  9. +9
    -0
      app/Exceptions/SkipException.php
  10. +10
    -0
      app/Kintone/Models/DropDown/PoolTransferHistory/TransferMethod.php
  11. +9
    -0
      app/Kintone/Models/DropDown/PoolTransferHistory/TransgerType.php
  12. +4
    -0
      app/Kintone/Models/KintoneModel.php
  13. +30
    -1
      app/Kintone/Models/PaymentPlan.php
  14. +36
    -0
      app/Kintone/Models/Pool.php
  15. +75
    -0
      app/Kintone/Models/PoolTransferHistory.php
  16. +40
    -0
      app/Kintone/Models/SmbcAccountTransferResult.php
  17. +3
    -0
      app/Kintone/Models/SmbcPayment.php
  18. +38
    -0
      app/Kintone/Models/YuchoPaymentResult.php
  19. +192
    -0
      app/Logic/PoolAttachManager.php
  20. +119
    -0
      app/Logic/PoolTransferManager.php
  21. +21
    -1
      app/Logic/ReceiptManager.php
  22. +15
    -0
      app/Util/CollectionUtil.php
  23. +4
    -0
      config/kintone.php

+ 1
- 0
app/Console/Commands/DataPatch/FillPaymentPlan.php Просмотреть файл

@@ -74,6 +74,7 @@ class FillPaymentPlan extends BaseCommand
// プランの取得
$plans = $this->getPlans();


foreach ($plans as $plan) {

// 契約の取得


+ 129
- 0
app/Console/Commands/PoolTransfer/AttachToPaymentPlan.php Просмотреть файл

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

namespace App\Console\Commands\PoolTransfer;

use App\Console\Commands\BaseCommand;
use App\Email\Members\EntryPaymentComplete;
use App\Exceptions\SkipException;
use App\Kintone\KintoneRecordQueryOperator;
use App\Kintone\Models\PaymentPlan;
use App\Kintone\Models\Pool;
use App\Kintone\Models\SeasonTicketContractEntry;
use App\Logic\EmailManager;
use App\Logic\PoolAttachManager;

class AttachToPaymentPlan extends BaseCommand
{

const COMMAND = "pool-transfer:attach-to-payment-plan";


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

/**
* The console command description.
*
* @var string
*/
protected $description = '入金予定実績へ充当する';

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

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return int
*/
public function service(): int


{
$targets = $this->getTargets();


$this->outputInfo(sprintf("総件数:%d件", $targets->count()));



foreach ($targets as $index => $target) {

// 100件ごとに経過を出力
if ($index % 100 === 0) {
$this->outputInfo(sprintf("処理中:%d件目", $index + 1));
}
try {
$this->handleData($target);
} catch (SkipException $e) {
$this->outputWarn($e->getMessage());
}
}


return self::RESULTCODE_SUCCESS;
}

public function handleData(Pool $pool)
{
$manager = new PoolAttachManager();
$manager->attach($pool)
->save();

// 初回振り込み完了処理
if ($manager->getFirstPaymnetEntryRecordIds()->isNotEmpty()) {
foreach ($manager->getFirstPaymnetEntryRecordIds() as $entryRecordId) {
$this->handleFirstPaymentDone($entryRecordId);
}
}
}

public function handleFirstPaymentDone(int $entryRecordNo)
{
// 未払いチェック
$query = PaymentPlan::getQuery()->where(PaymentPlan::FIELD_FIRST_PAYMENT_ENTRY_RECORD_NO, $entryRecordNo);
$plans = PaymentPlan::getAccess()->all($query);
if ($plans->isEmpty()) {
return;
}

// 未払い検索
$未払い = $plans->first((function (PaymentPlan $plan) {
return !$plan->appropriationDate || $plan->appropriationAmount !== $plan->paymentPlanAmount;
}));
if ($未払い) {
return;
}


// 承認メール送信
$entry = SeasonTicketContractEntry::find($entryRecordNo);
$parking = $entry->getParking();
$plan = $entry->getPlan();
$email = new EntryPaymentComplete($parking, $entry, $plan);
(new EmailManager($email))->confirm();
}

public function getTargets()
{
$query = Pool::getQuery()->where(Pool::FIELD_POOL_AMOUNT, 0, KintoneRecordQueryOperator::GT);
$ret = Pool::getAccess()->all($query);
return $ret;
}
}

+ 124
- 0
app/Console/Commands/PoolTransfer/MoveToPool.php Просмотреть файл

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

namespace App\Console\Commands\PoolTransfer;

use App\Console\Commands\BaseCommand;
use App\Exceptions\SkipException;
use App\Kintone\KintoneRecordQueryOperator;
use App\Kintone\Models\DropDown\SmbcPayment\SmbcPaymentStatus;
use App\Kintone\Models\SmbcAccountTransferResult;
use App\Kintone\Models\SmbcPayment;
use App\Kintone\Models\YuchoPaymentResult;
use App\Logic\PoolTransferManager;
use App\Util\CollectionUtil;
use Illuminate\Support\Collection;

class MoveToPool extends BaseCommand
{

const COMMAND = "pool-transfer:move-to-pool";


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

/**
* The console command description.
*
* @var string
*/
protected $description = '入金プールへ異動する';

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

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return int
*/
public function service(): int


{
$targets = $this->getTargets();


$this->outputInfo(sprintf("総件数:%d件", $targets->count()));

foreach ($targets as $target) {

try {
$this->handleData($target);
} catch (SkipException $e) {
$this->outputWarn($e->getMessage());
}
}


return self::RESULTCODE_SUCCESS;
}

public function handleData(YuchoPaymentResult|SmbcPayment|SmbcAccountTransferResult $payment)
{

$manager = new PoolTransferManager();
$manager->moveToPool($payment);
}

/**
* @return Collection<int ,YuchoPaymentResult|SmbcPayment|SmbcAccountTransferResult>
*/
public function getTargets()
{
/**
* @var Collection<int ,YuchoPaymentResult|SmbcPayment|SmbcAccountTransferResult>
*/
$ret = collect();

// ゆうちょ振込
$query = YuchoPaymentResult::getQuery()->whereNotIn(YuchoPaymentResult::FIELD_POOL_DONE, ["済"])
->whereNotNull(YuchoPaymentResult::FIELD_CUSTOMER_CODE)
->where(YuchoPaymentResult::FIELD_PAYMENT_AMOUNT, 0, KintoneRecordQueryOperator::GT);

$targets = YuchoPaymentResult::getAccess()->all($query);
$ret->concat($targets);
CollectionUtil::pushAll($ret, $targets);
$this->outputInfo(sprintf("ゆうちょ件数:%d件", $targets->count()));

// コンビニ支払
$query = SmbcPayment::getQuery()->whereNotIn(SmbcPayment::FIELD_POOL_DONE, ["済"])
->whereNotNull(SmbcPayment::FIELD_CUSTOMER_CODE)
->where(SmbcPayment::FIELD_PAYMENT_AMOUNT, 0, KintoneRecordQueryOperator::GT)
->whereIn(SmbcPayment::FIELD_STATUS, [SmbcPaymentStatus::S002_決済結果待ち]);
$targets = SmbcPayment::getAccess()->all($query);
CollectionUtil::pushAll($ret, $targets);
$this->outputInfo(sprintf("コンビニ支払:%d件", $targets->count()));

// 口座振替
$query = SmbcAccountTransferResult::getQuery()->whereNotIn(SmbcAccountTransferResult::FIELD_POOL_DONE, ["済"])
->whereNotNull(SmbcAccountTransferResult::FIELD_CUSTOMER_CODE)
->where(SmbcAccountTransferResult::FIELD_PAYMENT_AMOUNT, 0, KintoneRecordQueryOperator::GT);
$targets = SmbcAccountTransferResult::getAccess()->all($query);
CollectionUtil::pushAll($ret, $targets);
$this->outputInfo(sprintf("口座振替:%d件", $targets->count()));

return $ret;
}
}

+ 1
- 0
app/Console/Kernel.php Просмотреть файл

@@ -18,6 +18,7 @@ class Kernel extends ConsoleKernel
Schedules\BankAccountRegisterRemaind::register($schedule);
Schedules\SeasonTikcetContractSelectionSetResult::register($schedule);
Schedules\SeasonTicketContractTerminateComplete::register($schedule);
Schedules\PoolTransfer::register($schedule);
}

/**


+ 22
- 0
app/Console/Schedules/PoolTransfer.php Просмотреть файл

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

namespace App\Console\Schedules;

use App\Console\Commands\PoolTransfer\MoveToPool;
use App\Console\Commands\PoolTransfer\AttachToPaymentPlan;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Support\Facades\Artisan;

class PoolTransfer extends BaseSchedule
{

static public function register(Schedule $schedule)
{
$schedule->command(MoveToPool::class)
->twiceDaily(10, 16)
->description("プール金異動")
->onSuccess(function () {
Artisan::call(AttachToPaymentPlan::class);
});
}
}

+ 1
- 1
app/Console/Schedules/SMBCBankAccountRegisterPoll.php Просмотреть файл

@@ -11,7 +11,7 @@ class SMBCBankAccountRegisterPoll extends BaseSchedule
static public function register(Schedule $schedule)
{
$schedule->command(Command::class)
->everyThreeMinutes()
->everyOddHour()
->unlessBetween('1:00', '6:00')
->description("SMBC口座振替申請結果取得");
}


+ 2
- 2
app/Console/Schedules/SMBCPaymentPoll.php Просмотреть файл

@@ -11,8 +11,8 @@ class SMBCPaymentPoll extends BaseSchedule
static public function register(Schedule $schedule)
{
$schedule->command(Command::class)
->everyTwoHours()
->twiceDailyAt(9, 15, 30)
->unlessBetween('1:00', '6:00')
->description("SMBC支払結果取得");
->description("SMBC支払結果取得(コンビニ)");
}
}

+ 0
- 1
app/Email/Members/EntryPaymentComplete.php Просмотреть файл

@@ -43,7 +43,6 @@ class EntryPaymentComplete extends Members
'use_start_date' => $entry->useStartDate ? $entry->useStartDate->format('Y/m/d') : "-",
'payment_method' => $entry->paymentMethod ?? "-",
'amount' => number_format($entry->amount ?? 0),
'paymentExplain' => EntryMessageBuilder::getPaymentExplainStr($this->entry),
'taxExplain' => EntryMessageBuilder::getTaxExplain($this->plan),
'can_terminate_15' => in_array(Parking::ELEMENT_CAN_TERMINATE_DATE_15, $this->parking->canTerminateDate),
'can_terminate_end_of_month' => in_array(Parking::ELEMENT_CAN_TERMINATE_DATE_END_OF_MONTH, $this->parking->canTerminateDate),


+ 9
- 0
app/Exceptions/SkipException.php Просмотреть файл

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

namespace App\Exceptions;

use Exception;

class SkipException extends Exception
{
}

+ 10
- 0
app/Kintone/Models/DropDown/PoolTransferHistory/TransferMethod.php Просмотреть файл

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

namespace App\Kintone\Models\DropDown\PoolTransferHistory;

abstract class TransferMethod
{
const ACCOUNT_TRANSFER = "口座振替";
const YUCHO = "ゆうちょ振込";
const CVS = "コンビニ支払";
}

+ 9
- 0
app/Kintone/Models/DropDown/PoolTransferHistory/TransgerType.php Просмотреть файл

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

namespace App\Kintone\Models\DropDown\PoolTransferHistory;

abstract class TransgerType
{
const INCOME = "入金";
const ATTACH = "充当";
}

+ 4
- 0
app/Kintone/Models/KintoneModel.php Просмотреть файл

@@ -453,6 +453,10 @@ abstract class KintoneModel

public function save()
{
if (count($this->changed) === 0) {
return;
}

$access = static::getAccess();
if ($this->recordId === null) {
$access->create($this);


+ 30
- 1
app/Kintone/Models/PaymentPlan.php Просмотреть файл

@@ -23,7 +23,9 @@ use Illuminate\Support\Collection;
* @property Carbon appropriationDate
* @property int appropriationAmount
* @property int remainingAmount
* @property int firstPaymentEntryRecordNo
* @property Collection<int ,Deposit> depositList
* @property string[] partialFee
*/
class PaymentPlan extends KintoneModel
{
@@ -42,9 +44,11 @@ class PaymentPlan extends KintoneModel
const FIELD_APPROPRIATION_DATE = "appropriation_date";
const FIELD_APPROPRIATION_AMOUNT = "appropriation_amount";
const FIELD_REMAINING_AMOUNT = "remaining_amount";
const FIELD_FIRST_PAYMENT_ENTRY_RECORD_NO = "first_payment_entry_record_no";
const FIELD_DEPOSIT_LIST = "保証金明細";
const FIELD_DEPOSIT_LIST_NAME = "保証金明細_名称";
const FIELD_DEPOSIT_LIST_AMOUNT = "保証金明細_金額";
const FIELD_PARTIAL_FEE = "定期料金日割り分";

protected const FIELDS = [
...parent::FIELDS,
@@ -61,7 +65,9 @@ class PaymentPlan extends KintoneModel
self::FIELD_APPROPRIATION_DATE => FieldType::DATE,
self::FIELD_APPROPRIATION_AMOUNT => FieldType::NUMBER,
self::FIELD_REMAINING_AMOUNT => FieldType::NUMBER,
self::FIELD_FIRST_PAYMENT_ENTRY_RECORD_NO => FieldType::NUMBER,
self::FIELD_DEPOSIT_LIST => FieldType::SUBTABLE,
self::FIELD_PARTIAL_FEE => FieldType::CHECK_BOX,
];

protected const SUB_TABLES = [
@@ -87,14 +93,37 @@ class PaymentPlan extends KintoneModel
];
}

/**
* 支払い済みか判定
*
* @return boolean
*/
public function donePayment(): bool
{
$paymentDate = $this->getDate(self::FIELD_APPROPRIATION_DATE);
$remainingAmount = $this->getNumber(self::FIELD_REMAINING_AMOUNT);
$paymentPlanAmount = $this->getNumber(self::FIELD_PAYMENT_PLAN_AMOUNT);
$paymentAmount = $this->getNumber(self::FIELD_APPROPRIATION_AMOUNT);

return !!$paymentDate && $remainingAmount === 0;
return !!$paymentDate && $remainingAmount === 0 && $paymentPlanAmount === $paymentAmount;
}

/**
* 日割り分の請求データか判定
*
* @return boolean
*/
public function isPartialFee(): bool
{
$target = $this->partialFee;
if (is_array($target) && !!count($target)) {
return true;
}
return false;
}



private function getViewName(): string
{



+ 36
- 0
app/Kintone/Models/Pool.php Просмотреть файл

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

namespace App\Kintone\Models;

use Illuminate\Support\Carbon;

/**
* アプリ名 入金プール
*
* @property int customerCode
* @property string customerName
* @property int poolAmount
*/
class Pool extends KintoneModel
{
const CONFIG_KEY = "KINTONE_APP_POOL";

const FIELD_CUSTOMER_CODE = "顧客コード";
const FIELD_CUSTOMER_NAME = "顧客名";
const FIELD_POOL_AMOUNT = "プール金";

protected const FIELDS = [
...parent::FIELDS,
self::FIELD_CUSTOMER_CODE => FieldType::NUMBER,
self::FIELD_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT,
self::FIELD_POOL_AMOUNT => FieldType::NUMBER,
];

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

protected const RELATIONS = [
Customer::class,
];
}

+ 75
- 0
app/Kintone/Models/PoolTransferHistory.php Просмотреть файл

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

namespace App\Kintone\Models;

use Illuminate\Support\Carbon;

/**
* アプリ名 プール金・異動履歴
*
* @property int poolRecordNo
* @property int customerCode
* @property string customerName
* @property Carbon transferDatetime
* @property string transferType
* @property int transferAmount
* @property int poolAmountBefore
* @property int poolAmountAfter
* @property ?string incomeMethod
* @property ?int incomeAccountTransferResultRecordNo
* @property ?int incomeYuchoTransferRecordNo
* @property ?int incomeCvsPaymentRecordNo
* @property ?int paymentPlanRecordNo
* @property ?int seasonContractRecordNo
*/
class PoolTransferHistory extends KintoneModel
{
const CONFIG_KEY = "KINTONE_APP_POOL_TRANSFER_HISTORY";

const FIELD_POOL_RECORD_NO = "入金プールレコード番号";
const FIELD_CUSTOMER_CODE = "顧客コード";
const FIELD_CUSTOMER_NAME = "顧客名";
const FIELD_TRANSFER_DATETIME = "異動日時";
const FIELD_TRANSFER_TYPE = "種別";
const FIELD_TRANSFER_AMOUNT = "異動金額";
const FIELD_POOL_AMOUNT_BEFORE = "異動前残高";
const FIELD_POOL_AMOUNT_AFTER = "異動後残高";
const FIELD_INCOME_METHOD = "入金手段";
const FIELD_INCOME_ACCOUNT_TRANSFER_RESULT_RECORD_NO = "口座振替結果レコード番号";
const FIELD_INCOME_YUCHO_TRANSFER_RECORD_NO = "ゆうちょ振込レコード番号";
const FIELD_INCOME_CVS_PAYMENT_RECORD_NO = "コンビニ支払レコード番号";
const FIELD_PAYMENT_PLAN_RECORD_NO = "入金予定結果レコード番号";
const FIELD_SEASON_CONTRACT_RECORD_NO = "車室情報管理レコード番号";


protected const FIELDS = [
...parent::FIELDS,
self::FIELD_POOL_RECORD_NO => FieldType::NUMBER,
self::FIELD_CUSTOMER_CODE => FieldType::NUMBER,
self::FIELD_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT,
self::FIELD_TRANSFER_DATETIME => FieldType::DATETIME,
self::FIELD_TRANSFER_TYPE => FieldType::DROP_DOWN,
self::FIELD_TRANSFER_AMOUNT => FieldType::NUMBER,
self::FIELD_POOL_AMOUNT_BEFORE => FieldType::NUMBER,
self::FIELD_POOL_AMOUNT_AFTER => FieldType::NUMBER,
self::FIELD_INCOME_METHOD => FieldType::SINGLE_LINE_TEXT,
self::FIELD_INCOME_ACCOUNT_TRANSFER_RESULT_RECORD_NO => FieldType::NUMBER,
self::FIELD_INCOME_YUCHO_TRANSFER_RECORD_NO => FieldType::NUMBER,
self::FIELD_INCOME_CVS_PAYMENT_RECORD_NO => FieldType::NUMBER,
self::FIELD_PAYMENT_PLAN_RECORD_NO => FieldType::NUMBER,
self::FIELD_SEASON_CONTRACT_RECORD_NO => FieldType::NUMBER,
];

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

protected const RELATIONS = [
Customer::class,
YuchoPaymentResult::class,
SmbcPayment::class,
SmbcAccountTransferResult::class,
Pool::class,
PaymentPlan::class,
];
}

+ 40
- 0
app/Kintone/Models/SmbcAccountTransferResult.php Просмотреть файл

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

namespace App\Kintone\Models;

use Illuminate\Support\Carbon;

/**
* アプリ名 SMBC口座振替結果
*
* @property int customerCode
* @property string customerName
* @property Carbon paymentDate
* @property int paymentAmount
* @property string[] poolDone
*/
class SmbcAccountTransferResult extends KintoneModel
{
const CONFIG_KEY = "KINTONE_APP_SMBC_ACCOUNT_TRANSFER_RESULT";

const FIELD_CUSTOMER_CODE = "顧客コード";
const FIELD_CUSTOMER_NAME = "顧客名";
const FIELD_PAYMENT_DATE = "引落日";
const FIELD_PAYMENT_AMOUNT = "引落金額";
const FIELD_POOL_DONE = "プール済み";
const FIELD_RESULT_CODE = "結果コード";

protected const FIELDS = [
...parent::FIELDS,
self::FIELD_CUSTOMER_CODE => FieldType::NUMBER,
self::FIELD_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT,
self::FIELD_PAYMENT_DATE => FieldType::DATE,
self::FIELD_PAYMENT_AMOUNT => FieldType::NUMBER,
self::FIELD_POOL_DONE => FieldType::CHECK_BOX,
self::FIELD_RESULT_CODE => FieldType::SINGLE_LINE_TEXT,
];

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

+ 3
- 0
app/Kintone/Models/SmbcPayment.php Просмотреть файл

@@ -12,6 +12,7 @@ use Illuminate\Support\Carbon;
* @property string orderNo
* @property int customerCode
* @property int claimAmount
* @property string[] poolDone
* @property string acceptNo
* @property string paymentStatus
* @property ?Carbon paymentStatusUpdateDatetime
@@ -30,6 +31,8 @@ class SmbcPayment extends KintoneModel
const FIELD_ORDER_NO = "請求_補助_番号";
const FIELD_CUSTOMER_CODE = "顧客コード";
const FIELD_CLAIM_AMOUNT = "請求金額";
const FIELD_POOL_DONE = "プール済み";


const FIELD_ACCEPT_NO = "決済受付番号";
const FIELD_PAYMENT_STATUS = "決済ステータス";


+ 38
- 0
app/Kintone/Models/YuchoPaymentResult.php Просмотреть файл

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

namespace App\Kintone\Models;

use Illuminate\Support\Carbon;

/**
* アプリ名 ゆうちょ振込情報
*
* @property int customerCode
* @property string customerName
* @property Carbon paymentDate
* @property int paymentAmount
* @property string[] poolDone
*/
class YuchoPaymentResult extends KintoneModel
{
const CONFIG_KEY = "KINTONE_APP_YUCHO_PAYMENT_RESULT";

const FIELD_CUSTOMER_CODE = "顧客コード";
const FIELD_CUSTOMER_NAME = "顧客名";
const FIELD_PAYMENT_DATE = "取引日";
const FIELD_PAYMENT_AMOUNT = "受入金額";
const FIELD_POOL_DONE = "プール済み";

protected const FIELDS = [
...parent::FIELDS,
self::FIELD_CUSTOMER_CODE => FieldType::NUMBER,
self::FIELD_CUSTOMER_NAME => FieldType::SINGLE_LINE_TEXT,
self::FIELD_PAYMENT_DATE => FieldType::DATE,
self::FIELD_PAYMENT_AMOUNT => FieldType::NUMBER,
self::FIELD_POOL_DONE => FieldType::CHECK_BOX,
];

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

+ 192
- 0
app/Logic/PoolAttachManager.php Просмотреть файл

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

namespace App\Logic;

use App\Exceptions\SkipException;
use App\Kintone\KintoneRecordQuery;
use App\Kintone\Models\DropDown\PaymentPlan\PaymentType;
use App\Kintone\Models\DropDown\PoolTransferHistory\TransgerType;
use App\Kintone\Models\PaymentPlan;
use App\Kintone\Models\Pool;
use App\Kintone\Models\PoolTransferHistory;
use App\Util\DateUtil;
use Exception;
use Illuminate\Support\Collection;

/**
* 入金プールから入金予定結果へ異動する
*/
class PoolAttachManager
{

private Pool|null $pool = null;

/**
* @var Collection<int, PoolTransferHistory>
*/
private Collection $histories;
/**
* @var Collection<int, PaymentPlan>
*/
private Collection $plans;
/**
* @var Collection<int, PaymentPlan>
*/
private Collection $completePlans;


/**
* @var Collection<int, bool>
*/
private Collection $firstPaymnetEntryRecordIds;


public function attach(Pool $pool)
{
$this->clear();

if ($pool->poolAmount === 0) {
throw new SkipException(sprintf("プール金なし 顧客コード:%d", $pool->customerCode));
}
$this->pool = $pool;

$this->plans = $this->getPaymentPlans();

foreach ($this->plans as $plan) {
try {
if (!$this->canAttach($plan)) {
throw new AttachStop(sprintf("残高不足のため充当途中停止 顧客コード:%d", $this->pool->customerCode));
}
$this->makeHistory($plan);
$this->setPoolAmount($plan);
$this->setPaymentPlanDone($plan);
} catch (AttachStop $e) {
logs()->warning($e->getMessage());
break;
}
}

return $this;
}

public function getFirstPaymnetEntryRecordIds()
{
return $this->firstPaymnetEntryRecordIds->keys();
}

private function getPaymentPlans()
{
$query = PaymentPlan::getQuery()
->where(PaymentPlan::FIELD_CUSTOMER_CODE, $this->pool->customerCode)
->whereNull(PaymentPlan::FIELD_APPROPRIATION_DATE)
->where(function (KintoneRecordQuery $q) {
$q->whereNull(PaymentPlan::FIELD_APPROPRIATION_AMOUNT)
->orWhere(PaymentPlan::FIELD_APPROPRIATION_AMOUNT, 0);
})
->orderByAsc(PaymentPlan::FIELD_PAYMENT_PLAN_DATE);

$plans = PaymentPlan::getAccess()->all($query);
return $plans;
}

private function canAttach(PaymentPlan $plan)
{
$afterPool = $this->pool->poolAmount - $plan->paymentPlanAmount;
return 0 <= $afterPool;
}


private function makeHistory(PaymentPlan $plan)
{
$history = new PoolTransferHistory();
$history->poolRecordNo = $this->pool->getRecordId();
$history->customerCode = $this->pool->customerCode;
$history->transferDatetime = DateUtil::now();
$history->transferType = TransgerType::ATTACH;
$history->transferAmount = $plan->paymentPlanAmount;
$history->poolAmountBefore = $this->pool->poolAmount;
$history->poolAmountAfter = $this->pool->poolAmount - $plan->paymentPlanAmount;
$history->paymentPlanRecordNo = $plan->getRecordId();

$this->histories->push($history);
}

private function setPoolAmount(PaymentPlan $plan)
{

$afterPool = $this->pool->poolAmount - $plan->paymentPlanAmount;
$this->pool->poolAmount = $afterPool;
}

private function setPaymentPlanDone(PaymentPlan $plan)
{
$plan->appropriationDate = DateUtil::now();
$plan->appropriationAmount = $plan->paymentPlanAmount;
$plan->remainingAmount = 0;

if (!!$plan->firstPaymentEntryRecordNo) {
$this->firstPaymnetEntryRecordIds->put($plan->firstPaymentEntryRecordNo, true);
}

$this->completePlans->push($plan);
}

public function save()
{
foreach ($this->histories as $history) {
$history->save();
}
foreach ($this->completePlans as $plan) {
$plan->save();
}
$this->pool->save();

$this->makeReceipt();

return $this;
}

private function makeReceipt()
{

if ($this->completePlans->isEmpty()) {
return;
}

// 支払い種別ごとにグルーピング
$ids = [];
foreach ($this->completePlans as $plan) {

// 保証金は領収証を発行しない
if ($plan->paymentType === PaymentType::A保証金) {
continue;
}

$ids[$plan->paymentType][] = $plan;
}

// 領収証作成
foreach ($ids as $targets) {
$manager = new ReceiptManager();

$manager->setPaymentPlans(collect($targets))
->create($targets);
}

return $this;
}

private function clear()
{
$this->pool = null;
$this->histories = collect();
$this->firstPaymnetEntryRecordIds = collect();
$this->plans = collect();
$this->completePlans = collect();
}
}


class AttachStop extends Exception
{
}

+ 119
- 0
app/Logic/PoolTransferManager.php Просмотреть файл

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

namespace App\Logic;

use App\Exceptions\SkipException;
use App\Kintone\Models\DropDown\PoolTransferHistory\TransferMethod;
use App\Kintone\Models\DropDown\PoolTransferHistory\TransgerType;
use App\Kintone\Models\Pool;
use App\Kintone\Models\PoolTransferHistory;
use App\Kintone\Models\SmbcAccountTransferResult;
use App\Kintone\Models\SmbcPayment;
use App\Kintone\Models\YuchoPaymentResult;
use App\Util\DateUtil;

/**
* 各種支払いデータから入金プールへ異動する
*/
class PoolTransferManager
{

private SmbcPayment|SmbcAccountTransferResult|YuchoPaymentResult|null $payment = null;
private Pool|null $pool = null;
private PoolTransferHistory|null $history = null;


public function moveToPool(SmbcPayment|SmbcAccountTransferResult|YuchoPaymentResult $payment): Pool
{
$this->clear();

if (!$payment->customerCode) {
throw new SkipException(sprintf("顧客コード未割当 レコード番号:%d", $payment->getRecordId()));
}
$this->payment = $payment;

$this->getPool();

$this->setPoolDone();

$this->makeHistory();

$this->setPoolAmount();

$this->save();

return $this->pool;
}


private function getPool()
{
$access = Pool::getAccess();
$query = Pool::getQuery()->where(Pool::FIELD_CUSTOMER_CODE, $this->payment->customerCode);
$list = $access->some($query);
if ($list->isNotEmpty()) {
if ($list->count() !== 1) {
throw new SkipException(sprintf("データ不正 入金プール一意制約違反 顧客コード%d", $this->payment->customerCode));
}
$this->pool = $list->first();
return;
}
$pool = new Pool();
$pool->customerCode = $this->payment->customerCode;
$pool->poolAmount = 0;
$pool->save();

$this->pool = $pool;
}

private function makeHistory()
{
$history = new PoolTransferHistory();
$history->poolRecordNo = $this->pool->getRecordId();
$history->customerCode = $this->payment->customerCode;
$history->transferDatetime = DateUtil::now();
$history->transferType = TransgerType::INCOME;
$history->transferAmount = $this->payment->paymentAmount;
$history->poolAmountBefore = $this->pool->poolAmount;
$history->poolAmountAfter = $this->pool->poolAmount + $this->payment->paymentAmount;

if ($this->payment instanceof SmbcPayment) {
$history->incomeMethod = TransferMethod::CVS;
$history->incomeCvsPaymentRecordNo = $this->payment->getRecordId();
}
if ($this->payment instanceof SmbcAccountTransferResult) {
$history->incomeMethod = TransferMethod::ACCOUNT_TRANSFER;
$history->incomeAccountTransferResultRecordNo = $this->payment->getRecordId();
}
if ($this->payment instanceof YuchoPaymentResult) {
$history->incomeMethod = TransferMethod::YUCHO;
$history->incomeYuchoTransferRecordNo = $this->payment->getRecordId();
}

$this->history = $history;
}

private function setPoolDone()
{
$this->payment->poolDone = ["済"];
}

private function setPoolAmount()
{
$this->pool->poolAmount += $this->payment->paymentAmount;
}

private function save()
{
$this->history->save();
$this->pool->save();
$this->payment->save();
}

private function clear()
{
$this->payment = null;
$this->pool = null;
$this->history = null;
}
}

+ 21
- 1
app/Logic/ReceiptManager.php Просмотреть файл

@@ -22,6 +22,8 @@ class ReceiptManager
{
private ?Receipt $receipt = null;

private $paymentPlans = null;

public function __construct(?int $recordNo = null)
{
if ($recordNo) {
@@ -36,6 +38,12 @@ class ReceiptManager
return $this->receipt;
}

public function setPaymentPlans(Collection $paymentPlans)
{
$this->paymentPlans = $paymentPlans;
return $this;
}


public function create(array $paymentPlanRecordNoList)
{
@@ -67,7 +75,7 @@ class ReceiptManager
$detail->amount = $detail->unitPrice * $detail->quantity;
$detail->targetMonth = $payment->targetMonth ? sprintf("%d月分", $payment->targetMonth) : "";
$detail->taxRate = config("business.taxRate.normal", 0);
$detail->memo = "memo";
$detail->memo = $this->getMemoContents($payment);
$receipt->receiptDetail->push($detail);
$receipt->receiptTotalAmount += $payment->appropriationAmount;
}
@@ -112,6 +120,9 @@ class ReceiptManager

private function getPayments(array $paymentPlanRecordNoList)
{
if (!!$this->paymentPlans) {
return $this->paymentPlans;
}
$query = PaymentPlan::getQuery()->whereIn(PaymentPlan::FIELD_RECORD_NO, $paymentPlanRecordNoList);
$ret = PaymentPlan::getAccess()->all($query);

@@ -286,4 +297,13 @@ class ReceiptManager
}
throw new AppCommonException('申請番号取得失敗');
}

private function getMemoContents(PaymentPlan $plan): string
{
if ($plan->isPartialFee()) {
return "日割り分";
}

return "";
}
}

+ 15
- 0
app/Util/CollectionUtil.php Просмотреть файл

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

namespace App\Util;

use Illuminate\Support\Collection;

class CollectionUtil
{
public static function pushAll($base, $append)
{
foreach ($append as $ele) {
$base->push($ele);
}
}
}

+ 4
- 0
config/kintone.php Просмотреть файл

@@ -50,6 +50,10 @@ return [
...App\Kintone\Models\Ask::setConfig(),
...App\Kintone\Models\Receipt::setConfig(),
...App\Kintone\Models\SmbcPayment::setConfig(),
...App\Kintone\Models\SmbcAccountTransferResult::setConfig(),
...App\Kintone\Models\YuchoPaymentResult::setConfig(),
...App\Kintone\Models\Pool::setConfig(),
...App\Kintone\Models\PoolTransferHistory::setConfig(),
],

];

Загрузка…
Отмена
Сохранить