<?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.xzzn.ems.mapper.EmsDailyEnergyDataMapper">

    <resultMap type="EmsDailyEnergyData" id="EmsDailyEnergyDataResult">
        <result property="id"    column="id"    />
        <result property="siteId"    column="site_id"    />
        <result property="dataDate"    column="data_date"    />
        <result property="dataHour"    column="data_hour"    />
        <result property="peakChargeDiff"    column="peak_charge_diff"    />
        <result property="peakDischargeDiff"    column="peak_discharge_diff"    />
        <result property="highChargeDiff"    column="high_charge_diff"    />
        <result property="highDischargeDiff"    column="high_discharge_diff"    />
        <result property="flatChargeDiff"    column="flat_charge_diff"    />
        <result property="flatDischargeDiff"    column="flat_discharge_diff"    />
        <result property="valleyChargeDiff"    column="valley_charge_diff"    />
        <result property="valleyDischargeDiff"    column="valley_discharge_diff"    />
        <result property="calcTime"    column="calc_time"    />
        <result property="createBy"    column="create_by"    />
        <result property="createTime"    column="create_time"    />
        <result property="updateBy"    column="update_by"    />
        <result property="updateTime"    column="update_time"    />
        <result property="remark"    column="remark"    />
    </resultMap>

    <sql id="selectEmsDailyEnergyDataVo">
        select id, site_id, data_date, data_hour,
               peak_charge_diff, peak_discharge_diff, high_charge_diff, high_discharge_diff,
               flat_charge_diff, flat_discharge_diff, valley_charge_diff, valley_discharge_diff,
               calc_time, create_by, create_time, update_by, update_time, remark
        from ems_daily_energy_data
    </sql>

    <select id="selectEmsDailyEnergyDataList" parameterType="EmsDailyEnergyData" resultMap="EmsDailyEnergyDataResult">
        <include refid="selectEmsDailyEnergyDataVo"/>
        <where>
            <if test="siteId != null  and siteId != ''"> and site_id = #{siteId}</if>
            <if test="dataDate != null "> and data_date = #{dataDate}</if>
            <if test="dataHour != null "> and data_hour = #{dataHour}</if>
            <if test="peakChargeDiff != null "> and peak_charge_diff = #{peakChargeDiff}</if>
            <if test="peakDischargeDiff != null "> and peak_discharge_diff = #{peakDischargeDiff}</if>
            <if test="highChargeDiff != null "> and high_charge_diff = #{highChargeDiff}</if>
            <if test="highDischargeDiff != null "> and high_discharge_diff = #{highDischargeDiff}</if>
            <if test="flatChargeDiff != null "> and flat_charge_diff = #{flatChargeDiff}</if>
            <if test="flatDischargeDiff != null "> and flat_discharge_diff = #{flatDischargeDiff}</if>
            <if test="valleyChargeDiff != null "> and valley_charge_diff = #{valleyChargeDiff}</if>
            <if test="valleyDischargeDiff != null "> and valley_discharge_diff = #{valleyDischargeDiff}</if>
            <if test="calcTime != null "> and calc_time = #{calcTime}</if>
        </where>
        order by data_date desc, calc_time desc, id desc
    </select>

    <select id="selectEmsDailyEnergyDataById" parameterType="Long" resultMap="EmsDailyEnergyDataResult">
        <include refid="selectEmsDailyEnergyDataVo"/>
        where id = #{id}
    </select>

    <insert id="insertEmsDailyEnergyData" parameterType="EmsDailyEnergyData" useGeneratedKeys="true" keyProperty="id">
        insert into ems_daily_energy_data
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="siteId != null">site_id,</if>
            <if test="dataDate != null">data_date,</if>
            <if test="dataHour != null">data_hour,</if>
            <if test="peakChargeDiff != null">peak_charge_diff,</if>
            <if test="peakDischargeDiff != null">peak_discharge_diff,</if>
            <if test="highChargeDiff != null">high_charge_diff,</if>
            <if test="highDischargeDiff != null">high_discharge_diff,</if>
            <if test="flatChargeDiff != null">flat_charge_diff,</if>
            <if test="flatDischargeDiff != null">flat_discharge_diff,</if>
            <if test="valleyChargeDiff != null">valley_charge_diff,</if>
            <if test="valleyDischargeDiff != null">valley_discharge_diff,</if>
            <if test="calcTime != null">calc_time,</if>
            <if test="createBy != null">create_by,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="remark != null">remark,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="siteId != null">#{siteId},</if>
            <if test="dataDate != null">#{dataDate},</if>
            <if test="dataHour != null">#{dataHour},</if>
            <if test="peakChargeDiff != null">#{peakChargeDiff},</if>
            <if test="peakDischargeDiff != null">#{peakDischargeDiff},</if>
            <if test="highChargeDiff != null">#{highChargeDiff},</if>
            <if test="highDischargeDiff != null">#{highDischargeDiff},</if>
            <if test="flatChargeDiff != null">#{flatChargeDiff},</if>
            <if test="flatDischargeDiff != null">#{flatDischargeDiff},</if>
            <if test="valleyChargeDiff != null">#{valleyChargeDiff},</if>
            <if test="valleyDischargeDiff != null">#{valleyDischargeDiff},</if>
            <if test="calcTime != null">#{calcTime},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="remark != null">#{remark},</if>
        </trim>
    </insert>

    <update id="updateEmsDailyEnergyData" parameterType="EmsDailyEnergyData">
        update ems_daily_energy_data
        <trim prefix="SET" suffixOverrides=",">
            <if test="siteId != null">site_id = #{siteId},</if>
            <if test="dataDate != null">data_date = #{dataDate},</if>
            <if test="dataHour != null">data_hour = #{dataHour},</if>
            <if test="peakChargeDiff != null">peak_charge_diff = #{peakChargeDiff},</if>
            <if test="peakDischargeDiff != null">peak_discharge_diff = #{peakDischargeDiff},</if>
            <if test="highChargeDiff != null">high_charge_diff = #{highChargeDiff},</if>
            <if test="highDischargeDiff != null">high_discharge_diff = #{highDischargeDiff},</if>
            <if test="flatChargeDiff != null">flat_charge_diff = #{flatChargeDiff},</if>
            <if test="flatDischargeDiff != null">flat_discharge_diff = #{flatDischargeDiff},</if>
            <if test="valleyChargeDiff != null">valley_charge_diff = #{valleyChargeDiff},</if>
            <if test="valleyDischargeDiff != null">valley_discharge_diff = #{valleyDischargeDiff},</if>
            <if test="calcTime != null">calc_time = #{calcTime},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="remark != null">remark = #{remark},</if>
        </trim>
        where id = #{id}
    </update>

    <delete id="deleteEmsDailyEnergyDataById" parameterType="Long">
        delete from ems_daily_energy_data where id = #{id}
    </delete>

    <delete id="deleteEmsDailyEnergyDataByIds" parameterType="String">
        delete from ems_daily_energy_data where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

    <select id="getDataByDate" parameterType="String" resultMap="EmsDailyEnergyDataResult">
        <include refid="selectEmsDailyEnergyDataVo"/>
        where data_date = #{today}
        AND site_id = #{siteId}
        AND data_hour IS NULL
    </select>

    <select id="selectBySiteIdAndDateHour" resultMap="EmsDailyEnergyDataResult">
        <include refid="selectEmsDailyEnergyDataVo"/>
        where site_id = #{siteId}
          and data_date = DATE(#{dataDate})
          and data_hour = #{dataHour}
        limit 1
    </select>

    <insert id="insertOrUpdateData" parameterType="com.xzzn.ems.domain.EmsDailyEnergyData"
            useGeneratedKeys="true" keyProperty="id">
        INSERT INTO ems_daily_energy_data (
            id, site_id, data_date,
        <if test="dataHour != null">data_hour,</if>
        <if test="peakChargeDiff != null">peak_charge_diff,</if>
        <if test="peakDischargeDiff != null">peak_discharge_diff,</if>
        <if test="highChargeDiff != null">high_charge_diff,</if>
        <if test="highDischargeDiff != null">high_discharge_diff,</if>
        <if test="flatChargeDiff != null">flat_charge_diff,</if>
        <if test="flatDischargeDiff != null">flat_discharge_diff,</if>
        <if test="valleyChargeDiff != null">valley_charge_diff,</if>
        <if test="valleyDischargeDiff != null">valley_discharge_diff,</if>
            calc_time,
            create_by,
            create_time,
            update_by,
            update_time,
            remark
        ) VALUES (
                     #{id},
                     #{siteId},
                     #{dataDate},
        <if test="dataHour != null">#{dataHour},</if>
        <if test="peakChargeDiff != null">#{peakChargeDiff},</if>
        <if test="peakDischargeDiff != null">#{peakDischargeDiff},</if>
        <if test="highChargeDiff != null">#{highChargeDiff},</if>
        <if test="highDischargeDiff != null">#{highDischargeDiff},</if>
        <if test="flatChargeDiff != null">#{flatChargeDiff},</if>
        <if test="flatDischargeDiff != null">#{flatDischargeDiff},</if>
        <if test="valleyChargeDiff != null">#{valleyChargeDiff},</if>
        <if test="valleyDischargeDiff != null">#{valleyDischargeDiff},</if>
                     #{calcTime},
                     'system',
                     NOW(),
                     'system',
                     NOW(),
                     #{remark}
                 ) ON DUPLICATE KEY UPDATE
            <if test="dataHour != null">data_hour = #{dataHour},</if>
            <if test="peakChargeDiff != null">peak_charge_diff = #{peakChargeDiff},</if>
            <if test="peakDischargeDiff != null">peak_discharge_diff = #{peakDischargeDiff},</if>
            <if test="highChargeDiff != null">high_charge_diff = #{highChargeDiff},</if>
            <if test="highDischargeDiff != null">high_discharge_diff = #{highDischargeDiff},</if>
            <if test="flatChargeDiff != null">flat_charge_diff = #{flatChargeDiff},</if>
            <if test="flatDischargeDiff != null">flat_discharge_diff = #{flatDischargeDiff},</if>
            <if test="valleyChargeDiff != null">valley_charge_diff = #{valleyChargeDiff},</if>
            <if test="valleyDischargeDiff != null">valley_discharge_diff = #{valleyDischargeDiff},</if>
            calc_time = #{calcTime},
            update_time = NOW();
    </insert>

    <select id="getDataBySiteId" resultType="com.xzzn.ems.domain.vo.AmmeterStatisListVo">
        select DATE_FORMAT(r.dataDate, '%Y-%m-%d') as dataTime,
               r.activePeakKwh,
               r.reActivePeakKwh,
               r.activeHighKwh,
               r.reActiveHighKwh,
               r.activeFlatKwh,
               r.reActiveFlatKwh,
               r.activeValleyKwh,
               r.reActiveValleyKwh
        from (
                 -- 优先使用按天汇总记录（data_hour is null）
                 select DATE(t.data_date) as dataDate,
                        t.peak_charge_diff as activePeakKwh,
                        t.peak_discharge_diff as reActivePeakKwh,
                        t.high_charge_diff as activeHighKwh,
                        t.high_discharge_diff as reActiveHighKwh,
                        t.flat_charge_diff as activeFlatKwh,
                        t.flat_discharge_diff as reActiveFlatKwh,
                        t.valley_charge_diff as activeValleyKwh,
                        t.valley_discharge_diff as reActiveValleyKwh
                 from ems_daily_energy_data t
                 where t.data_hour is null
                 <if test="siteId != null and siteId != ''">
                     and t.site_id = #{siteId}
                 </if>
                 <if test="startTime != null and startTime != ''">
                     and t.data_date &gt;= #{startTime}
                 </if>
                 <if test="endTime != null and endTime != ''">
                     and t.data_date &lt; DATE_ADD(#{endTime}, INTERVAL 1 DAY)
                 </if>

                 union all

                 -- 若某天没有日汇总记录，则按小时数据汇总兜底
                 select DATE(h.data_date) as dataDate,
                        SUM(IFNULL(h.peak_charge_diff, 0)) as activePeakKwh,
                        SUM(IFNULL(h.peak_discharge_diff, 0)) as reActivePeakKwh,
                        SUM(IFNULL(h.high_charge_diff, 0)) as activeHighKwh,
                        SUM(IFNULL(h.high_discharge_diff, 0)) as reActiveHighKwh,
                        SUM(IFNULL(h.flat_charge_diff, 0)) as activeFlatKwh,
                        SUM(IFNULL(h.flat_discharge_diff, 0)) as reActiveFlatKwh,
                        SUM(IFNULL(h.valley_charge_diff, 0)) as activeValleyKwh,
                        SUM(IFNULL(h.valley_discharge_diff, 0)) as reActiveValleyKwh
                 from ems_daily_energy_data h
                 where h.data_hour is not null
                 <if test="siteId != null and siteId != ''">
                     and h.site_id = #{siteId}
                 </if>
                 <if test="startTime != null and startTime != ''">
                     and h.data_date &gt;= #{startTime}
                 </if>
                 <if test="endTime != null and endTime != ''">
                     and h.data_date &lt; DATE_ADD(#{endTime}, INTERVAL 1 DAY)
                 </if>
                   and not exists (
                     select 1
                     from ems_daily_energy_data d
                     where d.site_id = h.site_id
                       and DATE(d.data_date) = DATE(h.data_date)
                       and d.data_hour is null
                 )
                 group by h.site_id, DATE(h.data_date)
             ) r
        order by r.dataDate desc
    </select>

    <select id="getLastTotalRevenue" resultType="java.math.BigDecimal">
        select t.total_revenue
        from ems_daily_charge_data t
        where t.site_id = #{siteId}
          and date(t.date_time) &lt; CURDATE()
        order by t.date_time desc
        limit 1
    </select>

    <select id="getRealTimeRevenue" resultType="java.util.Map">
        select t.total_revenue as totalRevenue, t.day_revenue as dayRevenue
        from ems_daily_charge_data t
        where t.site_id = #{siteId}
        order by t.date_time desc
        limit 1
    </select>

    <select id="getRevenueDataBySiteId" resultType="com.xzzn.ems.domain.vo.AmmeterRevenueStatisListVo">
        select
            DATE_FORMAT(t.data_date, '%Y-%m-%d') as dataTime,
            COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) &lt; 5 THEN 1 ELSE 0 END) as isWorkday,
            CASE
                WHEN COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) &lt; 5 THEN 1 ELSE 0 END) = 1 THEN '工作日'
                ELSE '节假日'
            END as dayType,
            COALESCE(NULLIF(TRIM(w.weather_desc), ''), '--') as weatherDesc,
            ROUND(SUM(IFNULL(t.peak_charge_diff, 0) * IFNULL(pc.peak, 0)), 3) as activePeakPrice,
            ROUND(SUM(IFNULL(t.peak_discharge_diff, 0) * IFNULL(pc.peak, 0)), 3) as reActivePeakPrice,
            ROUND(SUM(IFNULL(t.high_charge_diff, 0) * IFNULL(pc.high, 0)), 3) as activeHighPrice,
            ROUND(SUM(IFNULL(t.high_discharge_diff, 0) * IFNULL(pc.high, 0)), 3) as reActiveHighPrice,
            ROUND(SUM(IFNULL(t.flat_charge_diff, 0) * IFNULL(pc.flat, 0)), 3) as activeFlatPrice,
            ROUND(SUM(IFNULL(t.flat_discharge_diff, 0) * IFNULL(pc.flat, 0)), 3) as reActiveFlatPrice,
            ROUND(SUM(IFNULL(t.valley_charge_diff, 0) * IFNULL(pc.valley, 0)), 3) as activeValleyPrice,
            ROUND(SUM(IFNULL(t.valley_discharge_diff, 0) * IFNULL(pc.valley, 0)), 3) as reActiveValleyPrice,
            ROUND(
                SUM(
                    (IFNULL(t.peak_discharge_diff, 0) - IFNULL(t.peak_charge_diff, 0)) * IFNULL(pc.peak, 0)
                    + (IFNULL(t.high_discharge_diff, 0) - IFNULL(t.high_charge_diff, 0)) * IFNULL(pc.high, 0)
                    + (IFNULL(t.flat_discharge_diff, 0) - IFNULL(t.flat_charge_diff, 0)) * IFNULL(pc.flat, 0)
                    + (IFNULL(t.valley_discharge_diff, 0) - IFNULL(t.valley_charge_diff, 0)) * IFNULL(pc.valley, 0)
                ),
                3
            ) as actualRevenue
        from ems_daily_energy_data t
        left join ems_calendar_day c on c.calendar_date = t.data_date
        left join ems_site_weather_day w on w.site_id = t.site_id and w.calendar_date = t.data_date
        left join ems_energy_price_config pc on pc.id = COALESCE(
            (
                select p.id
                from ems_energy_price_config p
                where p.site_id  = t.site_id
                  and STR_TO_DATE(CONCAT(p.year, '-', LPAD(p.month, 2, '0'), '-01'), '%Y-%m-%d') &lt;= DATE_FORMAT(t.data_date, '%Y-%m-01')
                order by STR_TO_DATE(CONCAT(p.year, '-', LPAD(p.month, 2, '0'), '-01'), '%Y-%m-%d') desc
                limit 1
            ),
            (
                select p2.id
                from ems_energy_price_config p2
                where p2.site_id  = t.site_id
                order by STR_TO_DATE(CONCAT(p2.year, '-', LPAD(p2.month, 2, '0'), '-01'), '%Y-%m-%d') asc
                limit 1
            )
        )
        where 1=1
        and t.data_hour is not null
        <if test="siteId != null">
            and t.site_id = #{siteId}
        </if>
        <if test="startTime != null">
            and t.data_date &gt;= #{startTime}
        </if>
        <if test="endTime != null">
            and t.data_date &lt;= #{endTime}
        </if>
        group by t.data_date,
                 COALESCE(c.is_workday, CASE WHEN WEEKDAY(t.data_date) &lt; 5 THEN 1 ELSE 0 END),
                 COALESCE(NULLIF(TRIM(w.weather_desc), ''), '--')
        order by t.data_date desc

    </select>
</mapper>
