diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-28 00:42:08 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-03-28 00:42:08 +0000 |
| commit | b8e8328b1ffffb80bf4ebb776a4a24e5680fc5bc (patch) | |
| tree | bbb4d82cee5f3fbf107e0648dea9a8f66e2710c4 /db/schema/contract.ts | |
| parent | 34bbeb86c1a8d24b5f526710889b5e54d699cfd0 (diff) | |
테이블 칼럼 리사이즈 및 핀 충돌 해결
Diffstat (limited to 'db/schema/contract.ts')
| -rw-r--r-- | db/schema/contract.ts | 244 |
1 files changed, 159 insertions, 85 deletions
diff --git a/db/schema/contract.ts b/db/schema/contract.ts index 10721b4d..cc1f8c57 100644 --- a/db/schema/contract.ts +++ b/db/schema/contract.ts @@ -169,92 +169,166 @@ export const contractSigners = pgTable("contract_signers", { export const contractsDetailView = pgView("contracts_detail_view").as((qb) => { return qb - .select({ - // Contract primary information - id: contracts.id, - contractNo: contracts.contractNo, - contractName: contracts.contractName, - status: contracts.status, - startDate: contracts.startDate, - endDate: contracts.endDate, - - // Project information - projectId: contracts.projectId, - projectCode: projects.code, - projectName: projects.name, - - // Vendor information - vendorId: contracts.vendorId, - vendorName: vendors.vendorName, - - // Payment and delivery details - paymentTerms: contracts.paymentTerms, - deliveryTerms: contracts.deliveryTerms, - deliveryDate: contracts.deliveryDate, - deliveryLocation: contracts.deliveryLocation, - - // Financial information - currency: contracts.currency, - totalAmount: contracts.totalAmount, - discount: contracts.discount, - tax: contracts.tax, - shippingFee: contracts.shippingFee, - netTotal: contracts.netTotal, - - // Additional settings - partialShippingAllowed: contracts.partialShippingAllowed, - partialPaymentAllowed: contracts.partialPaymentAllowed, - remarks: contracts.remarks, - version: contracts.version, - - // Timestamps - createdAt: contracts.createdAt, - updatedAt: contracts.updatedAt, - - // Electronic signature status - ADDED .as('has_signature') here - hasSignature: sql<boolean>`EXISTS ( - SELECT 1 - FROM ${contractEnvelopes} - WHERE ${contractEnvelopes.contractId} = ${contracts.id} - )`.as('has_signature'), - // --- 전자서명 이력 (Envelope) + 서명자(Signer)를 JSON 으로 중첩한 배열 --- - envelopes: sql<string>`COALESCE(( - SELECT json_agg( - json_build_object( - 'id', ce.id, - 'envelopeId', ce.envelope_id, - 'documentId', ce.document_id, - 'envelopeStatus', ce.envelope_status, - 'fileName', ce.file_name, - 'filePath', ce.file_path, - 'createdAt', ce.created_at, - 'updatedAt', ce.updated_at, - 'signers', ( - SELECT json_agg( - json_build_object( - 'id', cs.id, - 'vendorContactId', cs.vendor_contact_id, - 'signerType', cs.signer_type, - 'signerEmail', cs.signer_email, - 'signerName', cs.signer_name, - 'signerPosition', cs.signer_position, - 'signerStatus', cs.signer_status, - 'signedAt', cs.signed_at + .select({ + // Contract primary information + id: contracts.id, + contractNo: contracts.contractNo, + contractName: contracts.contractName, + status: contracts.status, + startDate: contracts.startDate, + endDate: contracts.endDate, + + // Project information + projectId: contracts.projectId, + projectCode: projects.code, + projectName: projects.name, + + // Vendor information + vendorId: contracts.vendorId, + vendorName: vendors.vendorName, + + // Payment and delivery details + paymentTerms: contracts.paymentTerms, + deliveryTerms: contracts.deliveryTerms, + deliveryDate: contracts.deliveryDate, + deliveryLocation: contracts.deliveryLocation, + + // Financial information + currency: contracts.currency, + totalAmount: contracts.totalAmount, + discount: contracts.discount, + tax: contracts.tax, + shippingFee: contracts.shippingFee, + netTotal: contracts.netTotal, + + // Additional settings + partialShippingAllowed: contracts.partialShippingAllowed, + partialPaymentAllowed: contracts.partialPaymentAllowed, + remarks: contracts.remarks, + version: contracts.version, + + // Timestamps + createdAt: contracts.createdAt, + updatedAt: contracts.updatedAt, + + // Electronic signature status + hasSignature: sql<boolean>`EXISTS ( + SELECT 1 + FROM ${contractEnvelopes} + WHERE ${contractEnvelopes.contractId} = ${contracts.id} + )`.as("has_signature"), + // hasItme: sql<boolean>`EXISTS ( + // SELECT 1 + // FROM ${contractItems} + // WHERE ${contractItems.contractId} = ${contracts.id} + // )`.as("has_signature"), + + // ========================= + // 1) contract_items -> JSON + // ========================= + // 'items' (or "contractItems")라는 필드를 JSON 배열로 가져오기 + items: sql<string>`COALESCE(( + SELECT json_agg( + json_build_object( + 'id', ci.id, + 'itemId', ci.item_id, + 'description', ci.description, + 'quantity', ci.quantity, + 'unitPrice', ci.unit_price, + 'taxRate', ci.tax_rate, + 'taxAmount', ci.tax_amount, + 'totalLineAmount', ci.total_line_amount, + 'remark', ci.remark, + 'createdAt', ci.created_at, + 'updatedAt', ci.updated_at + ) + ) + FROM ${contractItems} AS ci + WHERE ci.contract_id = ${contracts.id} + ), '[]')`.as("items"), + + // ========================= + // 2) contract_envelopes -> JSON + // ========================= + envelopes: sql<string>`COALESCE(( + SELECT json_agg( + json_build_object( + 'id', ce.id, + 'envelopeId', ce.envelope_id, + 'documentId', ce.document_id, + 'envelopeStatus', ce.envelope_status, + 'fileName', ce.file_name, + 'filePath', ce.file_path, + 'createdAt', ce.created_at, + 'updatedAt', ce.updated_at, + 'signers', ( + SELECT json_agg( + json_build_object( + 'id', cs.id, + 'vendorContactId', cs.vendor_contact_id, + 'signerType', cs.signer_type, + 'signerEmail', cs.signer_email, + 'signerName', cs.signer_name, + 'signerPosition', cs.signer_position, + 'signerStatus', cs.signer_status, + 'signedAt', cs.signed_at + ) ) + FROM ${contractSigners} AS cs + WHERE cs.envelope_id = ce.id ) - FROM ${contractSigners} AS cs - WHERE cs.envelope_id = ce.id ) ) - ) - FROM ${contractEnvelopes} AS ce - WHERE ce.contract_id = ${contracts.id} - ), '[]')`.as("envelopes") - }) - .from(contracts) - .leftJoin(projects, eq(contracts.projectId, projects.id)) - .leftJoin(vendors, eq(contracts.vendorId, vendors.id)) -}); - -// Type inference for the view -export type ContractDetail = typeof contractsDetailView.$inferSelect;
\ No newline at end of file + FROM ${contractEnvelopes} AS ce + WHERE ce.contract_id = ${contracts.id} + ), '[]')`.as("envelopes"), + }) + .from(contracts) + .leftJoin(projects, eq(contracts.projectId, projects.id)) + .leftJoin(vendors, eq(contracts.vendorId, vendors.id)) + }); + + export interface ContractItemParsed { + id: number + itemId: number + description: string | null + quantity: number + unitPrice: number | null + taxRate: number | null + taxAmount: number | null + totalLineAmount: number | null + remark: string | null + createdAt: string + updatedAt: string + } + + // 기존 Envelope + Signers + export interface Envelope { + id: number + envelopeId: string + documentId: string | null + envelopeStatus: string | null + fileName: string + filePath: string + createdAt: string + updatedAt: string + signers?: { + id: number + vendorContactId: number | null + signerType: string + signerEmail: string + signerName: string + signerPosition: string | null + signerStatus: string + signedAt: string | null + }[] + } + + // Drizzle가 만들어준 raw type + export type ContractDetail = typeof contractsDetailView.$inferSelect; + + // 우리가 UI에서 쓰고 싶은 파싱된 타입 + export type ContractDetailParsed = Omit<ContractDetail, "envelopes" | "items"> & { + envelopes: Envelope[] + items: ContractItemParsed[] + }
\ No newline at end of file |
