From e3b336f0be4b27afd5ef8bfe6e5f048a18fb9b38 Mon Sep 17 00:00:00 2001 From: Rizki Date: Tue, 27 Jan 2026 17:08:31 +0700 Subject: [PATCH 1/8] upd --- src/schema/procurement.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/schema/procurement.ts b/src/schema/procurement.ts index fab93d4..50cc349 100644 --- a/src/schema/procurement.ts +++ b/src/schema/procurement.ts @@ -1,3 +1,5 @@ export * from "../entity/procurement/procurement_category"; export * from "../entity/procurement/procurement_vendor"; export * from "../entity/procurement/procurement_project_yearly"; + +export * from "../types/procurement"; From 93d2e1f4227e41b1a0a1b27ef2fb70e273654bde Mon Sep 17 00:00:00 2001 From: Rizki Date: Tue, 27 Jan 2026 18:02:18 +0700 Subject: [PATCH 2/8] add entity for tender --- .../procurement_checklist_payment.ts | 81 +++++++ .../procurement_checklist_payment_approval.ts | 32 +++ .../procurement_checklist_payment_document.ts | 20 ++ .../procurement_checklist_payment_item.ts | 37 +++ src/entity/procurement/procurement_tender.ts | 229 ++++++++++++++++++ src/schema/procurement.ts | 5 + src/types/procurement.ts | 41 ++++ 7 files changed, 445 insertions(+) create mode 100644 src/entity/procurement/procurement_checklist_payment.ts create mode 100644 src/entity/procurement/procurement_checklist_payment_approval.ts create mode 100644 src/entity/procurement/procurement_checklist_payment_document.ts create mode 100644 src/entity/procurement/procurement_checklist_payment_item.ts create mode 100644 src/entity/procurement/procurement_tender.ts diff --git a/src/entity/procurement/procurement_checklist_payment.ts b/src/entity/procurement/procurement_checklist_payment.ts new file mode 100644 index 0000000..c90a66b --- /dev/null +++ b/src/entity/procurement/procurement_checklist_payment.ts @@ -0,0 +1,81 @@ +import { Column, CreateDateColumn, DeleteDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; +import { HrmsDepartment } from "../hrms/hrms_department"; +import { ProcurementChecklistPaymentItem } from "./procurement_checklist_payment_item"; +import { ProcurementChecklistPaymentApproval } from "./procurement_checklist_payment_approval"; +import { FinanceFundingSource } from "../finance/finance_funding_sources"; +import { FinanceAtividade } from "../finance/finance_atividade"; +import { FinanceSubBudgetLine } from "../finance/fincance_sub_budget_lines"; +import { ProcurementChecklistPaymentStatus, ProcurementChecklistPaymentType } from "../../types/procurement"; +import { ProcurementTender } from "./procurement_tender"; + +@Entity("procurement_checklist_payment", { schema: "procurement" }) +export class ProcurementChecklistPayment { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => ProcurementTender, (tender) => tender.checklist_payment, { onDelete: "CASCADE" }) + tender: ProcurementTender; + + @Column({ + unique: false, + length: 128, + }) + type: ProcurementChecklistPaymentType; + + @Column({ + unique: true, + length: 128, + }) + code: string; + + @Column({ + nullable: false, + }) + checklist_payment_at: Date; + + @ManyToOne(() => FinanceFundingSource, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + funding_source: FinanceFundingSource; + + @ManyToOne(() => HrmsDepartment, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + department: HrmsDepartment; + + @ManyToOne(() => FinanceAtividade, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + activity: FinanceAtividade; + + @ManyToOne(() => FinanceSubBudgetLine, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + sub_budget_line: FinanceSubBudgetLine; + + @OneToMany(() => ProcurementChecklistPaymentItem, (item) => item.payment, { cascade: true }) + items: ProcurementChecklistPaymentItem[]; + + @OneToMany(() => ProcurementChecklistPaymentApproval, (approval) => approval.payment, { cascade: true }) + approvals: ProcurementChecklistPaymentApproval[]; + + @Column({ nullable: false }) + status: ProcurementChecklistPaymentStatus; + + @Column() + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @Column({ nullable: true }) + @UpdateDateColumn() + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @Column({ nullable: true }) + @DeleteDateColumn() + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/entity/procurement/procurement_checklist_payment_approval.ts b/src/entity/procurement/procurement_checklist_payment_approval.ts new file mode 100644 index 0000000..b857d60 --- /dev/null +++ b/src/entity/procurement/procurement_checklist_payment_approval.ts @@ -0,0 +1,32 @@ +import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { ProcurementChecklistPayment } from "./procurement_checklist_payment"; +import { ProcurementChecklistPaymentApprovalRole } from "../../types/procurement"; +import { HrmsEmployee } from "../hrms/hrms_employee"; + +@Entity("procurement_checklist_payment_approval", { schema: "procurement" }) +export class ProcurementChecklistPaymentApproval { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => ProcurementChecklistPayment, (payment) => payment.approvals, { onDelete: "CASCADE" }) + payment: ProcurementChecklistPayment; + + @Column({ type: "enum", enum: ProcurementChecklistPaymentApprovalRole }) + role: ProcurementChecklistPaymentApprovalRole; + + @ManyToOne(() => HrmsEmployee, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + employee: HrmsEmployee; + + @Column() + name: string; + + @Column({ nullable: true }) + position: string; + + @Column({ type: "date", nullable: true }) + signed_date: Date; + + @Column({ nullable: true, default: false }) + is_signed: boolean; +} diff --git a/src/entity/procurement/procurement_checklist_payment_document.ts b/src/entity/procurement/procurement_checklist_payment_document.ts new file mode 100644 index 0000000..48ebeb3 --- /dev/null +++ b/src/entity/procurement/procurement_checklist_payment_document.ts @@ -0,0 +1,20 @@ +import { Column, CreateDateColumn, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { ProcurementChecklistPaymentItem } from "./procurement_checklist_payment_item"; + +@Entity("procurement_checklist_payment_document", { schema: "procurement" }) +export class ProcurementChecklistPaymentDocument { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => ProcurementChecklistPaymentItem, (item) => item.documents, { onDelete: "CASCADE" }) + checklist_item: ProcurementChecklistPaymentItem; + + @Column({ nullable: true }) + reference_id: string; + + @Column({ nullable: true }) + document_number: string; + + @CreateDateColumn() + created_at: Date; +} diff --git a/src/entity/procurement/procurement_checklist_payment_item.ts b/src/entity/procurement/procurement_checklist_payment_item.ts new file mode 100644 index 0000000..1b568c3 --- /dev/null +++ b/src/entity/procurement/procurement_checklist_payment_item.ts @@ -0,0 +1,37 @@ +import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { ProcurementChecklistPayment } from "./procurement_checklist_payment"; +import { ProcurementChecklistPaymentItemType } from "../../types/procurement"; +import { ProcurementChecklistPaymentDocument } from "./procurement_checklist_payment_document"; + +@Entity("procurement_checklist_payment_item", { schema: "procurement" }) +export class ProcurementChecklistPaymentItem { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => ProcurementChecklistPayment, (payment) => payment.items, { onDelete: "CASCADE" }) + payment: ProcurementChecklistPayment; + + @Column({ type: "enum", enum: ProcurementChecklistPaymentItemType }) + type: ProcurementChecklistPaymentItemType; + + @Column({ default: false }) + is_checked: boolean; + + @Column({ type: "date", nullable: true }) + file_date: Date; + + @Column({ + nullable: true, + type: "float8", + }) + fund: number; + + @Column({ length: 128, nullable: true }) + document_number: string; + + @Column({ nullable: true }) + reference_id: string; + + @OneToMany(() => ProcurementChecklistPaymentDocument, (doc) => doc.checklist_item, { cascade: true }) + documents: ProcurementChecklistPaymentDocument[]; +} diff --git a/src/entity/procurement/procurement_tender.ts b/src/entity/procurement/procurement_tender.ts new file mode 100644 index 0000000..46a2761 --- /dev/null +++ b/src/entity/procurement/procurement_tender.ts @@ -0,0 +1,229 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, ManyToOne, JoinColumn, OneToMany } from "typeorm"; +import { HrmsDepartment } from "../hrms/hrms_department"; +import { Status } from "../../types/status"; +import { FinanceCpv } from "../finance/finance_cpvs"; +import { ProcurementTenderStatus } from "../../types/procurement"; +import { ProcurementVendor } from "./procurement_vendor"; +import { ProcurementChecklistPayment } from "./procurement_checklist_payment"; + +@Entity("procurement_tenders", { schema: "procurement" }) +export class ProcurementTender { + @PrimaryGeneratedColumn("uuid") + id: string; + + // ========================= + // GENERAL INFORMATION + // ========================= + + @ManyToOne(() => HrmsDepartment, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + department: HrmsDepartment; + + @ManyToOne(() => FinanceCpv, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + cpv: FinanceCpv; + + // ========================= + // TENDER INFORMATION + // ========================= + + @Column({ length: 64 }) + tender_number: string; // 123/ANTL/2025/011 + + @Column({ length: 256 }) + tender_name: string; + + @Column({ length: 32 }) + tender_type: string; // Tender / RFQ / etc + + @Column({ type: "float8", nullable: true }) + planning_price: number; + + @Column({ type: "float8", nullable: true }) + realization_price: number; + + @ManyToOne(() => ProcurementVendor, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + vendor: ProcurementVendor; + + @Column({ type: "date", nullable: true }) + start_date: Date; + + @Column({ type: "date", nullable: true }) + target_complete_date: Date; + + @Column({ length: 32 }) + status: ProcurementTenderStatus; // On Going, Completed, Cancelled + + // ========================= + // UPLOAD DOCUMENTS (CORE) + // ========================= + + // Pedido Pagamentu (PR) + @Column({ length: 256, nullable: true }) + pr_file_url: string; + + @Column({ type: "date", nullable: true }) + pr_file_date: Date; + + @Column({ length: 64, nullable: true }) + pr_number: string; + + // CPV / PR + @Column({ length: 256, nullable: true }) + cpv_pr_file_url: string; + + @Column({ type: "date", nullable: true }) + cpv_pr_file_date: Date; + + @Column({ length: 64, nullable: true }) + cpv_pr_number: string; + + // Obrigasan + @Column({ length: 256, nullable: true }) + obrigasan_file_url: string; + + @Column({ type: "date", nullable: true }) + obrigasan_file_date: Date; + + @Column({ length: 64, nullable: true }) + obrigasan_number: string; + + // PO + @Column({ length: 256, nullable: true }) + po_file_url: string; + + @Column({ type: "date", nullable: true }) + po_file_date: Date; + + @Column({ length: 64, nullable: true }) + po_number: string; + + // Factura + @Column({ length: 256, nullable: true }) + facture_file_url: string; + + @Column({ type: "date", nullable: true }) + facture_file_date: Date; + + @Column({ length: 64, nullable: true }) + facture_number: string; + + // R&I Report + @Column({ length: 256, nullable: true }) + ri_report_file_url: string; + + @Column({ type: "date", nullable: true }) + ri_report_file_date: Date; + + @Column({ length: 64, nullable: true }) + ri_report_number: string; + + // Certificate Payment + @Column({ length: 256, nullable: true }) + certificate_payment_file_url: string; + + @Column({ type: "date", nullable: true }) + certificate_payment_file_date: Date; + + @Column({ length: 64, nullable: true }) + certificate_payment_number: string; + + // Contract + @Column({ length: 256, nullable: true }) + contract_file_url: string; + + @Column({ type: "date", nullable: true }) + contract_file_date: Date; + + @Column({ length: 64, nullable: true }) + contract_number: string; + + // Recommendation Maintenance + @Column({ length: 256, nullable: true }) + recommendation_file_url: string; + + @Column({ type: "date", nullable: true }) + recommendation_file_date: Date; + + @Column({ length: 64, nullable: true }) + recommendation_number: string; + + // Service Report + @Column({ length: 256, nullable: true }) + service_report_file_url: string; + + @Column({ type: "date", nullable: true }) + service_report_file_date: Date; + + @Column({ length: 64, nullable: true }) + service_report_number: string; + + // ========================= + // OTHER DOCUMENT (3 ITEMS) + // ========================= + + @Column({ length: 128, nullable: true }) + other_doc1_label: string; + + @Column({ length: 256, nullable: true }) + other_doc1_file_url: string; + + @Column({ type: "date", nullable: true }) + other_doc1_file_date: Date; + + @Column({ length: 64, nullable: true }) + other_doc1_number: string; + + @Column({ length: 128, nullable: true }) + other_doc2_label: string; + + @Column({ length: 256, nullable: true }) + other_doc2_file_url: string; + + @Column({ type: "date", nullable: true }) + other_doc2_file_date: Date; + + @Column({ length: 64, nullable: true }) + other_doc2_number: string; + + @Column({ length: 128, nullable: true }) + other_doc3_label: string; + + @Column({ length: 256, nullable: true }) + other_doc3_file_url: string; + + @Column({ type: "date", nullable: true }) + other_doc3_file_date: Date; + + @Column({ length: 64, nullable: true }) + other_doc3_number: string; + + // ========================= + // CHECKLIST PAAMENTO + // ========================= + @OneToMany(() => ProcurementChecklistPayment, (item) => item.tender, { cascade: true }) + checklist_payment: ProcurementChecklistPayment; + + // ========================= + // AUDIT + // ========================= + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @UpdateDateColumn({ nullable: true }) + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @DeleteDateColumn({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/schema/procurement.ts b/src/schema/procurement.ts index 50cc349..092d340 100644 --- a/src/schema/procurement.ts +++ b/src/schema/procurement.ts @@ -1,5 +1,10 @@ export * from "../entity/procurement/procurement_category"; export * from "../entity/procurement/procurement_vendor"; export * from "../entity/procurement/procurement_project_yearly"; +export * from "../entity/procurement/procurement_tender"; +export * from "../entity/procurement/procurement_checklist_payment"; +export * from "../entity/procurement/procurement_checklist_payment_item"; +export * from "../entity/procurement/procurement_checklist_payment_document"; +export * from "../entity/procurement/procurement_checklist_payment_approval"; export * from "../types/procurement"; diff --git a/src/types/procurement.ts b/src/types/procurement.ts index be8521b..b5a9689 100644 --- a/src/types/procurement.ts +++ b/src/types/procurement.ts @@ -20,3 +20,44 @@ export enum ProcurementMethod { NCB = "NCB", ICB = "ICB", } + +export enum ProcurementTenderStatus { + ON_GOING = "ON_GOING", + COMPLETED = "COMPLETED", + CANCELLED = "CANCELLED", +} + +export enum ProcurementChecklistPaymentItemType { + ADVANCE_FUND = "advance_fund", + FCP_CPV = "fcp_cpv", + PRT = "prt", + PAYMENT_ORDER = "payment_order", + OBLIGATION = "obligation", + PAYMENT_REQUEST = "payment_request", + CHEQUE = "cheque", + INVOICE = "invoice", + ASSET_REGISTRATION = "asset_registration", + AND_RECOMMENDATION = "and_recomendation", + SERVICE_REPORT = "service_report", + FINANCE_CODE = "finance_code", + OTHER_DOCUMENT = "other_document", +} + +export enum ProcurementChecklistPaymentApprovalRole { + PREPARER = "preparer", + VERIFIER = "verifier", + APPROVER = "approver", +} + +export enum ProcurementChecklistPaymentStatus { + DRAFT = "draft", + PENDING_VERIFY = "pending_verifier", + PENDING_APPROVE = "pending_approver", + SUCCESS = "success", + REJECTED = "rejected", +} + +export enum ProcurementChecklistPaymentType { + SALARY_PAYMENT = "salary_payment", + DIRECT_PAYMENT = "direct_payment", +} From 3fbb337308f0aee271f81f78052e623407f7c2cb Mon Sep 17 00:00:00 2001 From: Rizki Date: Wed, 28 Jan 2026 13:20:19 +0700 Subject: [PATCH 3/8] upd --- src/entity/procurement/procurement_project_yearly.ts | 3 --- src/types/procurement.ts | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/entity/procurement/procurement_project_yearly.ts b/src/entity/procurement/procurement_project_yearly.ts index 0d8c3c9..5f4cc41 100644 --- a/src/entity/procurement/procurement_project_yearly.ts +++ b/src/entity/procurement/procurement_project_yearly.ts @@ -49,9 +49,6 @@ export class ProcurementProjectYearly { // SPECIFICATION & PROCESS // ========================= - @Column({ type: "text", nullable: true }) - specification: string; // Detail Specification / TOR / SOW - @Column({ type: "varchar", length: 100, nullable: true }) preparation_status: ProcurementPreparationStatus; // Status preparation (ready / not ready) diff --git a/src/types/procurement.ts b/src/types/procurement.ts index b5a9689..09cb11b 100644 --- a/src/types/procurement.ts +++ b/src/types/procurement.ts @@ -8,6 +8,8 @@ export enum ProcurementStatusType { export enum ProcurementPreparationStatus { ready = "ready", + completed = "completed", + approve = "approve", not_ready = "not_ready", } From 8af6839ec7dcf0b70372c32bc222feda0d4fbf6f Mon Sep 17 00:00:00 2001 From: Rizki Date: Thu, 29 Jan 2026 11:22:26 +0700 Subject: [PATCH 4/8] procurement tender --- src/entity/procurement/procurement_tender.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entity/procurement/procurement_tender.ts b/src/entity/procurement/procurement_tender.ts index 46a2761..5b9c884 100644 --- a/src/entity/procurement/procurement_tender.ts +++ b/src/entity/procurement/procurement_tender.ts @@ -34,7 +34,7 @@ export class ProcurementTender { tender_name: string; @Column({ length: 32 }) - tender_type: string; // Tender / RFQ / etc + tender_type: string; // Tender @Column({ type: "float8", nullable: true }) planning_price: number; From 4687c7154c80f96b204e7364a60a28584343dbba Mon Sep 17 00:00:00 2001 From: Rizki Date: Thu, 29 Jan 2026 12:01:17 +0700 Subject: [PATCH 5/8] add PO --- .../procurement/procurement_purchase_order.ts | 131 ++++++++++++++++++ .../procurement_purchase_order_item.ts | 27 ++++ src/schema/procurement.ts | 2 + src/types/procurement.ts | 6 + 4 files changed, 166 insertions(+) create mode 100644 src/entity/procurement/procurement_purchase_order.ts create mode 100644 src/entity/procurement/procurement_purchase_order_item.ts diff --git a/src/entity/procurement/procurement_purchase_order.ts b/src/entity/procurement/procurement_purchase_order.ts new file mode 100644 index 0000000..05d62b1 --- /dev/null +++ b/src/entity/procurement/procurement_purchase_order.ts @@ -0,0 +1,131 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, ManyToOne, OneToMany, JoinColumn } from "typeorm"; + +import { ProcurementTender } from "./procurement_tender"; +import { ProcurementVendor } from "./procurement_vendor"; +import { ProcurementPOStatus } from "../../types/procurement"; +import { HrmsEmployee } from "../hrms/hrms_employee"; +import { FinancePurchaseRequest } from "../finance/finance_purchase_requests"; +import { FinanceCpv } from "../finance/finance_cpvs"; +import { ProcurementPurchaseOrderItem } from "./procurement_purchase_order_item"; + +@Entity("procurement_purchase_order", { schema: "procurement" }) +export class ProcurementPurchaseOrder { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => ProcurementTender, { nullable: false }) + @JoinColumn() + tender: ProcurementTender; // Tender + + @Column({ type: "varchar", length: 50, unique: true }) + code: string; // Po Code Automaticaly + + @Column({ type: "varchar", length: 50, unique: true }) + po_number: string; // Numero Ordem de Compra + + @Column({ type: "date" }) + po_date: Date; // Data Ordem de Compra + + @Column({ type: "text", nullable: true }) + address: string; // Morada / Address + + @Column({ type: "text", nullable: true }) + attention_to: string; // Send all queries about this order to the procurement office marked to + + @Column({ type: "text", nullable: true }) + amandement_number: string; // NNumero de Emenda + + // ========================= + // DELIVERY INFO + // ========================= + + @Column({ type: "text", nullable: true }) + delivery_to: string; // Entregar a / Delivery to + + @Column({ type: "date", nullable: true }) + delivery_start_date: Date; // Data de Entrage / Delivery Date start + + @Column({ type: "date", nullable: true }) + delivery_end_date: Date; // Data de Entrage / Delivery Date end + + @Column({ type: "text", nullable: true }) + delivery_terms: string; // Pontos & termos de entrega + + @ManyToOne(() => ProcurementVendor, { nullable: false }) + @JoinColumn() + vendor: ProcurementVendor; // Vendedor / Vendor + + @Column({ type: "text", nullable: true }) + status: ProcurementPOStatus; // Approved / Rejected / Pending + + // ========================= + // APPROVAL + // ========================= + + @ManyToOne(() => HrmsEmployee, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + prepared_by: HrmsEmployee; // Preparado por + + @Column({ type: "text", nullable: true }) + prepared_by_signature_image: string; + + @Column({ type: "text", nullable: true }) + prepared_by_signature_hash: string; + + @ManyToOne(() => HrmsEmployee, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + approved_by: HrmsEmployee; // Aprovado por + + @Column({ type: "text", nullable: true }) + approved_by_signature_image: string; + + @Column({ type: "text", nullable: true }) + approved_by_signature_hash: string; + + // ========================= + // Requisitioner + // ========================= + + @Column({ type: "text", nullable: true }) + requisitioner: string; // Requisitante / Requisitioner + + @ManyToOne(() => FinancePurchaseRequest, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + pr_number: FinancePurchaseRequest; // Numero de Requisicao de Compra + + @ManyToOne(() => FinanceCpv, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + cpv: FinanceCpv; // Numero de FCP / CPV Number : + + // ========================= + // RELATION + // ========================= + + @OneToMany(() => ProcurementPurchaseOrderItem, (item) => item.purchase_order, { cascade: true }) + items: ProcurementPurchaseOrderItem[]; + + @Column({ type: "float8", default: 0 }) + total_amount_usd: number; // Total Montante (USD) + + // ========================= + // AUDIT + // ========================= + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + created_by: string; + + @UpdateDateColumn({ nullable: true }) + updated_at: Date; + + @Column({ nullable: true }) + updated_by: string; + + @DeleteDateColumn({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true }) + deleted_by: string; +} diff --git a/src/entity/procurement/procurement_purchase_order_item.ts b/src/entity/procurement/procurement_purchase_order_item.ts new file mode 100644 index 0000000..8d67ad2 --- /dev/null +++ b/src/entity/procurement/procurement_purchase_order_item.ts @@ -0,0 +1,27 @@ +import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from "typeorm"; +import { ProcurementPurchaseOrder } from "./procurement_purchase_order"; + +@Entity("procurement_purchase_order_item", { schema: "procurement" }) +export class ProcurementPurchaseOrderItem { + @PrimaryGeneratedColumn("uuid") + id: string; + + @ManyToOne(() => ProcurementPurchaseOrder, (po) => po.items, { onDelete: "CASCADE" }) + @JoinColumn() + purchase_order: ProcurementPurchaseOrder; + + @Column({ type: "text" }) + description: string; // Descricao / Description + + @Column({ type: "varchar", length: 50, nullable: true }) + unit: string; // Unidade + + @Column({ type: "int" }) + quantity: number; // Quantidade + + @Column({ type: "float8" }) + unit_price_usd: number; // Preco Unitario (USD) + + @Column({ type: "float8" }) + amount_usd: number; // Montante (qty * unit price) +} diff --git a/src/schema/procurement.ts b/src/schema/procurement.ts index 092d340..3922a13 100644 --- a/src/schema/procurement.ts +++ b/src/schema/procurement.ts @@ -6,5 +6,7 @@ export * from "../entity/procurement/procurement_checklist_payment"; export * from "../entity/procurement/procurement_checklist_payment_item"; export * from "../entity/procurement/procurement_checklist_payment_document"; export * from "../entity/procurement/procurement_checklist_payment_approval"; +export * from "../entity/procurement/procurement_purchase_order"; +export * from "../entity/procurement/procurement_purchase_order_item"; export * from "../types/procurement"; diff --git a/src/types/procurement.ts b/src/types/procurement.ts index 09cb11b..1c4cd03 100644 --- a/src/types/procurement.ts +++ b/src/types/procurement.ts @@ -63,3 +63,9 @@ export enum ProcurementChecklistPaymentType { SALARY_PAYMENT = "salary_payment", DIRECT_PAYMENT = "direct_payment", } + +export enum ProcurementPOStatus { + APPROVED = "APPROVED", + REJECTED = "REJECTED", + PENDING = "PENDING", +} \ No newline at end of file From 5eb3460ab55df5d583e22059a5a126b2436928ac Mon Sep 17 00:00:00 2001 From: Rizki Date: Thu, 29 Jan 2026 15:15:48 +0700 Subject: [PATCH 6/8] payment request --- .../procurement_payment_request.ts | 216 ++++++++++++++++++ src/schema/procurement.ts | 1 + src/types/procurement.ts | 7 + 3 files changed, 224 insertions(+) create mode 100644 src/entity/procurement/procurement_payment_request.ts diff --git a/src/entity/procurement/procurement_payment_request.ts b/src/entity/procurement/procurement_payment_request.ts new file mode 100644 index 0000000..1f5c868 --- /dev/null +++ b/src/entity/procurement/procurement_payment_request.ts @@ -0,0 +1,216 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, ManyToOne, JoinColumn } from "typeorm"; + +import { ProcurementPurchaseOrder } from "./procurement_purchase_order"; +import { ProcurementVendor } from "./procurement_vendor"; +import { FinancePurchaseRequest } from "../finance/finance_purchase_requests"; +import { FinanceCpv } from "../finance/finance_cpvs"; +import { HrmsEmployee } from "../hrms/hrms_employee"; +import { ProcurementPRCStatus } from "../../types/procurement"; + +@Entity("procurement_payment_request", { schema: "procurement" }) +export class ProcurementPaymentRequest { + @PrimaryGeneratedColumn("uuid") + id: string; + + // ========================= + // HEADER + // ========================= + + @Column({ type: "varchar", length: 50, unique: true }) + code: string; // PRC Code Automaticaly + + @Column({ type: "varchar", length: 50, unique: true }) + prc_number: string; // Payment Request Number (2025-0177) + + @Column({ type: "date" }) + prc_date: Date; // Payment Request Date + + @Column({ type: "varchar", length: 150, nullable: true }) + to: string; // To (Director Finance) + + @Column({ type: "varchar", length: 150, nullable: true }) + from: string; // From (Procurement Unit) + + @Column({ type: "varchar", length: 100, nullable: true }) + payment_type: string; // Payment for Procurement + + @Column({ type: "varchar", length: 50, nullable: true }) + status: ProcurementPRCStatus; // Draft / Received / Approved / Rejected + + // ========================= + // REFERENCES + // ========================= + + @ManyToOne(() => FinanceCpv, { nullable: true, onDelete: "NO ACTION" }) + @JoinColumn() + cpv: FinanceCpv; // CPV Number + + @Column({ type: "float8", nullable: true }) + cpv_amount_usd: number; + + @ManyToOne(() => ProcurementPurchaseOrder, { nullable: true, onDelete: "NO ACTION" }) + @JoinColumn() + po: ProcurementPurchaseOrder; // PO Number + + @Column({ type: "float8", nullable: true }) + po_amount_usd: number; + + @ManyToOne(() => FinancePurchaseRequest, { nullable: true, onDelete: "NO ACTION" }) + @JoinColumn() + pr: FinancePurchaseRequest; // PR Number + + @Column({ type: "float8", nullable: true }) + pr_amount_usd: number; + + @Column({ type: "varchar", length: 100, nullable: true }) + contract_number: string; // Contract Number + + @Column({ type: "date", nullable: true }) + contract_date: Date; + + // ========================= + // PAYMENT REQUEST DETAIL + // ========================= + + @Column({ type: "text", nullable: true }) + payment_description: string; // Payment Request Description + + @ManyToOne(() => ProcurementVendor, { nullable: true }) + @JoinColumn() + vendor: ProcurementVendor; // Supplier / Contractor + + @Column({ type: "varchar", length: 100, nullable: true }) + invoice_number: string; + + @Column({ type: "date", nullable: true }) + invoice_date: Date; + + @Column({ type: "varchar", length: 20, nullable: true }) + currency: string; // USD + + @Column({ type: "float8", nullable: true }) + amount_claimed: number; + + // ========================= + // DEDUCTIONS + // ========================= + + @Column({ type: "float8", nullable: true }) + advance_payment_percent: number; + + @Column({ type: "float8", nullable: true }) + advance_payment_amount: number; + + @Column({ type: "float8", nullable: true }) + retention_percent: number; + + @Column({ type: "float8", nullable: true }) + retention_amount: number; + + @Column({ type: "float8", nullable: true }) + deduction_tax_percent: number; + + @Column({ type: "float8", nullable: true }) + deduction_tax_amount: number; + + @Column({ type: "float8", nullable: true }) + deduction_penalty_percent: number; + + @Column({ type: "float8", nullable: true }) + deduction_penalty_amount: number; + + @Column({ type: "float8", nullable: true }) + net_amount_paid: number; // NET TO BE PAID + + // ========================= + // PAYMENT STATUS + // ========================= + + @Column({ type: "boolean", default: false }) + is_partial: boolean; // Partial (YES/NO) + + @Column({ type: "boolean", default: false }) + is_final: boolean; // Final (YES/NO) + + @Column({ type: "float8", nullable: true }) + balance_remaining: number; // Balance excluding outstanding PRC + + // ========================= + // BANKING DETAILS + // ========================= + + @Column({ type: "varchar", length: 150, nullable: true }) + bank_name: string; + + @Column({ type: "varchar", length: 100, nullable: true }) + bank_swift_aba_bsb: string; + + @Column({ type: "text", nullable: true }) + bank_account_name: string; + + @Column({ type: "varchar", length: 150, nullable: true }) + bank_account_number: string; + + // ========================= + // DEDUCTION ACCOUNT + // ========================= + + @Column({ type: "varchar", length: 150, nullable: true }) + deduction_bank_name: string; + + @Column({ type: "text", nullable: true }) + deduction_bank_address: string; + + @Column({ type: "varchar", length: 50, nullable: true }) + deduction_account_no: string; + + @Column({ type: "varchar", length: 150, nullable: true }) + deduction_account_name: string; + + // ========================= + // APPROVAL FLOW + // ========================= + + @ManyToOne(() => HrmsEmployee, { nullable: true }) + @JoinColumn() + prepared_by: HrmsEmployee; + + @Column({ type: "varchar", length: 150, nullable: true }) + prepared_by_position: string; + + @ManyToOne(() => HrmsEmployee, { nullable: true }) + @JoinColumn() + verified_by: HrmsEmployee; + + @Column({ type: "varchar", length: 150, nullable: true }) + verified_by_position: string; + + @ManyToOne(() => HrmsEmployee, { nullable: true }) + @JoinColumn() + certified_by: HrmsEmployee; + + @Column({ type: "varchar", length: 150, nullable: true }) + certified_by_position: string; + + // ========================= + // AUDIT + // ========================= + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true }) + created_by: string; + + @UpdateDateColumn({ nullable: true }) + updated_at: Date; + + @Column({ nullable: true }) + updated_by: string; + + @DeleteDateColumn({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true }) + deleted_by: string; +} diff --git a/src/schema/procurement.ts b/src/schema/procurement.ts index 3922a13..7347adc 100644 --- a/src/schema/procurement.ts +++ b/src/schema/procurement.ts @@ -8,5 +8,6 @@ export * from "../entity/procurement/procurement_checklist_payment_document"; export * from "../entity/procurement/procurement_checklist_payment_approval"; export * from "../entity/procurement/procurement_purchase_order"; export * from "../entity/procurement/procurement_purchase_order_item"; +export * from "../entity/procurement/procurement_payment_request"; export * from "../types/procurement"; diff --git a/src/types/procurement.ts b/src/types/procurement.ts index 1c4cd03..ef75323 100644 --- a/src/types/procurement.ts +++ b/src/types/procurement.ts @@ -68,4 +68,11 @@ export enum ProcurementPOStatus { APPROVED = "APPROVED", REJECTED = "REJECTED", PENDING = "PENDING", +} + +export enum ProcurementPRCStatus { + DRAFT = "DRAFT", + APPROVED = "APPROVED", + REJECTED = "REJECTED", + RECEIVED = "RECEIVED", } \ No newline at end of file From 56b88f814b93ff4cdbb166b03426d60c29e0d6c9 Mon Sep 17 00:00:00 2001 From: Rizki Date: Fri, 30 Jan 2026 19:42:06 +0700 Subject: [PATCH 7/8] working order --- .../procurement_work_order_copies.ts | 51 +++++++++ .../procurement/procurement_work_orders.ts | 106 ++++++++++++++++++ src/schema/procurement.ts | 2 + src/types/procurement.ts | 14 ++- 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/entity/procurement/procurement_work_order_copies.ts create mode 100644 src/entity/procurement/procurement_work_orders.ts diff --git a/src/entity/procurement/procurement_work_order_copies.ts b/src/entity/procurement/procurement_work_order_copies.ts new file mode 100644 index 0000000..424f8c3 --- /dev/null +++ b/src/entity/procurement/procurement_work_order_copies.ts @@ -0,0 +1,51 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, ManyToOne, JoinColumn } from "typeorm"; +import { ProcurementWorkOrder } from "./procurement_work_orders"; + +@Entity("procurement_work_order_copies", { schema: "procurement" }) +export class ProcurementWorkOrderCopy { + @PrimaryGeneratedColumn("uuid") + id: string; + + // ========================= + // REFERENCE + // ========================= + + @ManyToOne(() => ProcurementWorkOrder, (wo) => wo.copies, { onDelete: "CASCADE", nullable: false }) + @JoinColumn() + work_order: ProcurementWorkOrder; + + // ========================= + // COPY INFORMATION + // ========================= + + @Column({ length: 32 }) + label: string; // COPIA 1, COPIA 2, COPIA 3 + + @Column({ length: 256 }) + recipient: string; // Exe. Presidente do C.A. da ANATL, E.P. + + @Column({ type: "int" }) + order: number; // 1, 2, 3 - untuk urutan display + + // ========================= + // AUDIT + // ========================= + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @UpdateDateColumn({ nullable: true }) + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @DeleteDateColumn({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/entity/procurement/procurement_work_orders.ts b/src/entity/procurement/procurement_work_orders.ts new file mode 100644 index 0000000..c75b577 --- /dev/null +++ b/src/entity/procurement/procurement_work_orders.ts @@ -0,0 +1,106 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, ManyToOne, JoinColumn, OneToMany } from "typeorm"; +import { ProcurementTender } from "./procurement_tender"; +import { ProcurementWorkOrderStatus } from "../../types/procurement"; +import { ProcurementWorkOrderCopy } from "./procurement_work_order_copies"; + +@Entity("procurement_work_orders", { schema: "procurement" }) +export class ProcurementWorkOrder { + @PrimaryGeneratedColumn("uuid") + id: string; + + // ========================= + // REFERENCE + // ========================= + + @ManyToOne(() => ProcurementTender, { onDelete: "NO ACTION", nullable: false }) + @JoinColumn() + tender: ProcurementTender; + + @Column({ length: 64 }) + reference_number: string; // 142/ANATL,E.P./U-APROV./VII/2025 + + // ========================= + // RECIPIENT INFORMATION + // ========================= + + @Column({ length: 256 }) + recipient_name: string; // SR. JUSCELINO DE JESUS PEREIRA + + @Column({ type: "text" }) + subject: string; // ORDEM DO SERVISU MANUTENSAUN EDIFISIU... + + // ========================= + // CONTENT + // ========================= + + @Column({ type: "text" }) + content: string; // Full work order content/body + + // ========================= + // SIGNATURE + // ========================= + + @Column({ length: 256, nullable: true }) + signer_name: string; // ENG. JOSÉ ANTÓNÍO SANCHES + + @Column({ length: 256, nullable: true }) + signer_position: string; // DIRECTOR U-APROVISIONAMENTO ANATL, E.P. + + @Column({ type: "date", nullable: true }) + signed_date: Date; + + // ========================= + // STATUS & METADATA + // ========================= + + @Column({ length: 32, default: "draft" }) + status: ProcurementWorkOrderStatus; // draft, issued, completed, cancelled + + @Column({ type: "date", nullable: true }) + issue_date: Date; // When the work order was officially issued + + @Column({ type: "date", nullable: true }) + start_date: Date; // Expected start date of work + + @Column({ type: "date", nullable: true }) + completion_date: Date; // Expected completion date + + // ========================= + // DOCUMENT + // ========================= + + @Column({ length: 256, nullable: true }) + document_file_url: string; // URL to generated PDF + + @Column({ type: "date", nullable: true }) + document_generated_at: Date; + + // ========================= + // COPIES + // ========================= + + @OneToMany(() => ProcurementWorkOrderCopy, (copy) => copy.work_order, { cascade: true }) + copies: ProcurementWorkOrderCopy[]; + + // ========================= + // AUDIT + // ========================= + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @UpdateDateColumn({ nullable: true }) + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @DeleteDateColumn({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/schema/procurement.ts b/src/schema/procurement.ts index 7347adc..3d61c0a 100644 --- a/src/schema/procurement.ts +++ b/src/schema/procurement.ts @@ -9,5 +9,7 @@ export * from "../entity/procurement/procurement_checklist_payment_approval"; export * from "../entity/procurement/procurement_purchase_order"; export * from "../entity/procurement/procurement_purchase_order_item"; export * from "../entity/procurement/procurement_payment_request"; +export * from "../entity/procurement/procurement_work_orders"; +export * from "../entity/procurement/procurement_work_order_copies"; export * from "../types/procurement"; diff --git a/src/types/procurement.ts b/src/types/procurement.ts index ef75323..16c163a 100644 --- a/src/types/procurement.ts +++ b/src/types/procurement.ts @@ -75,4 +75,16 @@ export enum ProcurementPRCStatus { APPROVED = "APPROVED", REJECTED = "REJECTED", RECEIVED = "RECEIVED", -} \ No newline at end of file +} + +// File: src/types/procurement.ts + +export enum ProcurementWorkOrderStatus { + DRAFT = "DRAFT", + PENDING_APPROVAL = "PENDING_APPROVAL", + APPROVED = "APPROVED", + ISSUED = "ISSUED", + IN_PROGRESS = "IN_PROGRESS", + COMPLETED = "COMPLETED", + CANCELLED = "CANCELLED", +} From ba2bcf56c4310a0c6fdf0f181a6d42b1e05b7683 Mon Sep 17 00:00:00 2001 From: Rizki Date: Sun, 1 Feb 2026 16:42:21 +0700 Subject: [PATCH 8/8] procurement surveys --- src/entity/procurement/procurement_surveys.ts | 58 +++++++++++++++++++ src/schema/procurement.ts | 1 + src/types/procurement.ts | 11 +++- 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/entity/procurement/procurement_surveys.ts diff --git a/src/entity/procurement/procurement_surveys.ts b/src/entity/procurement/procurement_surveys.ts new file mode 100644 index 0000000..bc49663 --- /dev/null +++ b/src/entity/procurement/procurement_surveys.ts @@ -0,0 +1,58 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, DeleteDateColumn, ManyToOne, JoinColumn } from "typeorm"; +import { ProcurementVendor } from "./procurement_vendor"; + +@Entity("procurement_surveys", { schema: "procurement" }) +export class ProcurementSurvey { + @PrimaryGeneratedColumn("uuid") + id: string; + + // ========================= + // SURVEY INFORMATION + // ========================= + + @Column({ type: "date" }) + data_date: Date; // DATA field + + @Column({ type: "date" }) + survey_date: Date; // TANGGAL SURVEY field + + // ========================= + // COMPANY & LOCATION + // ========================= + + @ManyToOne(() => ProcurementVendor, { onDelete: "NO ACTION", nullable: true }) + @JoinColumn() + company: ProcurementVendor; // KOMPANYA + + @Column({ length: 256 }) + location: string; // LOCATION - CRISTO REI, DILI + + // ========================= + // SURVEY RESULT + // ========================= + + @Column({ type: "text" }) + survey_result: string; // HASIL SURVEY + + // ========================= + // AUDIT + // ========================= + + @CreateDateColumn() + created_at: Date; + + @Column({ nullable: true, length: 256 }) + created_by: string; + + @UpdateDateColumn({ nullable: true }) + updated_at: Date; + + @Column({ nullable: true, length: 256 }) + updated_by: string; + + @DeleteDateColumn({ nullable: true }) + deleted_at: Date; + + @Column({ nullable: true, length: 256 }) + deleted_by: string; +} diff --git a/src/schema/procurement.ts b/src/schema/procurement.ts index 3d61c0a..705ef0f 100644 --- a/src/schema/procurement.ts +++ b/src/schema/procurement.ts @@ -11,5 +11,6 @@ export * from "../entity/procurement/procurement_purchase_order_item"; export * from "../entity/procurement/procurement_payment_request"; export * from "../entity/procurement/procurement_work_orders"; export * from "../entity/procurement/procurement_work_order_copies"; +export * from "../entity/procurement/procurement_surveys"; export * from "../types/procurement"; diff --git a/src/types/procurement.ts b/src/types/procurement.ts index 16c163a..16883aa 100644 --- a/src/types/procurement.ts +++ b/src/types/procurement.ts @@ -77,8 +77,6 @@ export enum ProcurementPRCStatus { RECEIVED = "RECEIVED", } -// File: src/types/procurement.ts - export enum ProcurementWorkOrderStatus { DRAFT = "DRAFT", PENDING_APPROVAL = "PENDING_APPROVAL", @@ -88,3 +86,12 @@ export enum ProcurementWorkOrderStatus { COMPLETED = "COMPLETED", CANCELLED = "CANCELLED", } + +export enum ProcurementSurveyStatus { + DRAFT = "DRAFT", + APPROVED = "APPROVED", + ISSUED = "ISSUED", + IN_PROGRESS = "IN_PROGRESS", + COMPLETED = "COMPLETED", + CANCELLED = "CANCELLED", +}