summaryrefslogtreecommitdiff
path: root/lib/project-avl/service.ts
blob: 6ba10c5e55753fb3c4395754488a6e309e744f33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// src/lib/projectApprovedVendors/service.ts
"use server"; // Next.js 서버 액션에서 직접 import하려면 (선택)

import { revalidateTag, unstable_noStore } from "next/cache";
import  db  from "@/db/db";
import { customAlphabet } from "nanoid";

import { filterColumns } from "@/lib/filter-columns";
import { unstable_cache } from "@/lib/unstable-cache";
import { getErrorMessage } from "@/lib/handle-error";

import { asc, desc, ilike, inArray, and, gte, lte, not, or ,eq} from "drizzle-orm";
import { GetProjectAVLSchema } from "./validations";
import { projectApprovedVendors } from "@/db/schema";
import { countProjectAVLs, selectProejctAVLs } from "./repository";


/* -----------------------------------------------------
   1) 조회 관련 
----------------------------------------------------- */

/**
 * 복잡한 조건으로 Item 목록을 조회 (+ pagination) 하고,
 * 총 개수에 따라 pageCount를 계산해서 리턴.
 * Next.js의 unstable_cache를 사용해 일정 시간 캐시.
 */
export async function getProjecTAVL(input: GetProjectAVLSchema) {

  return unstable_cache(
    async () => {
      try {
        const offset = (input.page - 1) * input.perPage;

        // const advancedTable = input.flags.includes("advancedTable");
        const advancedTable = true;

        // advancedTable 모드면 filterColumns()로 where 절 구성
        const advancedWhere = filterColumns({
          table: projectApprovedVendors,
          filters: input.filters,
          joinOperator: input.joinOperator,
        });


        let globalWhere
        if (input.search) {
          const s = `%${input.search}%`
          globalWhere = 
          or(
            ilike(projectApprovedVendors.vendor_name, s), 
          ilike(projectApprovedVendors.tax_id, s)
          , ilike(projectApprovedVendors.vendor_email, s)
          , ilike(projectApprovedVendors.vendor_type_name_ko, s)
          , ilike(projectApprovedVendors.project_name, s)
          , ilike(projectApprovedVendors.project_code, s)
        )
          // 필요시 여러 칼럼 OR조건 (status, priority, etc)
        }

        const finalWhere = and(
          // advancedWhere or your existing conditions
          advancedWhere,
          globalWhere // and()함수로 결합 or or() 등으로 결합
        )


        // 아니면 ilike, inArray, gte 등으로 where 절 구성
        const where = finalWhere
        

        const orderBy =
          input.sort.length > 0
            ? input.sort.map((item) =>
                item.desc ? desc(projectApprovedVendors[item.id]) : asc(projectApprovedVendors[item.id])
              )
            : [asc(projectApprovedVendors.approved_at)];

        // 트랜잭션 내부에서 Repository 호출
        const { data, total } = await db.transaction(async (tx) => {
          const data = await selectProejctAVLs(tx, {
            where,
            orderBy,
            offset,
            limit: input.perPage,
          });

          const total = await countProjectAVLs(tx, where);
          return { data, total };
        });

        const pageCount = Math.ceil(total / input.perPage);

        return { data, pageCount };
      } catch (err) {
        // 에러 발생 시 디폴트
        return { data: [], pageCount: 0 };
      }
    },
    [JSON.stringify(input)], // 캐싱 키
    {
      revalidate: 3600,
      tags: ["project-approved-vendors"], // revalidateTag("projectApprovedVendors") 호출 시 무효화
    }
  )();
}