File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.itn.itnhub.process.ProcessItemMapper">
<!--
processed_at/web_edited_at/created_at/updated_at을 밀리초 epoch로 내려준다
(review_item과 동일 관례). null이면 extract(epoch from null)도 null이라 그대로 null이 내려간다.
-->
<sql id="columns">
id, org_id, seq, site_name, category, board_name, post_title, url, description,
has_attachment, prior_kogl_type, contract_docs, produced_date, published_date,
review_major, review_minor, review_result, review_kogl_type, review_ai_type,
review_opinion, review_note, prior_evidence,
judged_kogl_type, judged_ai_type, final_opinion, judgment_basis, process_status,
(extract(epoch from processed_at) * 1000)::bigint as processed_at,
(extract(epoch from web_edited_at) * 1000)::bigint as web_edited_at,
(extract(epoch from created_at) * 1000)::bigint as created_at,
(extract(epoch from updated_at) * 1000)::bigint as updated_at
</sql>
<sql id="keywordFilter">
<if test="keyword != null">
and (site_name ilike concat('%', #{keyword}, '%')
or post_title ilike concat('%', #{keyword}, '%'))
</if>
<!-- 열별 조건. 서로 AND로 겹쳐서 복합검색이 된다(권리확인과 동일 규칙). -->
<if test="site != null">
and site_name ilike concat('%', #{site}, '%')
</if>
<if test="board != null">
and board_name ilike concat('%', #{board}, '%')
</if>
<if test="title != null">
and post_title ilike concat('%', #{title}, '%')
</if>
</sql>
<!-- status: null=전체, "DONE"=처리완료, "PENDING"=그 외(null/빈/미처리 등 처리완료가 아닌 전부). -->
<sql id="statusFilter">
<if test="status != null and status == 'DONE'">
and process_status = '처리완료'
</if>
<if test="status != null and status == 'PENDING'">
and (process_status is null or process_status = '' or process_status <> '처리완료')
</if>
</sql>
<select id="findPage" resultType="kr.itn.itnhub.process.ProcessItem">
select <include refid="columns"/>
from process_item
where org_id = #{orgId}
<include refid="keywordFilter"/>
<include refid="statusFilter"/>
order by seq asc
limit #{limit} offset #{offset}
</select>
<select id="countByOrg" resultType="int">
select count(*)
from process_item
where org_id = #{orgId}
<include refid="keywordFilter"/>
<include refid="statusFilter"/>
</select>
<select id="findAllByOrg" resultType="kr.itn.itnhub.process.ProcessItem">
select <include refid="columns"/>
from process_item
where org_id = #{orgId}
order by seq asc
</select>
<select id="findSeqsByOrg" resultType="int">
select seq from process_item where org_id = #{orgId}
</select>
<select id="findById" resultType="kr.itn.itnhub.process.ProcessItem">
select <include refid="columns"/>
from process_item
where org_id = #{orgId} and id = #{id}
</select>
<!--
정책(b): 조사원+권리확인 영역(site_name..prior_evidence, 계약서 유무 제외)은 재업로드마다
항상 최신 파일값으로 덮어쓴다. 계약서 유무(contract_docs)는 웹에서 입력하는 값이라
web_edited_at이 null일 때만(=웹에서 아직 아무도 손대지 않았을 때만) 파일값을 반영한다.
권리처리 영역(judged_kogl_type..process_status)도 마찬가지로 web_edited_at이 null일
때만 파일값을 반영한다 - 이미 웹에서 처리 결과를 입력한 행은 재업로드가 절대 덮어쓰지
않는다. processed_at/web_edited_at 자체는 이 upsert가 건드리지 않는다.
-->
<insert id="upsertFromFile" parameterType="kr.itn.itnhub.process.ProcessItem">
insert into process_item (
org_id, seq, site_name, category, board_name, post_title, url, description,
has_attachment, prior_kogl_type, contract_docs, produced_date, published_date,
review_major, review_minor, review_result, review_kogl_type, review_ai_type,
review_opinion, review_note, prior_evidence,
judged_kogl_type, judged_ai_type, final_opinion, judgment_basis, process_status
) values (
#{orgId}, #{seq}, #{siteName}, #{category}, #{boardName}, #{postTitle}, #{url}, #{description},
#{hasAttachment}, #{priorKoglType}, #{contractDocs}, #{producedDate}, #{publishedDate},
#{reviewMajor}, #{reviewMinor}, #{reviewResult}, #{reviewKoglType}, #{reviewAiType},
#{reviewOpinion}, #{reviewNote}, #{priorEvidence},
#{judgedKoglType}, #{judgedAiType}, #{finalOpinion}, #{judgmentBasis}, #{processStatus}
)
on conflict (org_id, seq) do update set
site_name = excluded.site_name,
category = excluded.category,
board_name = excluded.board_name,
post_title = excluded.post_title,
url = excluded.url,
description = excluded.description,
has_attachment = excluded.has_attachment,
prior_kogl_type = excluded.prior_kogl_type,
produced_date = excluded.produced_date,
published_date = excluded.published_date,
review_major = excluded.review_major,
review_minor = excluded.review_minor,
review_result = excluded.review_result,
review_kogl_type = excluded.review_kogl_type,
review_ai_type = excluded.review_ai_type,
review_opinion = excluded.review_opinion,
review_note = excluded.review_note,
prior_evidence = excluded.prior_evidence,
contract_docs = case when process_item.web_edited_at is null then excluded.contract_docs else process_item.contract_docs end,
judged_kogl_type = case when process_item.web_edited_at is null then excluded.judged_kogl_type else process_item.judged_kogl_type end,
judged_ai_type = case when process_item.web_edited_at is null then excluded.judged_ai_type else process_item.judged_ai_type end,
final_opinion = case when process_item.web_edited_at is null then excluded.final_opinion else process_item.final_opinion end,
judgment_basis = case when process_item.web_edited_at is null then excluded.judgment_basis else process_item.judgment_basis end,
process_status = case when process_item.web_edited_at is null then excluded.process_status else process_item.process_status end,
updated_at = now()
</insert>
<!--
processed_at은 "처리완료"에 처음 도달한 시각만 남긴다: 이미 값이 있으면(먼저 처리완료로
저장된 적이 있으면) 이번 저장이 다시 처리완료든 미처리로 되돌리든 손대지 않는다.
-->
<update id="updateProcessing">
update process_item set
contract_docs = #{contractDocs},
judged_kogl_type = #{judgedKoglType},
judged_ai_type = #{judgedAiType},
final_opinion = #{finalOpinion},
judgment_basis = #{judgmentBasis},
process_status = #{processStatus},
web_edited_at = now(),
processed_at = case
when #{processStatus} = '처리완료' and process_item.processed_at is null then now()
else process_item.processed_at
end,
updated_at = now()
where org_id = #{orgId} and id = #{id}
</update>
<delete id="deleteById">
delete from process_item where org_id = #{orgId} and id = #{id}
</delete>
<delete id="deleteByOrg">
delete from process_item where org_id = #{orgId}
</delete>
<resultMap id="statsResultMap" type="kr.itn.itnhub.process.ProcessStats">
<constructor>
<arg column="total" javaType="_int"/>
<arg column="done" javaType="_int"/>
</constructor>
</resultMap>
<!-- 일괄 등록. 채운 항목만 반영되도록 coalesce를 쓰고, 처리완료로 바뀔 때만 처리시각을 찍는다. -->
<update id="updateProcessingBulk">
update process_item set
process_status = coalesce(#{processStatus}, process_status),
judged_kogl_type = coalesce(#{judgedKoglType}, judged_kogl_type),
final_opinion = coalesce(#{finalOpinion}, final_opinion),
processed_at = case when #{processStatus} = '처리완료' then now() else processed_at end,
web_edited_at = now(),
updated_at = now()
where org_id = #{orgId}
and id in
<foreach item="id" collection="ids" open="(" separator="," close=")">#{id}</foreach>
</update>
<delete id="deleteByIds">
delete from process_item
where org_id = #{orgId}
and id in
<foreach item="id" collection="ids" open="(" separator="," close=")">#{id}</foreach>
</delete>
<select id="stats" resultMap="statsResultMap">
select
count(*) as total,
count(*) filter (where process_status = '처리완료') as done
from process_item
where org_id = #{orgId}
</select>
</mapper>