@@ -2,6 +2,13 @@ export type User = {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
purchasing_role?:
|
||||
| 'requester'
|
||||
| 'department_head'
|
||||
| 'procurement'
|
||||
| 'finance'
|
||||
| 'warehouse'
|
||||
| 'admin';
|
||||
avatar?: string;
|
||||
email_verified_at: string | null;
|
||||
created_at: string;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
export type ConflictDeclaration = {
|
||||
id: number;
|
||||
user_id: number;
|
||||
supplier_id: number | null;
|
||||
requisition_id: number | null;
|
||||
has_conflict: boolean;
|
||||
known_since: string;
|
||||
declared_at: string;
|
||||
reason: string;
|
||||
previous_id: number | null;
|
||||
root_id: number | null;
|
||||
author: { name: string };
|
||||
supplier: { name: string } | null;
|
||||
requisition: { number: string } | null;
|
||||
successor?: { id: number } | null;
|
||||
};
|
||||
|
||||
export function conflictScope(declaration: ConflictDeclaration) {
|
||||
return [declaration.supplier?.name, declaration.requisition?.number]
|
||||
.filter(Boolean)
|
||||
.join(' · ');
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
export type Department = { id: number; name: string };
|
||||
export type CostCenter = {
|
||||
id: number;
|
||||
department_id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
};
|
||||
export type Company = {
|
||||
id: number;
|
||||
name: string;
|
||||
first_limit_minor: number;
|
||||
second_limit_minor: number;
|
||||
approval_includes_tax: boolean;
|
||||
rules_provisional: boolean;
|
||||
};
|
||||
export type RequisitionItem = {
|
||||
id?: number;
|
||||
description: string;
|
||||
category: string;
|
||||
purchase_type: string;
|
||||
quantity: string;
|
||||
unit: string;
|
||||
unit_price_minor: number;
|
||||
tax_rate: string;
|
||||
subtotal_minor: number;
|
||||
tax_minor: number;
|
||||
total_minor: number;
|
||||
};
|
||||
export type ApprovalStep = {
|
||||
id: number;
|
||||
position: number;
|
||||
role: string;
|
||||
decision: string;
|
||||
approver_id: number | null;
|
||||
comment: string | null;
|
||||
decided_at: string | null;
|
||||
};
|
||||
export type Requisition = {
|
||||
id: number;
|
||||
number: string;
|
||||
status: string;
|
||||
priority: string;
|
||||
needed_by: string;
|
||||
justification: string;
|
||||
cost_center_id: number;
|
||||
subtotal_minor: number;
|
||||
tax_minor: number;
|
||||
total_minor: number;
|
||||
created_at: string;
|
||||
requester?: { name: string };
|
||||
department?: Department;
|
||||
cost_center?: CostCenter;
|
||||
items: RequisitionItem[];
|
||||
steps: ApprovalStep[];
|
||||
approval_snapshot?: {
|
||||
rules_provisional: boolean;
|
||||
approval_includes_tax: boolean;
|
||||
} | null;
|
||||
};
|
||||
export const roleLabels: Record<string, string> = {
|
||||
requester: 'Solicitante',
|
||||
department_head: 'Chefe de departamento',
|
||||
procurement: 'Procurement',
|
||||
finance: 'Finanças',
|
||||
warehouse: 'Recepção / Armazém',
|
||||
admin: 'Administrador',
|
||||
};
|
||||
export const statusLabels: Record<string, string> = {
|
||||
draft: 'Rascunho',
|
||||
pending: 'Em aprovação',
|
||||
approved: 'Aprovada',
|
||||
rejected: 'Rejeitada',
|
||||
};
|
||||
export const priorityLabels: Record<string, string> = {
|
||||
normal: 'Normal',
|
||||
high: 'Alta',
|
||||
urgent: 'Urgente',
|
||||
};
|
||||
export const money = (minor: number) =>
|
||||
new Intl.NumberFormat('pt-MZ', {
|
||||
style: 'currency',
|
||||
currency: 'MZN',
|
||||
}).format(minor / 100);
|
||||
export const date = (value: string) =>
|
||||
new Intl.DateTimeFormat('pt-MZ').format(
|
||||
new Date(value.slice(0, 10) + 'T12:00:00'),
|
||||
);
|
||||
@@ -0,0 +1,25 @@
|
||||
export type MatrixRow = {
|
||||
id: number; reference: string; supplier: { name: string }; supplier_id: number;
|
||||
eligible: boolean; ineligibility_reasons: string[]; evaluation_count: number;
|
||||
score: number | null; score_minor: number | null; subtotal_minor: number; tax_minor: number; total_minor: number;
|
||||
evaluations: { evaluator_id: number; quality: string; history: string; payment: string; comment: string }[];
|
||||
};
|
||||
export type AwardApproval = { id: number; position: number; role: string; decision: string; approver_id: number | null; comment: string | null };
|
||||
export type PurchaseAward = {
|
||||
id: number; requisition_id: number; quotation_id: number; status: string; justification: string;
|
||||
subtotal_minor: number; tax_minor: number; total_minor: number; delivery_date: string; delivery_location: string;
|
||||
approval_snapshot: { approval_includes_tax: boolean; rules_provisional: boolean }; approvals: AwardApproval[];
|
||||
};
|
||||
export type OrderItem = { id: number; description: string; quantity: string; unit: string; unit_price_minor: number; tax_rate: string; subtotal_minor: number; tax_minor: number; total_minor: number };
|
||||
export type PurchaseOrder = {
|
||||
id: number; number: string; requisition_id: number; issued_at: string; currency: string;
|
||||
subtotal_minor: number; tax_minor: number; total_minor: number; items: OrderItem[];
|
||||
snapshot: {
|
||||
company: { name: string }; department: { name: string }; cost_center: { code: string; name: string };
|
||||
requisition: { number: string }; issuer: { name: string }; requester: { name: string };
|
||||
supplier: { name: string; nuit: string; contact: string; phone: string; email: string; address: string };
|
||||
quotation: { reference: string; payment_terms: string }; award: { justification: string; delivery_date: string; delivery_location: string };
|
||||
approval_rules: { approval_includes_tax: boolean; rules_provisional: boolean };
|
||||
decision_matrix: MatrixRow[]; final_approvals: AwardApproval[];
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
export type Supplier = {
|
||||
id: number;
|
||||
name: string;
|
||||
nuit: string;
|
||||
contact: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
address: string;
|
||||
category: string;
|
||||
beneficiaries: string;
|
||||
document_references: string;
|
||||
diligence_notes: string;
|
||||
blocked: boolean;
|
||||
next_review: string;
|
||||
status: string;
|
||||
review_comment: string | null;
|
||||
version: number;
|
||||
};
|
||||
|
||||
export const supplierFields = {
|
||||
name: 'Nome legal',
|
||||
nuit: 'NUIT (9 dígitos)',
|
||||
contact: 'Pessoa de contacto',
|
||||
email: 'Email',
|
||||
phone: 'Telefone',
|
||||
address: 'Morada',
|
||||
category: 'Categoria de fornecimento',
|
||||
beneficiaries: 'Beneficiários efectivos',
|
||||
document_references: 'Referências dos documentos verificados',
|
||||
diligence_notes: 'Resultado da diligência devida',
|
||||
next_review: 'Próxima revisão',
|
||||
};
|
||||
export const supplierStatuses: Record<string, string> = {
|
||||
pending: 'Pendente de validação',
|
||||
active: 'Activo',
|
||||
suspended: 'Suspenso',
|
||||
};
|
||||
export const documentTypes: Record<string, string> = {
|
||||
license: 'Alvará / licença',
|
||||
tax: 'Situação fiscal',
|
||||
conflict: 'Declaração de conflitos',
|
||||
other: 'Outro documento',
|
||||
};
|
||||
Reference in New Issue
Block a user