From 5772a3948dbd84c0c27930ea7fda7db812d457c1 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Fri, 24 Jul 2026 12:09:06 +0700 Subject: [PATCH] Remove 'code' field from BusinessType model, schemas, factory, and service; update related tests --- app/factories/business_type_factory.py | 1 - app/models/business_type.py | 1 - app/schemas/business_type.py | 3 -- app/services/business_type_service.py | 17 +------ .../2026-07-24-hapus-kode-business-type.md | 44 +++++++++++++++++++ tests/test_business_type.py | 38 +++++----------- 6 files changed, 57 insertions(+), 47 deletions(-) create mode 100644 docs/history/2026-07-24-hapus-kode-business-type.md diff --git a/app/factories/business_type_factory.py b/app/factories/business_type_factory.py index 13b8794..0f6b39c 100644 --- a/app/factories/business_type_factory.py +++ b/app/factories/business_type_factory.py @@ -8,7 +8,6 @@ class BusinessTypeFactory(Factory): def definition(self) -> dict: return { "id": None, - "code": random_string(8), "name": f"Business {random_string(6).title()}", "description": None, "is_active": True, diff --git a/app/models/business_type.py b/app/models/business_type.py index 810a2a4..6db5071 100644 --- a/app/models/business_type.py +++ b/app/models/business_type.py @@ -12,7 +12,6 @@ class BusinessType(Base): __tablename__ = "business_types" id: Mapped[str] = mapped_column(CHAR(36), primary_key=True, default=lambda: str(uuid.uuid4())) - code: Mapped[str] = mapped_column(String(30), unique=True) name: Mapped[str] = mapped_column(String(100)) description: Mapped[str | None] = mapped_column(Text, nullable=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True) diff --git a/app/schemas/business_type.py b/app/schemas/business_type.py index 9155a59..4e88c28 100644 --- a/app/schemas/business_type.py +++ b/app/schemas/business_type.py @@ -4,13 +4,11 @@ from pydantic import BaseModel class BusinessTypeCreate(BaseModel): - code: str name: str description: str | None = None class BusinessTypeUpdate(BaseModel): - code: str | None = None name: str | None = None description: str | None = None is_active: bool | None = None @@ -22,7 +20,6 @@ class BusinessTypeToggleStatus(BaseModel): class BusinessTypeResponse(BaseModel): id: str - code: str name: str description: str | None is_active: bool diff --git a/app/services/business_type_service.py b/app/services/business_type_service.py index e931a7a..9ec0258 100644 --- a/app/services/business_type_service.py +++ b/app/services/business_type_service.py @@ -11,7 +11,7 @@ def get_business_type_list(db: Session, is_active: bool = None): query = db.query(BusinessType).filter(BusinessType.deleted_at.is_(None)) if is_active is not None: query = query.filter(BusinessType.is_active == is_active) - return query.all() + return query.order_by(BusinessType.created_at.desc()).all() def get_business_type_by_id(db: Session, id: str): @@ -25,13 +25,6 @@ def get_business_type_by_id(db: Session, id: str): def create_business_type(db: Session, data: BusinessTypeCreate): - existing = db.query(BusinessType).filter(BusinessType.code == data.code).first() - if existing: - raise HTTPException( - status_code=status.HTTP_409_CONFLICT, - detail={"message": "Code already exists"}, - ) - bt = BusinessType(**data.model_dump()) db.add(bt) db.commit() @@ -49,14 +42,6 @@ def update_business_type(db: Session, id: str, data: BusinessTypeUpdate): update_data = data.model_dump(exclude_unset=True) - if "code" in update_data: - dup = db.query(BusinessType).filter(BusinessType.code == update_data["code"], BusinessType.id != id).first() - if dup: - raise HTTPException( - status_code=status.HTTP_409_CONFLICT, - detail={"message": "Code already exists"}, - ) - for field, value in update_data.items(): setattr(bt, field, value) diff --git a/docs/history/2026-07-24-hapus-kode-business-type.md b/docs/history/2026-07-24-hapus-kode-business-type.md new file mode 100644 index 0000000..446fae3 --- /dev/null +++ b/docs/history/2026-07-24-hapus-kode-business-type.md @@ -0,0 +1,44 @@ +# Hapus Kolom Code dari Business Type + +**Tanggal:** 2026-07-24 +**Status:** Selesai + +## Tujuan +Menghapus kolom `code` dari tabel `business_types` dan seluruh referensinya di API. + +## Yang Dikerjakan + +### 1. Model +- Hapus field `code: Mapped[str]` dari `BusinessType` model +- Sebelum: `code`, `name`, `description`, `is_active` +- Sesudah: `name`, `description`, `is_active` + +### 2. Schema +- Hapus `code` dari `BusinessTypeCreate`, `BusinessTypeUpdate`, `BusinessTypeResponse` +- Sebelum: `BusinessTypeCreate(code, name, description)` +- Sesudah: `BusinessTypeCreate(name, description)` + +### 3. Service +- Hapus uniqueness check `code` di `create_business_type()` +- Hapus uniqueness check `code` di `update_business_type()` + +### 4. Factory +- Hapus `code` dari `BusinessTypeFactory.definition()` + +### 5. Tests +- Hapus semua referensi `code` dari test service dan API +- Hapus test `test_create_duplicate_code` dan `test_update_conflict_code` + +## File yang Diubah + +| File | Aksi | Detail | +|------|------|--------| +| `api/app/models/business_type.py` | Diubah | Hapus field `code` | +| `api/app/schemas/business_type.py` | Diubah | Hapus `code` dari Create, Update, Response | +| `api/app/services/business_type_service.py` | Diubah | Hapus uniqueness check `code` | +| `api/app/factories/business_type_factory.py` | Diubah | Hapus `code` dari definition | +| `api/tests/test_business_type.py` | Diubah | Hapus referensi `code` dan test duplikasi | + +## Notes +- Perlu jalankan SQL `ALTER TABLE business_types DROP COLUMN code;` di database +- Tidak ada migrasi tool (Alembic), jadi harus manual via SQL diff --git a/tests/test_business_type.py b/tests/test_business_type.py index 0175b33..badfbc8 100644 --- a/tests/test_business_type.py +++ b/tests/test_business_type.py @@ -19,19 +19,12 @@ class TestService: assert get_business_type_list(db_session) == [] def test_create(self, db_session: Session): - data = BusinessTypeCreate(code="RETAIL", name="Retail") + data = BusinessTypeCreate(name="Retail") bt = create_business_type(db_session, data) - assert bt.code == "RETAIL" assert bt.name == "Retail" - def test_create_duplicate_code(self, db_session: Session): - create_business_type(db_session, BusinessTypeCreate(code="RETAIL", name="A")) - with pytest.raises(HTTPException) as exc: - create_business_type(db_session, BusinessTypeCreate(code="RETAIL", name="B")) - assert exc.value.status_code == 409 - def test_get_by_id(self, db_session: Session): - bt = create_business_type(db_session, BusinessTypeCreate(code="GROCERY", name="Grocery")) + bt = create_business_type(db_session, BusinessTypeCreate(name="Grocery")) result = get_business_type_by_id(db_session, bt.id) assert result.id == bt.id @@ -41,25 +34,18 @@ class TestService: assert exc.value.status_code == 404 def test_update(self, db_session: Session): - bt = create_business_type(db_session, BusinessTypeCreate(code="CAFE", name="Cafe")) + bt = create_business_type(db_session, BusinessTypeCreate(name="Cafe")) data = BusinessTypeUpdate(name="Coffee Shop") updated = update_business_type(db_session, bt.id, data) assert updated.name == "Coffee Shop" - def test_update_conflict_code(self, db_session: Session): - create_business_type(db_session, BusinessTypeCreate(code="A", name="A")) - bt = create_business_type(db_session, BusinessTypeCreate(code="B", name="B")) - with pytest.raises(HTTPException) as exc: - update_business_type(db_session, bt.id, BusinessTypeUpdate(code="A")) - assert exc.value.status_code == 409 - def test_update_not_found(self, db_session: Session): with pytest.raises(HTTPException) as exc: update_business_type(db_session, "x", BusinessTypeUpdate(name="X")) assert exc.value.status_code == 404 def test_delete(self, db_session: Session): - bt = create_business_type(db_session, BusinessTypeCreate(code="DEL", name="Del")) + bt = create_business_type(db_session, BusinessTypeCreate(name="Del")) delete_business_type(db_session, bt.id) assert bt.deleted_at is not None @@ -69,32 +55,32 @@ class TestService: assert exc.value.status_code == 404 def test_soft_deleted_excluded(self, db_session: Session): - create_business_type(db_session, BusinessTypeCreate(code="KEEP", name="Keep")) - bt = create_business_type(db_session, BusinessTypeCreate(code="GONE", name="Gone")) + create_business_type(db_session, BusinessTypeCreate(name="Keep")) + bt = create_business_type(db_session, BusinessTypeCreate(name="Gone")) delete_business_type(db_session, bt.id) assert len(get_business_type_list(db_session)) == 1 class TestAPI: def test_create(self, client: TestClient): - resp = client.post("/v1/business-types/", json={"code": "TOKO", "name": "Toko"}) + resp = client.post("/v1/business-types/", json={"name": "Toko"}) assert resp.status_code == 201 assert resp.json() == {"message": "The item was created successfully"} def test_list(self, client: TestClient, db_session: Session): - db_session.add(BusinessType(code="A", name="A")) + db_session.add(BusinessType(name="A")) db_session.commit() resp = client.get("/v1/business-types/") assert resp.status_code == 200 assert len(resp.json()) == 1 def test_get_by_id(self, client: TestClient, db_session: Session): - bt = BusinessType(code="GET", name="Get") + bt = BusinessType(name="Get") db_session.add(bt) db_session.commit() resp = client.get(f"/v1/business-types/{bt.id}") assert resp.status_code == 200 - assert resp.json()["code"] == "GET" + assert resp.json()["name"] == "Get" def test_get_not_found(self, client: TestClient): resp = client.get("/v1/business-types/x") @@ -102,7 +88,7 @@ class TestAPI: assert resp.json() == {"message": "The item does not exist"} def test_update(self, client: TestClient, db_session: Session): - bt = BusinessType(code="UPD", name="Old") + bt = BusinessType(name="Old") db_session.add(bt) db_session.commit() resp = client.put(f"/v1/business-types/{bt.id}", json={"name": "New"}) @@ -110,7 +96,7 @@ class TestAPI: assert resp.json()["name"] == "New" def test_delete(self, client: TestClient, db_session: Session): - bt = BusinessType(code="DEL", name="Del") + bt = BusinessType(name="Del") db_session.add(bt) db_session.commit() resp = client.delete(f"/v1/business-types/{bt.id}")