ab-ms-core / app /tests /unit /test_project_customers.py
MukeshKapoor25's picture
feat(customers): add endpoint to retrieve projects associated with a specific customer with pagination
f5b378b
import pytest
from unittest.mock import Mock
from app.services.project_service import ProjectService
from app.schemas.project_detail import ProjectCustomerOut, BarrierSizeOut, ContactOut, BidderNoteOut
from unittest.mock import MagicMock
import app.controllers.projects as projects_controller
import app.controllers.customers as customers_controller
def make_sample_bidder_row():
return {
'proj_no': 123,
'cust_id': 'CUST123',
'quote': None,
'contact': 'Jane Doe',
'phone': '555-1234',
'notes': 'Important customer',
'date_last_contact': None,
'date_followup': None,
'is_primary': 1,
'cust_type': 2,
'email_address': 'jane@example.com',
'Id': 10,
'fax': None,
'order_nr': None,
'customer_po': None,
'ship_date': None,
'deliver_date': None,
'replacement_cost': None,
'quote_date': None,
'invoice_date': None,
'less_payment': None,
'enabled': 1,
'employee_id': 5
}
def test_get_customers_service_calls_repo_methods(monkeypatch):
mock_db = Mock()
service = ProjectService(mock_db)
# Mock BidderRepository since service now creates its own instance
from app.db.repositories.bidder_repo import BidderRepository
mock_bidder_repo = Mock(spec=BidderRepository)
mock_bidder_repo.fetch_project_bidders_raw = Mock(return_value=[make_sample_bidder_row()])
mock_bidder_repo.get_bidder_barrier_sizes_raw = Mock(return_value=[{'Id': 1, 'InventoryId': 'INV1', 'BarrierSizeId': 42, 'InstallAdvisorFees': None, 'IsStandard': 1, 'Width': 10, 'Length': 20, 'CableUnits': 2, 'Height': 5, 'Price': None}])
mock_bidder_repo.get_bidder_contacts_raw = Mock(return_value=[{'Id': 2, 'ContactId': 200, 'BidderId': 10, 'Enabled': 1, 'FirstName': 'John', 'LastName': 'Smith', 'Title': 'Mgr', 'EmailAddress': 'john@example.com', 'WorkPhone': '555', 'MobilePhone': '999'}])
mock_bidder_repo.get_bidder_notes_raw = Mock(return_value=[{'Id': 3, 'BidderId': 10, 'Date': '2020-01-01T00:00:00', 'EmployeeID': '5', 'Notes': 'Note text'}])
# Patch BidderRepository instantiation
def fake_bidder_repo_init(db):
return mock_bidder_repo
monkeypatch.setattr('app.db.repositories.bidder_repo.BidderRepository', fake_bidder_repo_init)
customers = service.get_customers(123)
assert isinstance(customers, list)
assert len(customers) == 1
cust = customers[0]
assert isinstance(cust, ProjectCustomerOut)
assert cust.cust_id == 'CUST123'
assert cust.contact == 'Jane Doe'
assert cust.id == 10
assert len(cust.barrier_sizes) == 1
assert len(cust.contacts) == 1
assert len(cust.bidder_notes) == 1
def test_get_project_customers_endpoint_monkeypatched(monkeypatch):
# Monkeypatch the ProjectService.get_customers to return a known value
sample = ProjectCustomerOut(
proj_no=123,
cust_id='CUST999',
quote=None,
contact='Endpoint User',
phone='123',
notes=None,
date_last_contact=None,
date_followup=None,
primary=True,
cust_type='1',
email_address='end@example.com',
id=99,
fax=None,
order_nr=None,
customer_po=None,
ship_date=None,
deliver_date=None,
replacement_cost=None,
quote_date=None,
invoice_date=None,
less_payment=None,
barrier_sizes=[],
contacts=[],
bidder_notes=[],
bid_date=None,
enabled=True,
employee_id=None
)
def fake_get_customers(self, project_no, page=1, page_size=100):
return [sample]
monkeypatch.setattr('app.services.project_service.ProjectService.get_customers', fake_get_customers)
# Call controller function directly, injecting a mock DB session
fake_db = MagicMock()
result = projects_controller.get_project_customers(123, page=1, page_size=10, db=fake_db)
assert isinstance(result, list)
assert result[0].cust_id == 'CUST999'
assert result[0].id == 99
def test_get_project_customer_detail_service(monkeypatch):
"""Test ProjectService.get_project_customer_detail method"""
mock_db = Mock()
service = ProjectService(mock_db)
sample_bidder = make_sample_bidder_row()
sample_bidder['cust_id'] = 'CUST456'
# Mock BidderRepository methods
from app.db.repositories.bidder_repo import BidderRepository
mock_bidder_repo = Mock(spec=BidderRepository)
mock_bidder_repo.fetch_project_bidder_by_customer_id_raw = Mock(return_value=sample_bidder)
mock_bidder_repo.get_bidder_barrier_sizes_raw = Mock(return_value=[])
mock_bidder_repo.get_bidder_contacts_raw = Mock(return_value=[])
mock_bidder_repo.get_bidder_notes_raw = Mock(return_value=[])
# Patch BidderRepository instantiation
def fake_bidder_repo_init(db):
return mock_bidder_repo
monkeypatch.setattr('app.db.repositories.bidder_repo.BidderRepository', fake_bidder_repo_init)
customer = service.get_project_customer_detail(123, 'CUST456')
assert isinstance(customer, ProjectCustomerOut)
assert customer.cust_id == 'CUST456'
assert customer.id == 10
assert customer.contact == 'Jane Doe'
mock_bidder_repo.fetch_project_bidder_by_customer_id_raw.assert_called_once_with(123, 'CUST456')
def test_get_project_customer_detail_endpoint(monkeypatch):
"""Test controller endpoint for specific customer detail"""
sample = ProjectCustomerOut(
proj_no=123,
cust_id='CUST777',
quote=None,
contact='Detail User',
phone='456',
notes='Specific customer',
date_last_contact=None,
date_followup=None,
primary=False,
cust_type='2',
email_address='detail@example.com',
id=77,
fax=None,
order_nr='ORD123',
customer_po='PO456',
ship_date=None,
deliver_date=None,
replacement_cost=None,
quote_date=None,
invoice_date=None,
less_payment=None,
barrier_sizes=[],
contacts=[],
bidder_notes=[],
bid_date=None,
enabled=True,
employee_id='EMP5'
)
def fake_get_customer_detail(self, project_no, customer_id):
return sample
monkeypatch.setattr('app.services.project_service.ProjectService.get_project_customer_detail', fake_get_customer_detail)
fake_db = MagicMock()
result = projects_controller.get_project_customer_detail(123, 'CUST777', db=fake_db)
assert isinstance(result, ProjectCustomerOut)
assert result.cust_id == 'CUST777'
assert result.id == 77
assert result.order_nr == 'ORD123'
assert result.employee_id == 'EMP5'
def test_get_customer_projects_service(monkeypatch):
"""Test ProjectService.get_customer_projects method"""
mock_db = Mock()
service = ProjectService(mock_db)
# Create sample bidders for multiple projects
bidder1 = make_sample_bidder_row()
bidder1['proj_no'] = 100
bidder1['cust_id'] = 'CUST888'
bidder1['Id'] = 20
bidder2 = make_sample_bidder_row()
bidder2['proj_no'] = 200
bidder2['cust_id'] = 'CUST888'
bidder2['Id'] = 21
# Mock BidderRepository methods
from app.db.repositories.bidder_repo import BidderRepository
mock_bidder_repo = Mock(spec=BidderRepository)
mock_bidder_repo.fetch_bidders_by_customer_id_raw = Mock(return_value=[bidder1, bidder2])
mock_bidder_repo.get_bidder_barrier_sizes_raw = Mock(return_value=[])
mock_bidder_repo.get_bidder_contacts_raw = Mock(return_value=[])
mock_bidder_repo.get_bidder_notes_raw = Mock(return_value=[])
# Patch BidderRepository instantiation
def fake_bidder_repo_init(db):
return mock_bidder_repo
monkeypatch.setattr('app.db.repositories.bidder_repo.BidderRepository', fake_bidder_repo_init)
projects = service.get_customer_projects('CUST888', page=1, page_size=10)
assert isinstance(projects, list)
assert len(projects) == 2
assert projects[0].proj_no == 100
assert projects[0].cust_id == 'CUST888'
assert projects[1].proj_no == 200
assert projects[1].cust_id == 'CUST888'
mock_bidder_repo.fetch_bidders_by_customer_id_raw.assert_called_once_with('CUST888', page=1, page_size=10)
def test_get_customer_projects_endpoint(monkeypatch):
"""Test controller endpoint for customer projects"""
sample1 = ProjectCustomerOut(
proj_no=300,
cust_id='CUST555',
quote=None,
contact='Project A Contact',
phone='111',
notes=None,
date_last_contact=None,
date_followup=None,
primary=True,
cust_type='1',
email_address='a@example.com',
id=30,
fax=None,
order_nr=None,
customer_po=None,
ship_date=None,
deliver_date=None,
replacement_cost=None,
quote_date=None,
invoice_date=None,
less_payment=None,
barrier_sizes=[],
contacts=[],
bidder_notes=[],
bid_date=None,
enabled=True,
employee_id=None
)
sample2 = ProjectCustomerOut(
proj_no=400,
cust_id='CUST555',
quote=None,
contact='Project B Contact',
phone='222',
notes=None,
date_last_contact=None,
date_followup=None,
primary=False,
cust_type='2',
email_address='b@example.com',
id=31,
fax=None,
order_nr=None,
customer_po=None,
ship_date=None,
deliver_date=None,
replacement_cost=None,
quote_date=None,
invoice_date=None,
less_payment=None,
barrier_sizes=[],
contacts=[],
bidder_notes=[],
bid_date=None,
enabled=True,
employee_id=None
)
def fake_get_customer_projects(self, customer_id, page=1, page_size=100):
return [sample1, sample2]
monkeypatch.setattr('app.services.project_service.ProjectService.get_customer_projects', fake_get_customer_projects)
fake_db = MagicMock()
result = customers_controller.get_customer_projects('CUST555', page=1, page_size=10, db=fake_db)
assert isinstance(result, list)
assert len(result) == 2
assert result[0].proj_no == 300
assert result[0].cust_id == 'CUST555'
assert result[1].proj_no == 400
assert result[1].cust_id == 'CUST555'