diff --git a/backend/app/services/psa/autotask/__init__.py b/backend/app/services/psa/autotask/__init__.py new file mode 100644 index 00000000..19019d55 --- /dev/null +++ b/backend/app/services/psa/autotask/__init__.py @@ -0,0 +1,3 @@ +from app.services.psa.autotask.provider import AutotaskProvider + +__all__ = ["AutotaskProvider"] diff --git a/backend/app/services/psa/autotask/provider.py b/backend/app/services/psa/autotask/provider.py new file mode 100644 index 00000000..ed7ca8d8 --- /dev/null +++ b/backend/app/services/psa/autotask/provider.py @@ -0,0 +1,72 @@ +"""Autotask PSA provider stub. Full implementation planned for Phase 5.""" +from __future__ import annotations + +from app.services.psa.base import PSAProvider +from app.services.psa.types import ( + ConnectionTestResult, + PSATicket, + PSANote, + PSAStatus, + PSACompany, + PSAMember, + PSAConfiguration, + PSATimeEntry, +) + + +class AutotaskProvider(PSAProvider): + """Stub provider for Autotask PSA. All methods raise NotImplementedError. + + Full implementation is planned for Phase 5. This stub allows the provider + to be registered and discovered without causing import errors. + """ + + async def test_connection(self) -> ConnectionTestResult: + raise NotImplementedError("Autotask integration coming soon") + + async def get_ticket(self, ticket_id: str) -> PSATicket: + raise NotImplementedError("Autotask integration coming soon") + + async def search_tickets(self, query: str, **filters) -> list[PSATicket]: + raise NotImplementedError("Autotask integration coming soon") + + async def post_note( + self, + ticket_id: str, + text: str, + note_type: str, + member_id: str | None = None, + ) -> PSANote: + raise NotImplementedError("Autotask integration coming soon") + + async def update_ticket_status( + self, + ticket_id: str, + status_id: int, + ) -> PSATicket: + raise NotImplementedError("Autotask integration coming soon") + + async def get_ticket_statuses(self, board_id: int) -> list[PSAStatus]: + raise NotImplementedError("Autotask integration coming soon") + + async def list_companies(self, **filters) -> list[PSACompany]: + raise NotImplementedError("Autotask integration coming soon") + + async def get_company(self, company_id: str) -> PSACompany: + raise NotImplementedError("Autotask integration coming soon") + + async def list_members(self) -> list[PSAMember]: + raise NotImplementedError("Autotask integration coming soon") + + async def get_ticket_configurations(self, ticket_id: str) -> list[PSAConfiguration]: + raise NotImplementedError("Autotask integration coming soon") + + async def create_time_entry( + self, + ticket_id: str, + member_id: str, + hours: float, + notes: str | None = None, + work_type: str | None = None, + ) -> PSATimeEntry: + raise NotImplementedError("Autotask integration coming soon") diff --git a/backend/app/services/psa/halopsa/__init__.py b/backend/app/services/psa/halopsa/__init__.py new file mode 100644 index 00000000..a69ce468 --- /dev/null +++ b/backend/app/services/psa/halopsa/__init__.py @@ -0,0 +1,3 @@ +from app.services.psa.halopsa.provider import HaloPSAProvider + +__all__ = ["HaloPSAProvider"] diff --git a/backend/app/services/psa/halopsa/provider.py b/backend/app/services/psa/halopsa/provider.py new file mode 100644 index 00000000..92e4b757 --- /dev/null +++ b/backend/app/services/psa/halopsa/provider.py @@ -0,0 +1,72 @@ +"""Halo PSA provider stub. Full implementation planned for Phase 5.""" +from __future__ import annotations + +from app.services.psa.base import PSAProvider +from app.services.psa.types import ( + ConnectionTestResult, + PSATicket, + PSANote, + PSAStatus, + PSACompany, + PSAMember, + PSAConfiguration, + PSATimeEntry, +) + + +class HaloPSAProvider(PSAProvider): + """Stub provider for Halo PSA. All methods raise NotImplementedError. + + Full implementation is planned for Phase 5. This stub allows the provider + to be registered and discovered without causing import errors. + """ + + async def test_connection(self) -> ConnectionTestResult: + raise NotImplementedError("Halo PSA integration coming soon") + + async def get_ticket(self, ticket_id: str) -> PSATicket: + raise NotImplementedError("Halo PSA integration coming soon") + + async def search_tickets(self, query: str, **filters) -> list[PSATicket]: + raise NotImplementedError("Halo PSA integration coming soon") + + async def post_note( + self, + ticket_id: str, + text: str, + note_type: str, + member_id: str | None = None, + ) -> PSANote: + raise NotImplementedError("Halo PSA integration coming soon") + + async def update_ticket_status( + self, + ticket_id: str, + status_id: int, + ) -> PSATicket: + raise NotImplementedError("Halo PSA integration coming soon") + + async def get_ticket_statuses(self, board_id: int) -> list[PSAStatus]: + raise NotImplementedError("Halo PSA integration coming soon") + + async def list_companies(self, **filters) -> list[PSACompany]: + raise NotImplementedError("Halo PSA integration coming soon") + + async def get_company(self, company_id: str) -> PSACompany: + raise NotImplementedError("Halo PSA integration coming soon") + + async def list_members(self) -> list[PSAMember]: + raise NotImplementedError("Halo PSA integration coming soon") + + async def get_ticket_configurations(self, ticket_id: str) -> list[PSAConfiguration]: + raise NotImplementedError("Halo PSA integration coming soon") + + async def create_time_entry( + self, + ticket_id: str, + member_id: str, + hours: float, + notes: str | None = None, + work_type: str | None = None, + ) -> PSATimeEntry: + raise NotImplementedError("Halo PSA integration coming soon") diff --git a/frontend/src/pages/account/IntegrationsPage.tsx b/frontend/src/pages/account/IntegrationsPage.tsx index 48788569..d6db282b 100644 --- a/frontend/src/pages/account/IntegrationsPage.tsx +++ b/frontend/src/pages/account/IntegrationsPage.tsx @@ -259,6 +259,58 @@ export function IntegrationsPage() { {/* Connection Tab */} {activeTab === 'connection' && (
+ {/* PSA Provider Grid */} +
+

+ Available PSA Integrations +

+
+ {/* ConnectWise — active */} +
+
+ ConnectWise PSA + {connection ? ( + + Connected + + ) : ( + + Available + + )} +
+

Manage, ticket linking, time entries

+
+ + {/* Autotask — coming soon */} +
+
+ Autotask PSA + + Coming Soon + +
+

Datto / Kaseya integration

+
+ + {/* Halo PSA — coming soon */} +
+
+ Halo PSA + + Coming Soon + +
+

HaloPSA / HaloITSM integration

+
+
+
+ {/* Illustrative empty state when no connection exists */} {mode === 'setup' && (