Update deliverable creation: Projects with URLs and correct dates
Changes: - Deliverables now created as Projects (not Tasks) - Project dates: Using StartDate/EndDate from ProjectDetails - Deliverable dates: BriefDate as start, LiveDate (or DueDate) as end - OMG# field for deliverables: Contains URL (OMG# - 999999) - Example: 6361863 → https://bissell.omg.oliver.solutions/jobs/5361864 - Projects keep OMG# as plain number - Added find_deliverable_by_omg_number() for duplicate detection - Added generate_omg_url() for URL construction Structure: Folder > Project > Deliverable (as Project) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
255c03b65d
commit
d449668cb9
1 changed files with 96 additions and 33 deletions
129
wrike_monitor.py
129
wrike_monitor.py
|
|
@ -415,40 +415,106 @@ class WrikeMonitor:
|
|||
return task["id"]
|
||||
return None
|
||||
|
||||
def create_deliverable_task(self, project_id, job_details):
|
||||
"""Create deliverable task (skip if exists)"""
|
||||
task_title = job_details.get("Title", "Untitled Task")
|
||||
def find_deliverable_by_omg_number(self, parent_project_id, omg_number):
|
||||
"""Find deliverable (project) with matching OMG number"""
|
||||
if not omg_number:
|
||||
return None
|
||||
|
||||
# Get folder tree
|
||||
result = self.make_wrike_request("GET", f"/folders/{parent_project_id}/folders?fields=[\"customFields\",\"project\"]")
|
||||
|
||||
if result and "data" in result:
|
||||
# Find parent folder with childIds
|
||||
parent_folder = None
|
||||
for item in result["data"]:
|
||||
if item["id"] == parent_project_id:
|
||||
parent_folder = item
|
||||
break
|
||||
|
||||
if parent_folder:
|
||||
child_ids = parent_folder.get("childIds", [])
|
||||
# Search only in direct children that are projects
|
||||
for item in result["data"]:
|
||||
if item["id"] in child_ids and "project" in item:
|
||||
custom_fields = item.get("customFields", [])
|
||||
for field in custom_fields:
|
||||
if field.get("id") == Config.CUSTOM_FIELDS["omg_number"]:
|
||||
if field.get("value") == omg_number:
|
||||
return item["id"]
|
||||
return None
|
||||
|
||||
def generate_omg_url(self, omg_number):
|
||||
"""Generate OMG URL from OMG number (subtract 999999)"""
|
||||
try:
|
||||
omg_int = int(omg_number)
|
||||
job_id = omg_int - 999999
|
||||
return f"https://bissell.omg.oliver.solutions/jobs/{job_id}"
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
|
||||
def create_deliverable_project(self, parent_project_id, job_details):
|
||||
"""Create deliverable as a project (not a task) - skip if exists"""
|
||||
deliverable_title = job_details.get("Title", "Untitled Deliverable")
|
||||
job_number = job_details.get("Number", "")
|
||||
|
||||
# Check if exists
|
||||
# Check if exists by searching for existing deliverable with same OMG#
|
||||
if job_number:
|
||||
existing_task_id = self.find_task_by_omg_number(project_id, job_number)
|
||||
if existing_task_id:
|
||||
self.logger.info(f"⊙ Task already exists: {task_title} (#{job_number}) - skipping")
|
||||
return existing_task_id, True # Return (task_id, skipped=True)
|
||||
existing_deliverable_id = self.find_deliverable_by_omg_number(parent_project_id, job_number)
|
||||
if existing_deliverable_id:
|
||||
self.logger.info(f"⊙ Deliverable already exists: {deliverable_title} (#{job_number}) - skipping")
|
||||
return existing_deliverable_id, True # Return (deliverable_id, skipped=True)
|
||||
|
||||
# Parse dates
|
||||
due_date = self.parse_date(job_details.get("DueDate"))
|
||||
# Parse dates - use BriefDate as start, LiveDate (or DueDate) as end
|
||||
brief_date = self.parse_date(job_details.get("BriefDate"))
|
||||
live_date = self.parse_date(job_details.get("LiveDate")) or self.parse_date(job_details.get("DueDate"))
|
||||
|
||||
# Create task
|
||||
task_data = {
|
||||
"title": task_title,
|
||||
"description": job_details.get("Notes", ""),
|
||||
# Build description
|
||||
description_parts = []
|
||||
if job_details.get("Notes"):
|
||||
description_parts.append(job_details["Notes"])
|
||||
if job_details.get("Type"):
|
||||
description_parts.append(f"Type: {job_details['Type']}")
|
||||
if job_details.get("MediaType"):
|
||||
description_parts.append(f"Media: {job_details['MediaType']}")
|
||||
|
||||
deliverable_description = " | ".join(description_parts) if description_parts else ""
|
||||
|
||||
# Create deliverable as a project (subfolder)
|
||||
deliverable_data = {
|
||||
"title": deliverable_title,
|
||||
"description": deliverable_description
|
||||
}
|
||||
|
||||
if due_date:
|
||||
task_data["dates"] = {"due": due_date}
|
||||
if brief_date:
|
||||
task_data["dates"]["start"] = brief_date
|
||||
result = self.make_wrike_request("POST", f"/folders/{parent_project_id}/folders", deliverable_data)
|
||||
|
||||
result = self.make_wrike_request("POST", f"/folders/{project_id}/tasks", task_data)
|
||||
if result and "data" in result and len(result["data"]) > 0:
|
||||
task_id = result["data"][0]["id"]
|
||||
deliverable_id = result["data"][0]["id"]
|
||||
|
||||
# Convert to project with dates
|
||||
project_data = {"project": {}}
|
||||
if brief_date:
|
||||
project_data["project"]["startDate"] = brief_date
|
||||
if live_date:
|
||||
project_data["project"]["endDate"] = live_date
|
||||
|
||||
# Add custom fields
|
||||
custom_fields = []
|
||||
|
||||
# For deliverables: OMG# field gets the URL, not just the number
|
||||
if job_number:
|
||||
omg_url = self.generate_omg_url(job_number)
|
||||
if omg_url:
|
||||
custom_fields.append({
|
||||
"id": Config.CUSTOM_FIELDS["omg_number"],
|
||||
"value": omg_url
|
||||
})
|
||||
else:
|
||||
# Fallback to just the number if URL generation fails
|
||||
custom_fields.append({
|
||||
"id": Config.CUSTOM_FIELDS["omg_number"],
|
||||
"value": job_number
|
||||
})
|
||||
|
||||
job_category = job_details.get("JobCategory", job_details.get("MediaType", ""))
|
||||
if job_category:
|
||||
custom_fields.append({
|
||||
|
|
@ -456,12 +522,6 @@ class WrikeMonitor:
|
|||
"value": job_category
|
||||
})
|
||||
|
||||
if job_number:
|
||||
custom_fields.append({
|
||||
"id": Config.CUSTOM_FIELDS["omg_number"],
|
||||
"value": job_number
|
||||
})
|
||||
|
||||
notes_parts = []
|
||||
if job_details.get("Type"):
|
||||
notes_parts.append(f"Type: {job_details['Type']}")
|
||||
|
|
@ -474,10 +534,13 @@ class WrikeMonitor:
|
|||
})
|
||||
|
||||
if custom_fields:
|
||||
self.make_wrike_request("PUT", f"/tasks/{task_id}", {"customFields": custom_fields})
|
||||
project_data["customFields"] = custom_fields
|
||||
|
||||
self.logger.info(f"Created task: {task_title} (#{job_number})")
|
||||
return task_id, False # Return (task_id, skipped=False)
|
||||
# Update with project dates and custom fields
|
||||
self.make_wrike_request("PUT", f"/folders/{deliverable_id}", project_data)
|
||||
|
||||
self.logger.info(f"✓ Created deliverable (as project): {deliverable_title} (#{job_number})")
|
||||
return deliverable_id, False # Return (deliverable_id, skipped=False)
|
||||
|
||||
return None, False
|
||||
|
||||
|
|
@ -514,10 +577,10 @@ class WrikeMonitor:
|
|||
if not project_id:
|
||||
raise ValueError(f"Failed to create project: {project_title}")
|
||||
|
||||
# Create task
|
||||
task_id, skipped = self.create_deliverable_task(project_id, job_details)
|
||||
if not task_id:
|
||||
raise ValueError("Failed to create task")
|
||||
# Create deliverable (as project)
|
||||
deliverable_id, skipped = self.create_deliverable_project(project_id, job_details)
|
||||
if not deliverable_id:
|
||||
raise ValueError("Failed to create deliverable")
|
||||
|
||||
processing_time = time.time() - start_time
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue