<?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) {

 

    }




 

}