Phase 1: Workflows UI, Dedup/Merge UI, Import/Export UI, Print/PDF
- Workflows UI: full page with definitions/instances tabs, step editor, instance detail with approve/reject - Dedup/Merge UI: duplicate detection, side-by-side comparison, field-level merge dialog, merge history - Import/Export UI: import wizard (dry-run preview), export panel (CSV/XLSX), backend export route added - Print/PDF: PrintButton component, print.css, integrated in Contacts/Calendar/Reports/ContactDetail - Backend: GET /api/v1/export endpoint, export_companies_csv() service function - Routes: /workflows, /contacts/dedup, /import-export registered - Menu items: Workflows, Import/Export, Duplikate added to automation plugin manifest - IMPLEMENTATION_PLAN.md: audit-corrected plan for all 14 remaining features
This commit is contained in:
@@ -252,3 +252,42 @@ async def export_contacts_csv(
|
||||
]
|
||||
)
|
||||
return output.getvalue()
|
||||
|
||||
|
||||
async def export_companies_csv(
|
||||
db: AsyncSession,
|
||||
tenant_id: uuid.UUID,
|
||||
) -> str:
|
||||
"""Export companies (Contact.type == 'company') as CSV string."""
|
||||
q = (
|
||||
select(Contact)
|
||||
.where(
|
||||
Contact.tenant_id == tenant_id,
|
||||
Contact.deleted_at.is_(None),
|
||||
Contact.type == "company",
|
||||
)
|
||||
.order_by(Contact.name)
|
||||
)
|
||||
result = await db.execute(q)
|
||||
companies = result.scalars().all()
|
||||
|
||||
output = io.StringIO()
|
||||
writer = csv.writer(output)
|
||||
writer.writerow(
|
||||
["id", "type", "name", "email", "phone", "website", "city", "postalcode", "country"]
|
||||
)
|
||||
for c in companies:
|
||||
writer.writerow(
|
||||
[
|
||||
str(c.id),
|
||||
c.type or "company",
|
||||
c.name or "",
|
||||
c.email_1 or "",
|
||||
c.phone_1 or "",
|
||||
c.website or "",
|
||||
c.mailing_city or "",
|
||||
c.mailing_postalcode or "",
|
||||
c.mailing_country or "",
|
||||
]
|
||||
)
|
||||
return output.getvalue()
|
||||
|
||||
Reference in New Issue
Block a user