task-k.1
This commit is contained in:
@@ -394,6 +394,28 @@ export const crmEnquiryAttachments = pgTable('crm_enquiry_attachments', {
|
||||
deletedAt: timestamp('deleted_at', { withTimezone: true })
|
||||
});
|
||||
|
||||
export const crmReportDefinitions = pgTable(
|
||||
'crm_report_definitions',
|
||||
{
|
||||
id: text('id').primaryKey(),
|
||||
organizationId: text('organization_id').notNull(),
|
||||
code: text('code').notNull(),
|
||||
name: text('name').notNull(),
|
||||
description: text('description'),
|
||||
category: text('category').notNull(),
|
||||
isSystem: boolean('is_system').default(true).notNull(),
|
||||
isActive: boolean('is_active').default(true).notNull(),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
|
||||
},
|
||||
(table) => ({
|
||||
organizationCodeIdx: uniqueIndex('crm_report_definitions_org_code_idx').on(
|
||||
table.organizationId,
|
||||
table.code
|
||||
)
|
||||
})
|
||||
);
|
||||
|
||||
export const crmQuotations = pgTable(
|
||||
'crm_quotations',
|
||||
{
|
||||
|
||||
@@ -38,6 +38,13 @@ type TemplateMappingSeed = {
|
||||
columns?: TemplateColumnSeed[];
|
||||
};
|
||||
|
||||
type ReportDefinitionSeed = {
|
||||
code: string;
|
||||
name: string;
|
||||
description: string;
|
||||
category: string;
|
||||
};
|
||||
|
||||
function loadEnvFile(filePath: string) {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return;
|
||||
@@ -334,9 +341,52 @@ const FOUNDATION_OPTIONS = {
|
||||
{ code: 'facebook', label: 'Facebook', value: 'facebook', sortOrder: 4 },
|
||||
{ code: 'line', label: 'LINE', value: 'line', sortOrder: 5 },
|
||||
{ code: 'other', label: 'Other', value: 'other', sortOrder: 6 }
|
||||
],
|
||||
crm_report_category: [
|
||||
{ code: 'pipeline', label: 'Pipeline', value: 'pipeline', sortOrder: 1 },
|
||||
{ code: 'sales', label: 'Sales', value: 'sales', sortOrder: 2 },
|
||||
{ code: 'revenue', label: 'Revenue', value: 'revenue', sortOrder: 3 },
|
||||
{ code: 'customer', label: 'Customer', value: 'customer', sortOrder: 4 },
|
||||
{ code: 'quotation', label: 'Quotation', value: 'quotation', sortOrder: 5 },
|
||||
{ code: 'approval', label: 'Approval', value: 'approval', sortOrder: 6 },
|
||||
{ code: 'outcome', label: 'Outcome', value: 'outcome', sortOrder: 7 },
|
||||
{ code: 'executive', label: 'Executive', value: 'executive', sortOrder: 8 }
|
||||
]
|
||||
};
|
||||
|
||||
const REPORT_DEFINITIONS: ReportDefinitionSeed[] = [
|
||||
{
|
||||
code: 'lead_pipeline',
|
||||
name: 'Lead Pipeline',
|
||||
description: 'Foundation catalog entry for future lead pipeline reporting.',
|
||||
category: 'pipeline'
|
||||
},
|
||||
{
|
||||
code: 'enquiry_pipeline',
|
||||
name: 'Enquiry Pipeline',
|
||||
description: 'Foundation catalog entry for opportunity stage reporting.',
|
||||
category: 'pipeline'
|
||||
},
|
||||
{
|
||||
code: 'sales_performance',
|
||||
name: 'Sales Performance',
|
||||
description: 'Foundation catalog entry for salesperson KPI and ranking reports.',
|
||||
category: 'sales'
|
||||
},
|
||||
{
|
||||
code: 'lost_analysis',
|
||||
name: 'Lost Analysis',
|
||||
description: 'Foundation catalog entry for lost reason and competitor analysis.',
|
||||
category: 'outcome'
|
||||
},
|
||||
{
|
||||
code: 'revenue_by_customer',
|
||||
name: 'Revenue By Customer',
|
||||
description: 'Foundation catalog entry for customer revenue attribution reports.',
|
||||
category: 'revenue'
|
||||
}
|
||||
];
|
||||
|
||||
const DOCUMENT_SEQUENCES = [
|
||||
{ documentType: 'customer', prefix: 'CUS' },
|
||||
{ documentType: 'contact', prefix: 'CON' },
|
||||
@@ -972,6 +1022,43 @@ async function upsertDocumentTemplatesForOrganization(
|
||||
`;
|
||||
}
|
||||
|
||||
async function upsertReportDefinitionsForOrganization(
|
||||
sql: SqlClient,
|
||||
organization: { id: string }
|
||||
) {
|
||||
for (const definition of REPORT_DEFINITIONS) {
|
||||
await sql`
|
||||
insert into crm_report_definitions (
|
||||
id,
|
||||
organization_id,
|
||||
code,
|
||||
name,
|
||||
description,
|
||||
category,
|
||||
is_system,
|
||||
is_active
|
||||
) values (
|
||||
${crypto.randomUUID()},
|
||||
${organization.id},
|
||||
${definition.code},
|
||||
${definition.name},
|
||||
${definition.description},
|
||||
${definition.category},
|
||||
${true},
|
||||
${true}
|
||||
)
|
||||
on conflict (organization_id, code) do update
|
||||
set
|
||||
name = excluded.name,
|
||||
description = excluded.description,
|
||||
category = excluded.category,
|
||||
is_system = excluded.is_system,
|
||||
is_active = excluded.is_active,
|
||||
updated_at = now()
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
loadLocalEnv();
|
||||
|
||||
@@ -996,6 +1083,7 @@ async function main() {
|
||||
await upsertDocumentSequencesForOrganization(sql, organization.id, branchRows);
|
||||
await upsertApprovalWorkflowsForOrganization(sql, organization.id);
|
||||
await upsertDocumentTemplatesForOrganization(sql, organization);
|
||||
await upsertReportDefinitionsForOrganization(sql, organization);
|
||||
console.log(`[seed-foundation] Seeded foundation data for ${organization.name}`);
|
||||
}
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user