annator-command-center / ecommerce /b2b_data_push_service.py
techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 5)
90c6b42 verified
Raw
History Blame Contribute Delete
5.55 kB
"""
B2B Data Push Service
Orchestrates the synchronization of B2B data (customers, draft orders) to external integrations like HubSpot and QuickBooks.
"""
import logging
from typing import Any, Dict, Optional
from ecommerce.models import EcommerceCustomer, EcommerceOrder, EcommerceOrderItem
from sqlalchemy.orm import Session
from integrations.atom_quickbooks_integration_service import AtomQuickBooksIntegrationService
from integrations.hubspot_service import hubspot_service
logger = logging.getLogger(__name__)
class B2BDataPushService:
def __init__(self, db: Session):
self.db = db
# QuickBooks config would normally come from some settings/env
self.qbo = AtomQuickBooksIntegrationService({
"database": db,
"quickbooks_client_id": "MOCK", # Use actual from env if available
"quickbooks_client_secret": "MOCK",
"quickbooks_company_id": "MOCK",
})
async def push_b2b_customer(self, customer_id: str) -> Dict[str, Any]:
"""
Push a B2B customer profile to external CRM and Accounting integrations.
"""
customer = self.db.query(EcommerceCustomer).filter(EcommerceCustomer.id == customer_id).first()
if not customer:
return {"error": "Customer not found"}
results = {"hubspot": None, "quickbooks": None}
# 1. Push to HubSpot (Company)
try:
company_name = f"{customer.first_name} {customer.last_name}" or customer.email
domain = customer.email.split('@')[-1] if '@' in customer.email else None
hs_company = await hubspot_service.create_company(name=company_name, domain=domain)
results["hubspot"] = hs_company.get("id")
customer.crm_contact_id = hs_company.get("id") # Store as reference
logger.info(f"Pushed B2B customer {customer_id} to HubSpot: {results['hubspot']}")
except Exception as e:
logger.error(f"Failed to push to HubSpot: {e}")
results["hubspot_error"] = str(e)
# 2. Push to QuickBooks (Customer)
try:
display_name = f"{customer.first_name} {customer.last_name}" or customer.email
qbo_res = await self.qbo.create_customer(display_name=display_name, email=customer.email)
if qbo_res["success"]:
results["quickbooks"] = qbo_res["customer_id"]
customer.accounting_entity_id = qbo_res["customer_id"]
logger.info(f"Pushed B2B customer {customer_id} to QuickBooks: {results['quickbooks']}")
else:
results["quickbooks_error"] = qbo_res.get("error")
except Exception as e:
logger.error(f"Failed to push to QuickBooks: {e}")
results["quickbooks_error"] = str(e)
self.db.commit()
return results
async def push_draft_order(self, order_id: str) -> Dict[str, Any]:
"""
Push a B2B draft order to HubSpot (as Deal) and QuickBooks (as Invoice/Draft).
"""
order = self.db.query(EcommerceOrder).filter(EcommerceOrder.id == order_id).first()
if not order:
return {"error": "Order not found"}
customer = order.customer
results = {"hubspot_deal": None, "quickbooks_invoice": None}
# 1. Push to HubSpot as a Deal
try:
company_id = customer.crm_contact_id # HubSpot company ID stored in customer
deal_name = f"B2B Order {order.order_number}"
hs_deal = await hubspot_service.create_deal(
name=deal_name,
amount=order.total_price,
company_id=company_id
)
results["hubspot_deal"] = hs_deal.get("id")
logger.info(f"Pushed draft order {order_id} to HubSpot Deal: {results['hubspot_deal']}")
except Exception as e:
logger.error(f"Failed to push order to HubSpot Deal: {e}")
results["hubspot_deal_error"] = str(e)
# 2. Push to QuickBooks as an Invoice (Draft/Pending)
try:
line_items = []
for item in order.items:
line_items.append({
"Amount": item.price * item.quantity,
"Description": item.title,
"DetailType": "SalesItemLineDetail",
"SalesItemLineDetail": {
"ItemRef": {"value": item.product_id or "1"}, # Default item ref
"Qty": item.quantity,
"UnitPrice": item.price
}
})
invoice_data = {
"customer_id": customer.accounting_entity_id,
"amount": order.total_price,
"line_items": line_items,
"notes": f"Generated from B2B Draft {order.order_number}"
}
qbo_res = await self.qbo.create_invoice(invoice_data)
if qbo_res["success"]:
results["quickbooks_invoice"] = qbo_res["invoice_id"]
order.ledger_transaction_id = qbo_res["invoice_id"]
logger.info(f"Pushed draft order {order_id} to QuickBooks Invoice: {results['quickbooks_invoice']}")
else:
results["quickbooks_error"] = qbo_res.get("error")
except Exception as e:
logger.error(f"Failed to push order to QuickBooks: {e}")
results["quickbooks_error"] = str(e)
self.db.commit()
return results