<?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">

<!--
    Cross-tenant 어드민 합산 전용 mapper.

    핵심 규칙 (notes/gbpark/2026-04-27-cross-tenant-admin-aggregation.md §6.2):
      - SELECT 만. UPDATE/DELETE/INSERT 금지 (수정은 회사 도메인 컨텍스트로 위임).
      - WHERE 에 COMPANY_CODE 필터 박지 말 것 — fan-out 시 각 회사 DB 안에서만 실행되므로
        그 회사 데이터로 정의상 한정됨.
      - SELECT 절에도 COMPANY_CODE 박지 말 것 — Aggregator 가 메타 DB 라우팅 정보 기준으로
        응답 행에 박아준다 (회사 DB 안에 저장된 stale COMPANY_CODE 값 우선시 금지).
      - JOIN 은 회사 DB 내부 테이블끼리만. 메타 DB 조인 금지.

    namespace 단일: "admin-cross-tenant"
-->
<mapper namespace="admin-cross-tenant">

  <!--
    사용자 목록 — 단일 회사 admin.selectUserList 와 컬럼 동일 (COMPANY_CODE 제외).
    company_code 는 Aggregator 가 응답에 박는다.
    cross-tenant 1차 구현은 페이지네이션 없이 회사당 전체 반환 (설계서 §9.3).
    필터는 search / status / dept_code 만 지원 (단일 회사 화면과 동일).
  -->
  <select id="listUsers" parameterType="map" resultType="map">
    SELECT
        SABUN                                                       AS sabun
      , USER_ID                                                     AS user_id
      , USER_NAME                                                   AS user_name
      , COALESCE(USER_NAME_ENG, '')                                 AS user_name_eng
      , COALESCE(DEPT_CODE, '')                                     AS dept_code
      , COALESCE(DEPT_NAME, '')                                     AS dept_name
      , COALESCE(POSITION_CODE, '')                                 AS position_code
      , COALESCE(POSITION_NAME, '')                                 AS position_name
      , COALESCE(EMAIL, '')                                         AS email
      , COALESCE(TEL, '')                                           AS tel
      , COALESCE(CELL_PHONE, '')                                    AS cell_phone
      , COALESCE(USER_TYPE, '')                                     AS user_type
      , COALESCE(USER_TYPE_NAME, '')                                AS user_type_name
      , COALESCE(TO_CHAR(CREATED_DATE, 'YYYY-MM-DD'), '')           AS reg_date
      , STATUS                                                      AS status
      , COALESCE(LOCALE, '')                                        AS locale
    FROM USER_INFO
    WHERE 1=1
    <if test="search != null and search != ''">
      AND (USER_ID ILIKE #{search}
        OR USER_NAME ILIKE #{search}
        OR DEPT_NAME ILIKE #{search}
        OR POSITION_NAME ILIKE #{search}
        OR USER_TYPE_NAME ILIKE #{search}
        OR SABUN ILIKE #{search}
        OR EMAIL ILIKE #{search}
        OR TEL ILIKE #{search}
        OR CELL_PHONE ILIKE #{search})
    </if>
    <if test="status != null and status != ''">
      AND STATUS = #{status}
    </if>
    <if test="dept_code != null and dept_code != ''">
      AND DEPT_CODE = #{dept_code}
    </if>
    ORDER BY CREATED_DATE DESC, USER_NAME ASC
    <if test="per_company_limit_plus_one != null">
      LIMIT #{per_company_limit_plus_one}
    </if>
  </select>

  <!--
    권한 그룹 목록 — 단일 회사 role.getRoleGroupList 와 컬럼 동일 (COMPANY_CODE 제외).
    member_count / menu_count 서브쿼리 그대로 유지. 회사 DB 안에서 동작하므로
    그 회사의 AUTHORITY_SUB_USER / AUTHORITY_SUB_MENU 만 카운트됨.
  -->
  <select id="listRoleGroups" parameterType="map" resultType="map">
    SELECT
        AM.OBJID                                AS objid
      , AM.AUTH_NAME                            AS auth_name
      , AM.AUTH_CODE                            AS auth_code
      , AM.STATUS                               AS status
      , AM.WRITER                               AS writer
      , AM.CREATED_DATE                         AS created_date
      , (SELECT COUNT(*) FROM AUTHORITY_SUB_USER WHERE MASTER_OBJID = AM.OBJID) AS member_count
      , (SELECT COUNT(*) FROM AUTHORITY_SUB_MENU WHERE MASTER_OBJID = AM.OBJID) AS menu_count
    FROM AUTHORITY_MASTER AM
    WHERE 1=1
    <if test="search != null and search != ''">
      AND AM.AUTH_NAME ILIKE #{search}
    </if>
    ORDER BY AM.CREATED_DATE DESC
    <if test="per_company_limit_plus_one != null">
      LIMIT #{per_company_limit_plus_one}
    </if>
  </select>

  <!--
    배치 목록 — 단일 회사 batch.getBatchList 와 동일하게 SELECT *.
    PostgreSQL 컬럼명이 그대로 lowercase Map key 로 떨어짐.
    페이지네이션은 cross-tenant 1차 구현엔 비지원 (회사당 전체 반환).
  -->
  <select id="listBatches" parameterType="map" resultType="map">
    SELECT *
    FROM BATCH_CONFIGS
    WHERE 1=1
    <if test="search != null and search != ''">
      AND (BATCH_NAME ILIKE '%' || #{search} || '%'
           OR DESCRIPTION ILIKE '%' || #{search} || '%')
    </if>
    <if test="is_active != null and is_active != ''">
      AND IS_ACTIVE = #{is_active}
    </if>
    ORDER BY CREATED_DATE DESC
    <if test="per_company_limit_plus_one != null">
      LIMIT #{per_company_limit_plus_one}
    </if>
  </select>

  <!--
    다국어 키 목록 — 단일 회사 multilang.getMultilangKeyList 와 컬럼 동일.
    회사 DB 안에서 동작하므로 filter_company_code 분기 불필요 (그 회사 데이터로 정의상 한정).
    1차 구현은 category_id 재귀 필터 비지원 — 필요해지면 후속 추가.
  -->
  <select id="listLangKeys" parameterType="map" resultType="map">
    SELECT
        KEY_ID         AS key_id
      , USAGE_NOTE     AS usage_note
      , LANG_KEY       AS lang_key
      , DESCRIPTION    AS description
      , IS_ACTIVE      AS is_active
      , CATEGORY_ID    AS category_id
      , CREATED_DATE   AS created_date
      , CREATED_BY     AS created_by
      , UPDATED_DATE   AS updated_date
      , UPDATED_BY     AS updated_by
    FROM MULTI_LANG_KEY_MASTER
    WHERE 1=1
    <if test="menu_code != null and menu_code != ''">
      AND USAGE_NOTE = #{menu_code}
    </if>
    <if test="search != null and search != ''">
      AND (LANG_KEY ILIKE #{search}
        OR DESCRIPTION ILIKE #{search})
    </if>
    ORDER BY CREATED_DATE DESC, KEY_ID DESC
    <if test="per_company_limit_plus_one != null">
      LIMIT #{per_company_limit_plus_one}
    </if>
  </select>

</mapper>
