<?php
namespace App\Model\Logic;
use App\Common\Constants as C;
use App\Common\Functions as F;
//TODO:関数の並べ替え。関数の概要
class ReceiptsLogic {
// const COLUMNS = ['m_accounts_physical_name', 'price', 'tax', 'rate', 'summary'];
public static function getKeyValueArr(object $pMasterObj): array {
$selectedMasterObj = $pMasterObj->select([C::ID, C::LOGICAL_NAME]);
$keyValueArr = array();
// $keyValueArr = ['' => C::HYPHEN];
foreach ($selectedMasterObj as $value) {
$keyValueArr[$value[C::ID]] = $value[C::LOGICAL_NAME];
}
return $keyValueArr;
}
public static function getTaxTypeArr(): array {
return [C::S0 => '非課税', C::S1 => '内税', C::S2 => '外税'];
}
static function getRateArr(): array {
return [C::S0 => C::S0, C::S8 => C::S8, C::S1 . C::S0 => C::S1 . C::S0];
}
static function getNumOfRows(): int {
return C::NUM_OF_ROWS;
}
public static function getFormat(): string {
return F::getFormat(C::NUM_OF_ROWS);
}
public static function getYearArr(): array {
$thisYear = date('y');
$lastYear = strval(intval($thisYear) - C::I1);
return [$thisYear => $thisYear, $lastYear => $lastYear];
}
public static function getMonthArr(): array {
return self::getNumberArr(12);
}
public static function getThisMonth(): string {
return sprintf('%02d', date('m'));
}
public static function getDayArr(): array {
return self::getNumberArr(31);
}
public static function getThisDay(): string {
return sprintf('%02d', date('d'));//TODO:'d'の定数化
}
public static function validateData(array $pData): array {
return self::priValidateData($pData);
}
// 以下privateメソッド ----------------------------------------
private static function getNumberArr(int $pLastNumber): array {
$numberArr = array();
for ($i = C::I1; $i <= $pLastNumber; $i++) {
$formatted = sprintf(F::getFormat($pLastNumber), $i);
$numberArr[$formatted] = $formatted;
}
return $numberArr;
}
private static function priValidateData(array $pData): array {
$errorMessage = null;
if (!checkdate(intval($pData['month']), intval($pData['day']), intval('20' . $pData['year']))) {
// 日付に不備がある場合
$errorMessage = '日付が不正';
}
if (2 === intval($pData['tax_type']) && intval($pData['receipt_total']) <= C::I0) {
// レシート合計が入力されていない場合
$errorMessage = F::apndMsg_($errorMessage, 'レシート合計' . C::GA . C::MI . C::NYURYOKU);
}
$validatedLine = self::validateRow($pData);
if (isset($validatedLine[C::ERROR_MESSAGE])) {
// 明細行に不備がある場合
$errorMessage = F::apndMsg_($errorMessage, $validatedLine[C::ERROR_MESSAGE]);
}
$validatedLine[C::ERROR_MESSAGE] = $errorMessage;
return $validatedLine;
}
//TODO:戻り値の型の変更検討
/**
* 「レシート追加」ページの明細行の各項目が入力、または、選択されているか否かをチェックする
*
* @param $pRequest
* @return [エラーメッセージ, チェックをパスした行]の配列(チェックをパスした行が二次元配列のため、戻り値は三次元配列)
*/
private static function validateRow(array $pData): array {
$priceIArr = array(); // 価格
$priceRArr = array();
$taxRArr = array(); // 税額
$taxIArr = array(); // 税額
$empRowCtrIArr = array(); // 空行カウンタ
$rowMsgArr = array(); // エラーメッセージ
$rateRArr = array();
$totalPriceR = '0.00';
$totalTaxX100I = C::S0;
$sum0I = C::S0;
$sum8I = C::S0;
$sum10I = C::S0;
for ($i = C::I0; $i < C::NUM_OF_ROWS; $i++) {
$formatted = sprintf(self::getFormat(), $i);
$colMsgArr = array();
// 勘定科目
if (empty($pData[C::M_ACCOUNTS_ID_ . $formatted])) {
$colMsgArr[0] = C::KANJOKAMOKU . C::GA . C::MI . C::SENTAKU;
}
// 価格
$priceI = $pData[C::PRICE_ . $formatted];
if (! is_numeric($priceI)) {
$colMsgArr[1] = C::KAKAKU . C::GA . C::MI . C::NYURYOKU;
// } else {
// $priceIArr[] = intval($priceI);
// $priceRArr[] = floatval($priceI);
}
// 税率
$rateI = $pData[C::RATE_ . $formatted];
if (! is_numeric($rateI)) {
$colMsgArr[2] = C::ZEIRITSU . C::GA . C::MI . C::SENTAKU;
}
// 備考
$isSumEmpty = C::I0 === strlen(strval($pData[C::SUMMARY_ . $formatted]));
$errCnt = count($colMsgArr);
if (3 === $errCnt && $isSumEmpty) {
// (外税かつ科目価格税率が未選択未入力、または、外税以外かつ科目価格税額税率が未選択未入力)、かつ、備考が未入力の場合
$empRowCtrIArr[] = 1;
} elseif (0 < $errCnt) {
// 現在の明細行のいずれかの列に不備がない場合
$rowMsgArr[] = C::NUMERO_SIGN . strval($i + C::I1) . 'の' . implode(C::TOTEN, $colMsgArr);
} else /*if (is_numeric($priceI) && is_numeric($rateI))*/ {
// 現在の明細行に不備がない場合
$totalPriceR = bcadd($totalPriceR, $priceI, 2);
if (C::I0 === strcmp(C::S2, $pData['tax_type'])) {
// 消費税が外税の場合
$taxX100I = bcmul($priceI, $rateI);
$totalTaxX100I = bcadd($totalTaxX100I, $taxX100I);
$taxRArr[] = bcdiv($taxX100I, '100', 2);
$taxIArr[$formatted] = bcdiv($taxX100I, '100');
switch ($rateI) {
case '0':
$sum0I = bcadd($sum0I, $priceI);
break;
case '8':
$sum8I = bcadd($sum8I, $priceI);
break;
case '10':
$sum10I = bcadd($sum10I, $priceI);
break;
default:
break;
}
}
}
}
$totalTaxR = null;
$errorMessage = null;
if (C::NUM_OF_ROWS === count($empRowCtrIArr)) {
// 行数と空行数が同じ(明細が一行も入力されていない)場合、その旨をエラーメッセージに設定する
$errorMessage = '明細が一行も' . C::NYURYOKU . 'されていない';//TODO:定数化検討
} elseif (C::I0 < count($rowMsgArr)) {
$errorMessage = implode('<br>', $rowMsgArr);
} elseif (C::I0 === strcmp(C::S2, $pData['tax_type'])) {
// 消費税が外税の場合
$totalTaxR = bcdiv($totalTaxX100I, '100', 2);
$totalPriceIncludingTaxR = bcadd($totalPriceR, $totalTaxR, 2);
$diffR = bcsub($pData['receipt_total'], $totalPriceIncludingTaxR, 2);
if (C::I0 !== strcmp('0.00', $diffR)) {
$errorMessage = '価格合計と税額合計の和がレシート合計と等しくない';
}
}
//
return [
C::ERROR_MESSAGE => $errorMessage,
'totalPrice' => F::getIntPart($totalPriceR),
'totalTax' => F::getIntPart($totalTaxR),
'taxArr' => $taxIArr
];
}
private static function hogeMethod(array $pTaxRArr) {
}
}