MukeshKapoor25 commited on
Commit
c2fa6c9
·
1 Parent(s): 88aeac6

phone type reference data

Browse files
app/controllers/reference.py CHANGED
@@ -12,7 +12,7 @@ from app.schemas.reference import (
12
  BarrierSizeCreateIn, BarrierSizeUpdateIn, ProductApplicationCreateIn, ProductApplicationUpdateIn,
13
  FOBCreateIn, FOBUpdateIn, EstShipDateCreateIn, EstShipDateUpdateIn,
14
  EstFreightCreateIn, EstFreightUpdateIn, StatusInfoCreateIn, StatusInfoUpdateIn,
15
- PriorityCreateIn, PriorityUpdateIn
16
  )
17
  from app.core.dependencies import get_current_user_optional
18
  from app.schemas.auth import CurrentUser
@@ -879,4 +879,51 @@ def delete_priority(
879
  success = service.delete_priority(priority_id)
880
  if not success:
881
  raise HTTPException(status_code=404, detail="Priority not found")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
882
  return Response(status_code=204)
 
12
  BarrierSizeCreateIn, BarrierSizeUpdateIn, ProductApplicationCreateIn, ProductApplicationUpdateIn,
13
  FOBCreateIn, FOBUpdateIn, EstShipDateCreateIn, EstShipDateUpdateIn,
14
  EstFreightCreateIn, EstFreightUpdateIn, StatusInfoCreateIn, StatusInfoUpdateIn,
15
+ PriorityCreateIn, PriorityUpdateIn, PhoneTypeOut, PhoneTypeCreateIn, PhoneTypeUpdateIn
16
  )
17
  from app.core.dependencies import get_current_user_optional
18
  from app.schemas.auth import CurrentUser
 
879
  success = service.delete_priority(priority_id)
880
  if not success:
881
  raise HTTPException(status_code=404, detail="Priority not found")
882
+ return Response(status_code=204)
883
+
884
+ @router.get("/phone-types", response_model=List[PhoneTypeOut])
885
+ def get_phone_types(
886
+ active_only: bool = Query(False, description="Return only active records"),
887
+ db: Session = Depends(get_db),
888
+ current_user: Optional[CurrentUser] = Depends(get_current_user_optional)
889
+ ):
890
+ """Get all phone types"""
891
+ service = ReferenceDataService(db)
892
+ return service.get_phone_types(active_only)
893
+
894
+ @router.post("/phone-types", response_model=PhoneTypeOut, status_code=201)
895
+ def create_phone_type(
896
+ data: PhoneTypeCreateIn,
897
+ db: Session = Depends(get_db),
898
+ current_user: CurrentUser = Depends(get_current_user_optional)
899
+ ):
900
+ """Create a new phone type"""
901
+ service = ReferenceDataService(db)
902
+ return service.create_phone_type(data)
903
+
904
+ @router.put("/phone-types/{phone_type_id}", response_model=PhoneTypeOut)
905
+ def update_phone_type(
906
+ phone_type_id: int,
907
+ data: PhoneTypeUpdateIn,
908
+ db: Session = Depends(get_db),
909
+ current_user: CurrentUser = Depends(get_current_user_optional)
910
+ ):
911
+ """Update an existing phone type"""
912
+ service = ReferenceDataService(db)
913
+ result = service.update_phone_type(phone_type_id, data)
914
+ if not result:
915
+ raise HTTPException(status_code=404, detail="Phone type not found")
916
+ return result
917
+
918
+ @router.delete("/phone-types/{phone_type_id}", status_code=204)
919
+ def delete_phone_type(
920
+ phone_type_id: int,
921
+ db: Session = Depends(get_db),
922
+ current_user: CurrentUser = Depends(get_current_user_optional)
923
+ ):
924
+ """Delete a phone type"""
925
+ service = ReferenceDataService(db)
926
+ success = service.delete_phone_type(phone_type_id)
927
+ if not success:
928
+ raise HTTPException(status_code=404, detail="Phone type not found")
929
  return Response(status_code=204)
app/db/models/reference.py CHANGED
@@ -117,4 +117,13 @@ class EstFreight(Base):
117
 
118
  est_freight_id = Column("Id", Integer, primary_key=True, index=True)
119
  est_freight_description = Column("EstFreightDescription", String(255), nullable=True)
 
 
 
 
 
 
 
 
 
120
 
 
117
 
118
  est_freight_id = Column("Id", Integer, primary_key=True, index=True)
119
  est_freight_description = Column("EstFreightDescription", String(255), nullable=True)
120
+
121
+ class PhoneType(Base):
122
+ __tablename__ = "PhoneType"
123
+
124
+ id = Column("Id", Integer, primary_key=True, index=True)
125
+ name = Column("Name", String(50), nullable=False)
126
+ enabled = Column("Enabled", Boolean, nullable=True)
127
+ show_in_contact_page = Column("ShowInContactPage", Boolean, nullable=True)
128
+ modified_date = Column("ModifiedDate", DateTime, nullable=True)
129
 
app/db/repositories/reference_repo.py CHANGED
@@ -3,7 +3,7 @@ from sqlalchemy import text
3
  from app.db.models.reference import (
4
  State, Country, CompanyType, LeadGeneratedFrom, PaymentTerm,
5
  PurchasePrice, RentalPrice, BarrierSize, ProductApplication, Priority,
6
- FOB, EstShipDate, EstFreight, StatusInfo
7
  )
8
  from typing import List, Dict, Any, Optional, Type, Union
9
  from app.core.exceptions import RepositoryException
@@ -406,6 +406,7 @@ class ReferenceDataRepository:
406
  'est_freights': self.get_est_freights(active_only),
407
  'status_info': self.get_status_info(active_only),
408
  'priorities': self.get_priorities(True, 1), # Get priorities with CustomerTypeID = 1
 
409
  }
410
 
411
  def get_status_info(self, active_only: bool = True) -> List[Dict[str, Any]]:
@@ -468,6 +469,37 @@ class ReferenceDataRepository:
468
  logger.info(f"Retrieved {len(priorities_data)} priorities with CustomerTypeID = 1")
469
  return priorities_data
470
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
  def create_state(self, data: Dict[str, Any]) -> Dict[str, Any]:
472
  """Create a new state"""
473
  state = State(**data)
@@ -905,6 +937,37 @@ class ReferenceDataRepository:
905
  self.db.commit()
906
  return True
907
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
908
  def clear_cache(self):
909
  """Clear the internal cache to force fresh data on next request"""
910
  self._cache.clear()
 
3
  from app.db.models.reference import (
4
  State, Country, CompanyType, LeadGeneratedFrom, PaymentTerm,
5
  PurchasePrice, RentalPrice, BarrierSize, ProductApplication, Priority,
6
+ FOB, EstShipDate, EstFreight, StatusInfo, PhoneType
7
  )
8
  from typing import List, Dict, Any, Optional, Type, Union
9
  from app.core.exceptions import RepositoryException
 
406
  'est_freights': self.get_est_freights(active_only),
407
  'status_info': self.get_status_info(active_only),
408
  'priorities': self.get_priorities(True, 1), # Get priorities with CustomerTypeID = 1
409
+ 'phone_types': self.get_phone_types(active_only),
410
  }
411
 
412
  def get_status_info(self, active_only: bool = True) -> List[Dict[str, Any]]:
 
469
  logger.info(f"Retrieved {len(priorities_data)} priorities with CustomerTypeID = 1")
470
  return priorities_data
471
 
472
+ def get_phone_types(self, active_only: bool = False) -> List[Dict[str, Any]]:
473
+ """Get all phone types"""
474
+ cache_key = f"phone_types_{active_only}"
475
+ if cache_key in self._cache:
476
+ return self._cache[cache_key]
477
+
478
+ try:
479
+ query = self.db.query(PhoneType)
480
+ if active_only:
481
+ query = query.filter((PhoneType.enabled == True) | (PhoneType.enabled.is_(None)))
482
+
483
+ rows = query.order_by(PhoneType.name.asc()).all()
484
+ phone_types_data = []
485
+
486
+ for row in rows:
487
+ phone_types_data.append({
488
+ 'id': row.id,
489
+ 'name': row.name,
490
+ 'enabled': row.enabled,
491
+ 'show_in_contact_page': row.show_in_contact_page,
492
+ 'modified_date': row.modified_date
493
+ })
494
+
495
+ self._cache[cache_key] = phone_types_data
496
+ logger.info(f"Retrieved {len(phone_types_data)} phone types")
497
+ return phone_types_data
498
+
499
+ except Exception as e:
500
+ logger.error(f"Error retrieving phone types: {e}", exc_info=True)
501
+ return []
502
+
503
  def create_state(self, data: Dict[str, Any]) -> Dict[str, Any]:
504
  """Create a new state"""
505
  state = State(**data)
 
937
  self.db.commit()
938
  return True
939
 
940
+ def create_phone_type(self, data: Dict[str, Any]) -> Dict[str, Any]:
941
+ """Create a new phone type"""
942
+ phone_type = PhoneType(**data)
943
+ self.db.add(phone_type)
944
+ self.db.commit()
945
+ self.db.refresh(phone_type)
946
+ mapper = phone_type.__mapper__
947
+ return {mapper.get_property_by_column(column).key: getattr(phone_type, mapper.get_property_by_column(column).key) for column in phone_type.__table__.columns}
948
+
949
+ def update_phone_type(self, phone_type_id: int, data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
950
+ """Update an existing phone type"""
951
+ phone_type = self.db.query(PhoneType).filter(PhoneType.id == phone_type_id).first()
952
+ if not phone_type:
953
+ return None
954
+ for key, value in data.items():
955
+ if hasattr(phone_type, key):
956
+ setattr(phone_type, key, value)
957
+ self.db.commit()
958
+ self.db.refresh(phone_type)
959
+ mapper = phone_type.__mapper__
960
+ return {mapper.get_property_by_column(column).key: getattr(phone_type, mapper.get_property_by_column(column).key) for column in phone_type.__table__.columns}
961
+
962
+ def delete_phone_type(self, phone_type_id: int) -> bool:
963
+ """Delete a phone type"""
964
+ phone_type = self.db.query(PhoneType).filter(PhoneType.id == phone_type_id).first()
965
+ if not phone_type:
966
+ return False
967
+ self.db.delete(phone_type)
968
+ self.db.commit()
969
+ return True
970
+
971
  def clear_cache(self):
972
  """Clear the internal cache to force fresh data on next request"""
973
  self._cache.clear()
app/schemas/reference.py CHANGED
@@ -196,6 +196,26 @@ class FOBUpdateIn(BaseModel):
196
  fob_description: Optional[str] = Field(None, description="FOB description / name")
197
 
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  class EstShipDateOut(BaseModel):
200
  est_ship_date_id: int = Field(..., description="Estimated ship date ID")
201
  est_ship_date_description: Optional[str] = Field(None, description="Estimated ship date description")
@@ -271,6 +291,7 @@ class ReferenceDataResponse(BaseModel):
271
  est_freights: Optional[List[EstFreightOut]] = Field([], description="List of Estimated Freight options")
272
  status_info: List[StatusInfoOut] = Field(..., description="Project status info")
273
  priorities: Optional[List[PriorityOut]] = Field([], description="List of priorities")
 
274
 
275
  class ProjectReferenceResponse(BaseModel):
276
  """Grouped reference data used on project creation forms"""
@@ -281,3 +302,4 @@ class ProjectReferenceResponse(BaseModel):
281
  status_info: List[StatusInfoOut] = Field(..., description="Project status info")
282
  purchase_prices: List[PurchasePriceOut] = Field(..., description="Purchase price options")
283
  rental_prices: List[RentalPriceOut] = Field(..., description="Rental price options")
 
 
196
  fob_description: Optional[str] = Field(None, description="FOB description / name")
197
 
198
 
199
+ class PhoneTypeOut(BaseModel):
200
+ id: int = Field(..., description="Phone type ID")
201
+ name: str = Field(..., description="Phone type name")
202
+ enabled: Optional[bool] = Field(None, description="Enabled flag")
203
+ show_in_contact_page: Optional[bool] = Field(None, description="Show in contact page flag")
204
+ modified_date: Optional[datetime] = Field(None, description="Last modified date")
205
+
206
+
207
+ class PhoneTypeCreateIn(BaseModel):
208
+ name: str = Field(..., description="Phone type name")
209
+ enabled: Optional[bool] = Field(None, description="Enabled flag")
210
+ show_in_contact_page: Optional[bool] = Field(None, description="Show in contact page flag")
211
+
212
+
213
+ class PhoneTypeUpdateIn(BaseModel):
214
+ name: Optional[str] = Field(None, description="Phone type name")
215
+ enabled: Optional[bool] = Field(None, description="Enabled flag")
216
+ show_in_contact_page: Optional[bool] = Field(None, description="Show in contact page flag")
217
+
218
+
219
  class EstShipDateOut(BaseModel):
220
  est_ship_date_id: int = Field(..., description="Estimated ship date ID")
221
  est_ship_date_description: Optional[str] = Field(None, description="Estimated ship date description")
 
291
  est_freights: Optional[List[EstFreightOut]] = Field([], description="List of Estimated Freight options")
292
  status_info: List[StatusInfoOut] = Field(..., description="Project status info")
293
  priorities: Optional[List[PriorityOut]] = Field([], description="List of priorities")
294
+ phone_types: Optional[List[PhoneTypeOut]] = Field([], description="List of phone types")
295
 
296
  class ProjectReferenceResponse(BaseModel):
297
  """Grouped reference data used on project creation forms"""
 
302
  status_info: List[StatusInfoOut] = Field(..., description="Project status info")
303
  purchase_prices: List[PurchasePriceOut] = Field(..., description="Purchase price options")
304
  rental_prices: List[RentalPriceOut] = Field(..., description="Rental price options")
305
+ phone_types: Optional[List[PhoneTypeOut]] = Field([], description="Phone type options")
app/services/reference_service.py CHANGED
@@ -10,7 +10,7 @@ from app.schemas.reference import (
10
  BarrierSizeCreateIn, BarrierSizeUpdateIn, ProductApplicationCreateIn, ProductApplicationUpdateIn,
11
  FOBCreateIn, FOBUpdateIn, EstShipDateCreateIn, EstShipDateUpdateIn,
12
  EstFreightCreateIn, EstFreightUpdateIn, StatusInfoCreateIn, StatusInfoUpdateIn,
13
- PriorityCreateIn, PriorityUpdateIn
14
  )
15
  from typing import List, Dict, Any, Optional
16
  import logging
@@ -76,6 +76,11 @@ class ReferenceDataService:
76
  priorities_data = self.repo.get_priorities(active_only, customer_type_id)
77
  return [PriorityOut(**p) for p in priorities_data]
78
 
 
 
 
 
 
79
  def create_state(self, data: StateCreateIn) -> StateOut:
80
  """Create a new state"""
81
  data_dict = data.model_dump()
@@ -344,6 +349,24 @@ class ReferenceDataService:
344
  """Delete a priority"""
345
  return self.repo.delete_priority(priority_id)
346
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347
  def get_fobs(self, active_only: bool = True):
348
  """Get all FOBs as Pydantic models"""
349
  fobs_data = self.repo.get_fobs(active_only)
@@ -451,6 +474,8 @@ class ReferenceDataService:
451
  response_kwargs['project_statuses'] = [ProjectStatusOut(**ps) for ps in all_data['project_statuses']]
452
  if 'priorities' in all_data:
453
  response_kwargs['priorities'] = [PriorityOut(**p) for p in all_data['priorities']]
 
 
454
 
455
  return ReferenceDataResponse(**response_kwargs)
456
  except Exception as e:
 
10
  BarrierSizeCreateIn, BarrierSizeUpdateIn, ProductApplicationCreateIn, ProductApplicationUpdateIn,
11
  FOBCreateIn, FOBUpdateIn, EstShipDateCreateIn, EstShipDateUpdateIn,
12
  EstFreightCreateIn, EstFreightUpdateIn, StatusInfoCreateIn, StatusInfoUpdateIn,
13
+ PriorityCreateIn, PriorityUpdateIn, PhoneTypeOut, PhoneTypeCreateIn, PhoneTypeUpdateIn
14
  )
15
  from typing import List, Dict, Any, Optional
16
  import logging
 
76
  priorities_data = self.repo.get_priorities(active_only, customer_type_id)
77
  return [PriorityOut(**p) for p in priorities_data]
78
 
79
+ def get_phone_types(self, active_only: bool = False) -> List[PhoneTypeOut]:
80
+ """Get all phone types as Pydantic models"""
81
+ phone_types_data = self.repo.get_phone_types(active_only)
82
+ return [PhoneTypeOut(**pt) for pt in phone_types_data]
83
+
84
  def create_state(self, data: StateCreateIn) -> StateOut:
85
  """Create a new state"""
86
  data_dict = data.model_dump()
 
349
  """Delete a priority"""
350
  return self.repo.delete_priority(priority_id)
351
 
352
+ def create_phone_type(self, data: PhoneTypeCreateIn) -> PhoneTypeOut:
353
+ """Create a new phone type"""
354
+ data_dict = data.model_dump()
355
+ result = self.repo.create_phone_type(data_dict)
356
+ return PhoneTypeOut(**result)
357
+
358
+ def update_phone_type(self, phone_type_id: int, data: PhoneTypeUpdateIn) -> Optional[PhoneTypeOut]:
359
+ """Update an existing phone type"""
360
+ data_dict = data.model_dump(exclude_unset=True)
361
+ result = self.repo.update_phone_type(phone_type_id, data_dict)
362
+ if result:
363
+ return PhoneTypeOut(**result)
364
+ return None
365
+
366
+ def delete_phone_type(self, phone_type_id: int) -> bool:
367
+ """Delete a phone type"""
368
+ return self.repo.delete_phone_type(phone_type_id)
369
+
370
  def get_fobs(self, active_only: bool = True):
371
  """Get all FOBs as Pydantic models"""
372
  fobs_data = self.repo.get_fobs(active_only)
 
474
  response_kwargs['project_statuses'] = [ProjectStatusOut(**ps) for ps in all_data['project_statuses']]
475
  if 'priorities' in all_data:
476
  response_kwargs['priorities'] = [PriorityOut(**p) for p in all_data['priorities']]
477
+ if 'phone_types' in all_data:
478
+ response_kwargs['phone_types'] = [PhoneTypeOut(**pt) for pt in all_data['phone_types']]
479
 
480
  return ReferenceDataResponse(**response_kwargs)
481
  except Exception as e: