Skip to content
46 changes: 46 additions & 0 deletions python_fundamentals/exercises/day_24_decimal/product_invoice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from decimal import Decimal

from pydantic import BaseModel, Field, computed_field


class Product(BaseModel):
name: str = Field(min_length=3, max_length=20)
price: Decimal
quantity: int

@computed_field
def subtotal(self) -> Decimal:
return self.price * self.quantity


class Invoice(BaseModel):
invoice_id: str
customer_name: str = Field(min_length=3, max_length=20)
products: list[Product]
gst_percentage: Decimal

@computed_field
def subtotal_total(self) -> Decimal:
total: Decimal = Decimal("0")
for product in self.products:
total += product.subtotal
return total

@computed_field
def grand_total(self) -> Decimal:
subtotal: Decimal = self.subtotal_total
gst_amount = subtotal * (self.gst_percentage / 100)
return Decimal(subtotal + gst_amount)


p1: Product = Product(name="Sugar", price=Decimal("20.00"), quantity=1)
p2: Product = Product(name="Oil", price=Decimal("120.00"), quantity=2)

invoice: Invoice = Invoice(
invoice_id="123",
customer_name="Tejas Dixit",
products=[p1, p2],
gst_percentage=Decimal("18"),
)

print(invoice.model_dump())
74 changes: 74 additions & 0 deletions python_fundamentals/exercises/day_25_date_datetime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Day 25 — Date & DateTime

## Objective

Understand when to use `date` and `datetime` in Pydantic models and how Pydantic parses ISO formatted strings into Python objects.

---

## Concepts Covered

- `date`
- `datetime`
- Pydantic parsing
- `ValidationError`
- `model_dump()`
- `model_dump_json()`

---

## Business Use Cases

### `date`

- Employee joining date
- Date of birth
- Manufacturing date

### `datetime`

- User login
- Payment timestamp
- Audit logs
- Record creation time

---

## Key Learning

- Use `date` when only the calendar date is required.
- Use `datetime` when both date and time are required.
- Python validates `date()` and `datetime()` constructors.
- Pydantic parses strings into `date` and `datetime` objects.
- Invalid parsed values raise `ValidationError`.

---

## Run

```bash
uv run python employee.py
```

---

## Expected Output

- Successful creation of a valid `Employee`.
- `model_dump()` returns Python objects.
- `model_dump_json()` returns JSON.
- Invalid input raises `ValidationError`.

---

## Files

```
employee.py
```

---

## Status

✅ Completed
35 changes: 35 additions & 0 deletions python_fundamentals/exercises/day_25_date_datetime/employee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python3.12
from datetime import date, datetime

from pydantic import BaseModel, Field, ValidationError


class Employee(BaseModel):
emp_name: str = Field(min_length=3, max_length=20)
joining_date: date
created_at: datetime


try:
tejas_dixit: Employee = Employee(
emp_name="Tejas Dixit",
joining_date=date(year=2024, month=1, day=29),
created_at=datetime(year=2024, month=1, day=29, hour=13, minute=00, second=20),
)

print(f"Python Representaion of Employee Object: {tejas_dixit.model_dump()}")
print(f"Pydantic Representaion of Employee Object: {tejas_dixit.model_dump_json()}")

vignesh_gawali: Employee = Employee(
emp_name="Vignesh Gawali",
joining_date="2024-12-12", # Intentional: testing Pydantic parsing
created_at="0000-12-12 12:12", # Intentional: testing Pydantic parsing
)

print(f"Python Representaion of Employee Object: {vignesh_gawali.model_dump()}")
print(
f"Pydantic Representaion of Employee Object: {vignesh_gawali.model_dump_json()}"
)

except (ValueError, ValidationError) as exc:
print(exc)
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Day 26 — model_dump()

## Objective

Understand how `model_dump()` serializes a validated Pydantic model into a Python dictionary and how to control serialized output using `include` and `exclude`.

---

## Concepts Covered

- `model_dump()`
- Serialization
- `include`
- `exclude`
- Business Views

---

## Business Use Cases

- HR View
- Admin View
- Public Profile
- API Response
- Logging

---

## Key Learning

- `model_dump()` serializes a validated Pydantic model.
- It returns a standard Python dictionary.
- Use `include` to serialize only required fields.
- Use `exclude` to omit sensitive or unnecessary fields.
- One model can produce multiple business-specific representations.

---

## Run

```bash
uv run python employee.py
```

---

## Expected Output

- Python dictionary representation of the model.
- HR View containing selected fields.
- Admin View excluding selected fields.
- Automatic parsing of ISO formatted strings into Python objects.

---

## Files

```
employee.py
```

---

## Status

✅ Completed
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3.12

# model_dump() serializes a validated Pydantic model into a Python dictionary.
# Prefer model_dump() over __dict__ because it supports Pydantic features
# such as include, exclude, aliases and serializers.


from datetime import date, datetime

from pydantic import BaseModel, Field, ValidationError


class Employee(BaseModel):
"""This Model Represents and Employee of an Companay"""

emp_name: str = Field(min_length=3, max_length=20)
joining_date: date
created_at: datetime


def format_emp() -> None:
print(
"-" * 120,
end="\n",
)


try:
emp: Employee = Employee(
emp_name="Tejas Dixit",
joining_date=date(year=2024, month=1, day=29),
created_at=datetime(year=2024, month=1, day=25, hour=9, minute=30),
)

print(
f"HR View: {emp.model_dump(include={'emp_name', 'joining_date'})}"
) # exclude `created_at` field.

print(
f"ADMIN View: {emp.model_dump(exclude={'joining_date'})}"
) # excludes `joining_date` and include each field.

format_emp()

another_emp: Employee = Employee(
emp_name="Tejas Dixit",
joining_date="2024-12-29",
# Intentional: Pydantic will conert it into date format
created_at="2024-12-28 12:12",
# Intentional: Pydantic model will convert it into datetime format
)

print(
f"HR View: {another_emp.model_dump(include={'emp_name', 'joining_date'})}"
) # exclude `created_at` field.

print(f"ADMIN View: {another_emp.model_dump(exclude={'joining_date'})}")


except (ValueError, ValidationError) as exc:
print(exc)
27 changes: 27 additions & 0 deletions python_fundamentals/exercises/employee_field_serializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from datetime import date, datetime
from decimal import Decimal

from pydantic import BaseModel, field_serializer


class Employee(BaseModel):
name: str
salary: Decimal
joining_date: date

@field_serializer("salary")
def salary_in_dollars(self, salary: Decimal) -> str:
return f"${salary}"

@field_serializer("joining_date")
def format_date(self, date: datetime) -> str:
return date.strftime("%d %b %Y")


emp1: Employee = Employee(
name="Tejas Dixit",
salary=Decimal(25000),
joining_date=date(year=2024, month=1, day=29),
)

print(emp1.model_dump())
Loading
Loading