# Configure logger import logging from fastapi import APIRouter, FastAPI from contextlib import asynccontextmanager from zoneinfo import ZoneInfo from modules.connectors.connectorTicketJira import ConnectorTicketJira from modules.connectors.connectorSharepoint import ConnectorSharepoint from modules.interfaces.interfaceTicketObjects import TicketSharepointSyncInterface from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.cron import CronTrigger logger = logging.getLogger(__name__) scheduler = AsyncIOScheduler(timezone=ZoneInfo("Europe/Zurich")) @asynccontextmanager async def router_lifespan(app: FastAPI): # start scheduler when this router is mounted scheduler.add_job( perform_sync_jira_delta_group, CronTrigger(minute="0"), # run at the top of every hour id="jira_delta_group_sync", replace_existing=True, coalesce=True, max_instances=1, misfire_grace_time=1800, ) scheduler.start() logger.info("APScheduler started (jira_delta_group_sync hourly)") try: yield finally: if scheduler.running: scheduler.shutdown(wait=False) logger.info("APScheduler stopped") router = APIRouter( prefix="/api/jira", tags=["JIRA Sync"], lifespan=router_lifespan, ) @router.post("/sync/delta-group") async def sync_jira_delta_group(): """Endpoint to trigger JIRA-SharePoint sync for Delta Group project.""" logger.info("Received request to sync JIRA Delta Group project") await perform_sync_jira_delta_group() # Return a response return {"status": "Sync completed"} async def perform_sync_jira_delta_group(): logger.info("Syncing Jira issues for Delta Group...") # Sharepoint connection parameters sharepoint_client_id = None sharepoint_client_secret = None sharepoint_site_url = None # Jira connection parameters jira_username = "ONHOLD - TASK - p.motsch@valueon.ch" jira_api_token = "ATATT3xFfGF0d973nNb3R1wTDI4lesmJfJAmooS-4cYMJTyLfwYv4himrE6yyCxyX3aSMfl34NHcm2fAXeFXrLHUzJx0RQVUBonCFnlgexjLQTgS5BoCbSO7dwAVjlcHZZkArHbooCUaRwJ15n6AHkm-nwdjLQ3Z74TFnKKUZC4uhuh3Aj-MuX8=2D7124FA" jira_url = "https://deltasecurity.atlassian.net" project_code = "DCS" issue_type = "Task" # Basic validation (credentials will be added later) if not all([sharepoint_client_id, sharepoint_client_secret, sharepoint_site_url]): raise ValueError("SharePoint credentials not configured") if not all([jira_username, jira_api_token]): raise ValueError("JIRA credentials not configured") # Define the task sync definition task_sync_definition = { # key=excel-header, [get:jira>excel | put: excel>jira, jira-xml-field-list] "ID": ["get", ["key"]], "Module Category": ["get", ["fields", "customfield_10058", "value"]], "Summary": ["get", ["fields", "summary"]], "Description": ["get", ["fields", "description"]], "References": ["get", ["fields", "customfield_10066"]], "Priority": ["get", ["fields", "priority", "name"]], "Issue Status": ["get", ["fields", "customfield_10062"]], "Assignee": ["get", ["fields", "assignee", "displayName"]], "Issue Created": ["get", ["fields", "created"]], "Due Date": ["get", ["fields", "duedate"]], "DELTA Comments": ["get", ["fields", "customfield_10060"]], "SELISE Ticket References": ["put", ["fields", "customfield_10067"]], "SELISE Status Values": ["put", ["fields", "customfield_10065"]], "SELISE Comments": ["put", ["fields", "customfield_10064"]], } # SharePoint file configuration sync_folder = "/sites//Shared Documents/TicketSync" sync_file = "delta_group_selise_ticket_exchange_list.csv" backup_folder = "/sites//Shared Documents/TicketSync/Backups" audit_folder = "/sites//Shared Documents/TicketSync/AuditLogs" # Create the jira connector instance jira_connector = await ConnectorTicketJira.create( jira_username=jira_username, jira_api_token=jira_api_token, jira_url=jira_url, project_code=project_code, issue_type=issue_type, ) # Create the sharepoint connector instance ctx = ConnectorSharepoint.get_client_context_from_app( site_url=sharepoint_site_url, client_id=sharepoint_client_id, client_secret=sharepoint_client_secret, ) sharepoint_connector = await ConnectorSharepoint.create(ctx=ctx) # Create the sync interface instance sync_interface = await TicketSharepointSyncInterface.create( connector_ticket=jira_connector, connector_sharepoint=sharepoint_connector, task_sync_definition=task_sync_definition, sync_folder=sync_folder, sync_file=sync_file, backup_folder=backup_folder, audit_folder=audit_folder, ) # Sync from JIRA to CSV in Sharepoint await sync_interface.sync_from_jira_to_csv() # Sync from CSV in Sharepoint to JIRA await sync_interface.sync_from_csv_to_jira()