[2ff88f42] feat(connector-superoffice): Implement Sale and Project entities, refine workflow

This commit extends the SuperOffice connector to support the creation and linking of Sale \(Opportunity\) and Project \(Campaign\) entities, providing a comprehensive foundation for both sales and marketing automation workflows.

Key achievements:
- **`SUPEROFFICE_INTEGRATION_PLAN.md`**: Updated to include strategic mapping of D365 concepts \(Opportunity, Campaign\) to SuperOffice entities \(Sale, Project\).
- **`connector-superoffice/superoffice_client.py`**:
    - Implemented `create_sale` method to generate new opportunities, correctly mapping `Title` to SuperOffices
This commit is contained in:
2026-02-10 07:57:11 +00:00
parent 47cd047bc8
commit c420bb31c3
6 changed files with 209 additions and 14 deletions

View File

@@ -145,7 +145,78 @@ class SuperOfficeClient:
logger.info(f"Successfully created person: {created_person.get('Firstname')} {created_person.get('Lastname')} (ID: {created_person.get('PersonId')})")
return created_person
except Exception as e:
logger.error(f"Error creating person: {e}")
if hasattr(e, 'response') and e.response is not None:
logger.error(f"Response: {e.response.text}")
return None
def create_sale(self, title, contact_id, person_id=None, amount=0.0):
"""Creates a new Sale (Opportunity) linked to a contact and optionally a person."""
url = self._get_url("v1/Sale")
payload = {
"Heading": title,
"Contact": {
"ContactId": contact_id
},
"Amount": amount,
"SaleType": { # Assuming default ID 1 exists
"Id": 1
},
"SaleStage": { # Assuming default ID for the first stage is 1
"Id": 1
},
"Probability": 10 # Default probability
}
if person_id:
payload["Person"] = {
"PersonId": person_id
}
try:
logger.info(f"Attempting to create sale: '{title}' for Contact ID {contact_id}")
resp = self.session.post(url, headers=self._get_headers(), json=payload)
resp.raise_for_status()
created_sale = resp.json()
logger.info(f"Successfully created sale: {created_sale.get('Heading')} (ID: {created_sale.get('SaleId')})")
return created_sale
except Exception as e:
if hasattr(e, 'response') and e.response is not None:
logger.error(f"Response: {e.response.text}")
return None
def create_project(self, name, contact_id, person_id=None):
"""Creates a new Project linked to a contact and optionally adds a person as a member."""
url = self._get_url("v1/Project")
payload = {
"Name": name,
"Contact": {
"ContactId": contact_id
},
"ProjectType": { # Assuming default ID 1 exists
"Id": 1
},
"ProjectStatus": { # Assuming default ID 1 for 'In progress' exists
"Id": 1
},
"ProjectMembers": []
}
if person_id:
payload["ProjectMembers"].append({
"PersonId": person_id
})
try:
logger.info(f"Attempting to create project: '{name}' for Contact ID {contact_id}")
resp = self.session.post(url, headers=self._get_headers(), json=payload)
resp.raise_for_status()
created_project = resp.json()
logger.info(f"Successfully created project: {created_project.get('Name')} (ID: {created_project.get('ProjectId')})")
return created_project
except Exception as e:
logger.error(f"Error creating project: {e}")
if hasattr(e, 'response') and e.response is not None:
logger.error(f"Response: {e.response.text}")
return None