<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper">

    <resultMap type="com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement" id="CcdiBankStatementResult">
        <id     property="bankStatementId"    column="bank_statement_id"    />
        <result property="projectId"          column="project_id"           />
        <result property="leId"               column="LE_ID"                />
        <result property="accountId"          column="ACCOUNT_ID"           />
        <result property="groupId"            column="group_id"             />
        <result property="leAccountName"      column="LE_ACCOUNT_NAME"      />
        <result property="leAccountNo"        column="LE_ACCOUNT_NO"        />
        <result property="accountingDateId"   column="ACCOUNTING_DATE_ID"   />
        <result property="accountingDate"     column="ACCOUNTING_DATE"      />
        <result property="trxDate"            column="TRX_DATE"             />
        <result property="currency"           column="CURRENCY"             />
        <result property="amountDr"           column="AMOUNT_DR"            />
        <result property="amountCr"           column="AMOUNT_CR"            />
        <result property="amountBalance"      column="AMOUNT_BALANCE"       />
        <result property="cashType"           column="CASH_TYPE"            />
        <result property="customerLeId"       column="CUSTOMER_LE_ID"       />
        <result property="customerAccountName" column="CUSTOMER_ACCOUNT_NAME" />
        <result property="customerAccountNo"  column="CUSTOMER_ACCOUNT_NO"  />
        <result property="customerBank"       column="customer_bank"        />
        <result property="customerReference"  column="customer_reference"   />
        <result property="customerCertNo" column="customer_cert_no" />
        <result property="customerSocialCreditCode" column="customer_social_credit_code" />
        <result property="userMemo"           column="USER_MEMO"            />
        <result property="bankComments"       column="BANK_COMMENTS"        />
        <result property="bankTrxNumber"      column="BANK_TRX_NUMBER"      />
        <result property="bank"               column="BANK"                 />
        <result property="trxFlag"            column="TRX_FLAG"             />
        <result property="trxType"            column="TRX_TYPE"             />
        <result property="exceptionType"      column="EXCEPTION_TYPE"       />
        <result property="internalFlag"       column="internal_flag"        />
        <result property="batchId"            column="batch_id"             />
        <result property="batchSequence"      column="batch_sequence"       />
        <result property="createDate"         column="CREATE_DATE"          />
        <result property="createdBy"          column="created_by"           />
        <result property="metaJson"           column="meta_json"            />
        <result property="noBalance"          column="no_balance"           />
        <result property="beginBalance"       column="begin_balance"        />
        <result property="endBalance"         column="end_balance"          />
        <result property="overrideBsId"       column="override_bs_id"       />
        <result property="paymentMethod"      column="payment_method"       />
        <result property="cretNo"             column="cret_no"              />
    </resultMap>

    <sql id="selectCcdiBankStatementVo">
        bank_statement_id, project_id, LE_ID, ACCOUNT_ID, group_id,
        LE_ACCOUNT_NAME, LE_ACCOUNT_NO, ACCOUNTING_DATE_ID, ACCOUNTING_DATE,
        TRX_DATE, CURRENCY, AMOUNT_DR, AMOUNT_CR, AMOUNT_BALANCE,
        CASH_TYPE, CUSTOMER_LE_ID, CUSTOMER_ACCOUNT_NAME, CUSTOMER_ACCOUNT_NO,
        customer_bank, customer_reference, customer_cert_no, customer_social_credit_code, USER_MEMO, BANK_COMMENTS,
        BANK_TRX_NUMBER, BANK, TRX_FLAG, TRX_TYPE, EXCEPTION_TYPE,
        internal_flag, batch_id, batch_sequence, CREATE_DATE, created_by,
        meta_json, no_balance, begin_balance, end_balance,
        override_bs_id, payment_method, cret_no
    </sql>

    <resultMap id="CcdiBankStatementListVOResultMap" type="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO">
        <id property="bankStatementId" column="bankStatementId"/>
        <result property="trxDate" column="trxDate"/>
        <result property="leAccountNo" column="leAccountNo"/>
        <result property="leAccountName" column="leAccountName"/>
        <result property="customerAccountName" column="customerAccountName"/>
        <result property="customerAccountNo" column="customerAccountNo"/>
        <result property="userMemo" column="userMemo"/>
        <result property="cashType" column="cashType"/>
        <result property="displayAmount" column="displayAmount"/>
    </resultMap>

    <resultMap id="CcdiBankStatementDetailVOResultMap" type="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementDetailVO">
        <id property="bankStatementId" column="bankStatementId"/>
        <result property="projectId" column="projectId"/>
        <result property="trxDate" column="trxDate"/>
        <result property="currency" column="currency"/>
        <result property="leAccountNo" column="leAccountNo"/>
        <result property="leAccountName" column="leAccountName"/>
        <result property="customerAccountName" column="customerAccountName"/>
        <result property="customerAccountNo" column="customerAccountNo"/>
        <result property="customerBank" column="customerBank"/>
        <result property="customerReference" column="customerReference"/>
        <result property="userMemo" column="userMemo"/>
        <result property="bankComments" column="bankComments"/>
        <result property="bankTrxNumber" column="bankTrxNumber"/>
        <result property="bank" column="bank"/>
        <result property="cashType" column="cashType"/>
        <result property="amountDr" column="amountDr"/>
        <result property="amountCr" column="amountCr"/>
        <result property="amountBalance" column="amountBalance"/>
        <result property="displayAmount" column="displayAmount"/>
        <result property="trxFlag" column="trxFlag"/>
        <result property="trxType" column="trxType"/>
        <result property="exceptionType" column="exceptionType"/>
        <result property="internalFlag" column="internalFlag"/>
        <result property="paymentMethod" column="paymentMethod"/>
        <result property="cretNo" column="cretNo"/>
        <result property="createDate" column="createDate"/>
        <result property="originalFileName" column="originalFileName"/>
        <result property="uploadTime" column="uploadTime"/>
    </resultMap>

    <resultMap id="CcdiBankStatementFilterOptionsVOResultMap"
               type="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementFilterOptionsVO">
        <collection property="ourSubjectOptions"
                    column="{projectId=project_id}"
                    select="selectOurSubjectOptions"/>
        <collection property="ourBankOptions"
                    column="{projectId=project_id}"
                    select="selectOurBankOptions"/>
        <collection property="ourAccountOptions"
                    column="{projectId=project_id}"
                    select="selectOurAccountOptions"/>
    </resultMap>

    <select id="countMatchedStaffCountByProjectId" resultType="java.lang.Integer">
        select count(distinct trim(bs.cret_no))
        from ccdi_bank_statement bs
        inner join ccdi_base_staff staff on staff.id_card = bs.cret_no
        where bs.project_id = #{projectId}
          and bs.cret_no is not null
          and trim(bs.cret_no) != ''
    </select>

    <sql id="parsedTrxDateExpr">
        CASE
            WHEN bs.TRX_DATE IS NULL OR TRIM(bs.TRX_DATE) = '' THEN NULL
            WHEN LENGTH(TRIM(bs.TRX_DATE)) = 10 THEN STR_TO_DATE(CONCAT(TRIM(bs.TRX_DATE), ' 00:00:00'), '%Y-%m-%d %H:%i:%s')
            ELSE STR_TO_DATE(TRIM(bs.TRX_DATE), '%Y-%m-%d %H:%i:%s')
        END
    </sql>

    <sql id="displayAmountExpr">
        CASE
            WHEN IFNULL(bs.AMOUNT_CR, 0) > 0 THEN IFNULL(bs.AMOUNT_CR, 0)
            ELSE 0 - IFNULL(bs.AMOUNT_DR, 0)
        END
    </sql>

    <sql id="absoluteAmountExpr">
        CASE
            WHEN IFNULL(bs.AMOUNT_CR, 0) > 0 THEN IFNULL(bs.AMOUNT_CR, 0)
            ELSE IFNULL(bs.AMOUNT_DR, 0)
        END
    </sql>

    <sql id="statementListColumns">
        bs.bank_statement_id AS bankStatementId,
        bs.TRX_DATE AS trxDate,
        bs.LE_ACCOUNT_NO AS leAccountNo,
        bs.LE_ACCOUNT_NAME AS leAccountName,
        bs.CUSTOMER_ACCOUNT_NAME AS customerAccountName,
        bs.CUSTOMER_ACCOUNT_NO AS customerAccountNo,
        bs.USER_MEMO AS userMemo,
        bs.CASH_TYPE AS cashType,
        <include refid="displayAmountExpr"/> AS displayAmount
    </sql>

    <sql id="statementFilterWhere">
        AND (bs.project_id = #{query.projectId})
        <if test="query.tabType == 'in'">
            AND IFNULL(bs.AMOUNT_CR, 0) > 0
        </if>
        <if test="query.tabType == 'out'">
            AND IFNULL(bs.AMOUNT_DR, 0) > 0
        </if>
        <if test="query.transactionStartTime != null and query.transactionStartTime != ''">
            AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ >= ]]>
            CASE
                WHEN LENGTH(TRIM(#{query.transactionStartTime})) = 10
                    THEN STR_TO_DATE(CONCAT(TRIM(#{query.transactionStartTime}), ' 00:00:00'), '%Y-%m-%d %H:%i:%s')
                ELSE STR_TO_DATE(TRIM(#{query.transactionStartTime}), '%Y-%m-%d %H:%i:%s')
            END
        </if>
        <if test="query.transactionEndTime != null and query.transactionEndTime != ''">
            AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ <= ]]>
            CASE
                WHEN LENGTH(TRIM(#{query.transactionEndTime})) = 10
                    THEN STR_TO_DATE(CONCAT(TRIM(#{query.transactionEndTime}), ' 23:59:59'), '%Y-%m-%d %H:%i:%s')
                ELSE STR_TO_DATE(TRIM(#{query.transactionEndTime}), '%Y-%m-%d %H:%i:%s')
            END
        </if>
        <if test="(query.counterpartyName != null and query.counterpartyName != '') or query.counterpartyNameEmpty">
            AND (
                <if test="query.counterpartyName != null and query.counterpartyName != ''">
                    bs.CUSTOMER_ACCOUNT_NAME LIKE CONCAT('%', TRIM(#{query.counterpartyName}), '%')
                </if>
                <if test="query.counterpartyName != null and query.counterpartyName != '' and query.counterpartyNameEmpty">
                    OR
                </if>
                <if test="query.counterpartyNameEmpty">
                    bs.CUSTOMER_ACCOUNT_NAME IS NULL OR TRIM(bs.CUSTOMER_ACCOUNT_NAME) = ''
                </if>
            )
        </if>
        <if test="(query.userMemo != null and query.userMemo != '') or query.userMemoEmpty">
            AND (
                <if test="query.userMemo != null and query.userMemo != ''">
                    bs.USER_MEMO LIKE CONCAT('%', TRIM(#{query.userMemo}), '%')
                </if>
                <if test="query.userMemo != null and query.userMemo != '' and query.userMemoEmpty">
                    OR
                </if>
                <if test="query.userMemoEmpty">
                    bs.USER_MEMO IS NULL OR TRIM(bs.USER_MEMO) = ''
                </if>
            )
        </if>
        <if test="query.ourSubjects != null and query.ourSubjects.size() > 0">
            AND bs.LE_ACCOUNT_NAME IN
            <foreach collection="query.ourSubjects" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
        <if test="query.ourCertNos != null and query.ourCertNos.size() > 0">
            AND bs.cret_no IN
            <foreach collection="query.ourCertNos" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
        <if test="query.ourBanks != null and query.ourBanks.size() > 0">
            AND bs.BANK IN
            <foreach collection="query.ourBanks" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
        <if test="query.ourAccounts != null and query.ourAccounts.size() > 0">
            AND bs.LE_ACCOUNT_NO IN
            <foreach collection="query.ourAccounts" item="item" open="(" separator="," close=")">
                #{item}
            </foreach>
        </if>
        <if test="query.amountMin != null">
            AND (<include refid="absoluteAmountExpr"/>) <![CDATA[ >= ]]> #{query.amountMin}
        </if>
        <if test="query.amountMax != null">
            AND (<include refid="absoluteAmountExpr"/>) <![CDATA[ <= ]]> #{query.amountMax}
        </if>
        <if test="(query.counterpartyAccount != null and query.counterpartyAccount != '') or query.counterpartyAccountEmpty">
            AND (
                <if test="query.counterpartyAccount != null and query.counterpartyAccount != ''">
                    bs.CUSTOMER_ACCOUNT_NO LIKE CONCAT('%', TRIM(#{query.counterpartyAccount}), '%')
                </if>
                <if test="query.counterpartyAccount != null and query.counterpartyAccount != '' and query.counterpartyAccountEmpty">
                    OR
                </if>
                <if test="query.counterpartyAccountEmpty">
                    bs.CUSTOMER_ACCOUNT_NO IS NULL OR TRIM(bs.CUSTOMER_ACCOUNT_NO) = ''
                </if>
            )
        </if>
        <if test="(query.transactionType != null and query.transactionType != '') or query.transactionTypeEmpty">
            AND (
                <if test="query.transactionType != null and query.transactionType != ''">
                    bs.CASH_TYPE LIKE CONCAT('%', TRIM(#{query.transactionType}), '%')
                </if>
                <if test="query.transactionType != null and query.transactionType != '' and query.transactionTypeEmpty">
                    OR
                </if>
                <if test="query.transactionTypeEmpty">
                    bs.CASH_TYPE IS NULL OR TRIM(bs.CASH_TYPE) = ''
                </if>
            )
        </if>
    </sql>

    <sql id="statementOrderBy">
        <choose>
            <when test="query.orderBy == 'amount' and query.orderDirection == 'asc'">
                ORDER BY <include refid="absoluteAmountExpr"/> ASC, bs.bank_statement_id ASC
            </when>
            <when test="query.orderBy == 'amount' and query.orderDirection == 'desc'">
                ORDER BY <include refid="absoluteAmountExpr"/> DESC, bs.bank_statement_id DESC
            </when>
            <when test="query.orderDirection == 'asc'">
                ORDER BY <include refid="parsedTrxDateExpr"/> ASC, bs.bank_statement_id ASC
            </when>
            <otherwise>
                ORDER BY <include refid="parsedTrxDateExpr"/> DESC, bs.bank_statement_id DESC
            </otherwise>
        </choose>
    </sql>

    <select id="selectStatementPage" resultMap="CcdiBankStatementListVOResultMap">
        SELECT
        <include refid="statementListColumns"/>
        FROM ccdi_bank_statement bs
        <where>
            <include refid="statementFilterWhere"/>
        </where>
        <include refid="statementOrderBy"/>
    </select>

    <select id="selectStatementListForExport" resultMap="CcdiBankStatementListVOResultMap">
        SELECT
        <include refid="statementListColumns"/>
        FROM ccdi_bank_statement bs
        <where>
            <include refid="statementFilterWhere"/>
        </where>
        <include refid="statementOrderBy"/>
    </select>

    <select id="selectStatementsForHistoryImport" resultMap="CcdiBankStatementResult">
        SELECT
        <include refid="selectCcdiBankStatementVo"/>
        FROM ccdi_bank_statement bs
        <where>
            (bs.project_id = #{projectId})
            AND (bs.batch_id = #{batchId})
            <if test="startDate != null and startDate != ''">
                AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ >= ]]>
                CASE
                    WHEN LENGTH(TRIM(#{startDate})) = 10
                        THEN STR_TO_DATE(CONCAT(TRIM(#{startDate}), ' 00:00:00'), '%Y-%m-%d %H:%i:%s')
                    ELSE STR_TO_DATE(TRIM(#{startDate}), '%Y-%m-%d %H:%i:%s')
                END
            </if>
            <if test="endDate != null and endDate != ''">
                AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ <= ]]>
                CASE
                    WHEN LENGTH(TRIM(#{endDate})) = 10
                        THEN STR_TO_DATE(CONCAT(TRIM(#{endDate}), ' 23:59:59'), '%Y-%m-%d %H:%i:%s')
                    ELSE STR_TO_DATE(TRIM(#{endDate}), '%Y-%m-%d %H:%i:%s')
                END
            </if>
        </where>
        ORDER BY bs.batch_sequence ASC, bs.bank_statement_id ASC
    </select>

    <select id="selectStatementDetailById" resultMap="CcdiBankStatementDetailVOResultMap">
        SELECT
            bs.bank_statement_id AS bankStatementId,
            bs.project_id AS projectId,
            bs.TRX_DATE AS trxDate,
            bs.CURRENCY AS currency,
            bs.LE_ACCOUNT_NO AS leAccountNo,
            bs.LE_ACCOUNT_NAME AS leAccountName,
            bs.CUSTOMER_ACCOUNT_NAME AS customerAccountName,
            bs.CUSTOMER_ACCOUNT_NO AS customerAccountNo,
            bs.customer_bank AS customerBank,
            bs.customer_reference AS customerReference,
            bs.USER_MEMO AS userMemo,
            bs.BANK_COMMENTS AS bankComments,
            bs.BANK_TRX_NUMBER AS bankTrxNumber,
            bs.BANK AS bank,
            bs.CASH_TYPE AS cashType,
            bs.AMOUNT_DR AS amountDr,
            bs.AMOUNT_CR AS amountCr,
            bs.AMOUNT_BALANCE AS amountBalance,
            <include refid="displayAmountExpr"/> AS displayAmount,
            bs.TRX_FLAG AS trxFlag,
            bs.TRX_TYPE AS trxType,
            bs.EXCEPTION_TYPE AS exceptionType,
            bs.internal_flag AS internalFlag,
            bs.payment_method AS paymentMethod,
            bs.cret_no AS cretNo,
            bs.CREATE_DATE AS createDate,
            fur.file_name AS originalFileName,
            fur.upload_time AS uploadTime,
            fur.source_project_name AS sourceProjectName
        FROM ccdi_bank_statement bs
        LEFT JOIN (
            SELECT latest_record.project_id, latest_record.log_id, latest_record.file_name, latest_record.upload_time,
                   latest_record.source_project_name
            FROM ccdi_file_upload_record latest_record
            INNER JOIN (
                SELECT project_id, log_id, MAX(id) AS max_id
                FROM ccdi_file_upload_record
                GROUP BY project_id, log_id
            ) latest_meta ON latest_meta.max_id = latest_record.id
        ) fur ON fur.log_id = bs.batch_id AND fur.project_id = bs.project_id
        WHERE bs.bank_statement_id = #{bankStatementId}
    </select>

    <select id="selectFilterOptions" resultMap="CcdiBankStatementFilterOptionsVOResultMap">
        SELECT #{projectId} AS project_id
    </select>

    <select id="selectOurSubjectOptions" resultType="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementOptionVO">
        SELECT DISTINCT
            TRIM(bs.LE_ACCOUNT_NAME) AS label,
            TRIM(bs.LE_ACCOUNT_NAME) AS value
        FROM ccdi_bank_statement bs
        WHERE bs.project_id = #{projectId}
          AND bs.LE_ACCOUNT_NAME IS NOT NULL
          AND TRIM(bs.LE_ACCOUNT_NAME) != ''
        ORDER BY TRIM(bs.LE_ACCOUNT_NAME)
    </select>

    <select id="selectOurBankOptions" resultType="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementOptionVO">
        SELECT DISTINCT
            TRIM(bs.BANK) AS label,
            TRIM(bs.BANK) AS value
        FROM ccdi_bank_statement bs
        WHERE bs.project_id = #{projectId}
          AND bs.BANK IS NOT NULL
          AND TRIM(bs.BANK) != ''
        ORDER BY TRIM(bs.BANK)
    </select>

    <select id="selectOurAccountOptions" resultType="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementOptionVO">
        SELECT DISTINCT
            TRIM(bs.LE_ACCOUNT_NO) AS label,
            TRIM(bs.LE_ACCOUNT_NO) AS value
        FROM ccdi_bank_statement bs
        WHERE bs.project_id = #{projectId}
          AND bs.LE_ACCOUNT_NO IS NOT NULL
          AND TRIM(bs.LE_ACCOUNT_NO) != ''
        ORDER BY TRIM(bs.LE_ACCOUNT_NO)
    </select>

    <insert id="insertBatch" parameterType="java.util.List">
        insert into ccdi_bank_statement (
            project_id, LE_ID, ACCOUNT_ID, group_id,
            LE_ACCOUNT_NAME, LE_ACCOUNT_NO, ACCOUNTING_DATE_ID, ACCOUNTING_DATE,
            TRX_DATE, CURRENCY, AMOUNT_DR, AMOUNT_CR, AMOUNT_BALANCE,
            CASH_TYPE, CUSTOMER_LE_ID, CUSTOMER_ACCOUNT_NAME, CUSTOMER_ACCOUNT_NO,
            customer_bank, customer_reference, customer_cert_no, customer_social_credit_code, USER_MEMO, BANK_COMMENTS,
            BANK_TRX_NUMBER, BANK, TRX_FLAG, TRX_TYPE, EXCEPTION_TYPE,
            internal_flag, batch_id, batch_sequence, CREATE_DATE, created_by,
            meta_json, no_balance, begin_balance, end_balance,
            override_bs_id, payment_method, cret_no
        ) values
        <foreach collection="list" item="item" separator=",">
            (
                #{item.projectId}, #{item.leId}, #{item.accountId}, #{item.groupId},
                #{item.leAccountName}, #{item.leAccountNo}, #{item.accountingDateId}, #{item.accountingDate},
                #{item.trxDate}, #{item.currency}, #{item.amountDr}, #{item.amountCr}, #{item.amountBalance},
                #{item.cashType}, #{item.customerLeId}, #{item.customerAccountName}, #{item.customerAccountNo},
                #{item.customerBank}, #{item.customerReference}, #{item.customerCertNo}, #{item.customerSocialCreditCode}, #{item.userMemo}, #{item.bankComments},
                #{item.bankTrxNumber}, #{item.bank}, #{item.trxFlag}, #{item.trxType}, #{item.exceptionType},
                #{item.internalFlag}, #{item.batchId}, #{item.batchSequence}, #{item.createDate}, #{item.createdBy},
                #{item.metaJson}, #{item.noBalance}, #{item.beginBalance}, #{item.endBalance},
                #{item.overrideBsId}, #{item.paymentMethod}, #{item.cretNo}
            )
        </foreach>
        on duplicate key update
            batch_id = batch_id
    </insert>

    <delete id="deleteByProjectIdAndBatchId">
        delete from ccdi_bank_statement
        where project_id = #{projectId}
          and batch_id = #{batchId}
    </delete>

</mapper>
