-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add company to migration and new domain jobs including model
- Loading branch information
shri
committed
Jul 30, 2024
1 parent
8c799ea
commit 835be76
Showing
13 changed files
with
496 additions
and
7 deletions.
There are no files selected for viewing
138 changes: 138 additions & 0 deletions
138
...p/db/migrations/versions/2024-07-30_make_tenant_id_mandatory_in_user_and__a05c476c0ae9.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
# type: ignore | ||
"""Make tenant_id mandatory in user and add models company and job post | ||
Revision ID: a05c476c0ae9 | ||
Revises: b6ffcfae703a | ||
Create Date: 2024-07-30 12:21:24.309890+00:00 | ||
""" | ||
from __future__ import annotations | ||
|
||
import warnings | ||
from typing import TYPE_CHECKING | ||
|
||
import sqlalchemy as sa | ||
from alembic import op | ||
from advanced_alchemy.types import EncryptedString, EncryptedText, GUID, ORA_JSONB, DateTimeUTC | ||
from sqlalchemy import Text # noqa: F401 | ||
from sqlalchemy.dialects import postgresql | ||
|
||
from app.db.models.custom_types import LocationType, FundingType | ||
if TYPE_CHECKING: | ||
from collections.abc import Sequence | ||
|
||
__all__ = ["downgrade", "upgrade", "schema_upgrades", "schema_downgrades", "data_upgrades", "data_downgrades"] | ||
|
||
sa.GUID = GUID | ||
sa.DateTimeUTC = DateTimeUTC | ||
sa.ORA_JSONB = ORA_JSONB | ||
sa.EncryptedString = EncryptedString | ||
sa.EncryptedText = EncryptedText | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = 'a05c476c0ae9' | ||
down_revision = 'b6ffcfae703a' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
with warnings.catch_warnings(): | ||
warnings.filterwarnings("ignore", category=UserWarning) | ||
with op.get_context().autocommit_block(): | ||
schema_upgrades() | ||
data_upgrades() | ||
|
||
def downgrade() -> None: | ||
with warnings.catch_warnings(): | ||
warnings.filterwarnings("ignore", category=UserWarning) | ||
with op.get_context().autocommit_block(): | ||
data_downgrades() | ||
schema_downgrades() | ||
|
||
def schema_upgrades() -> None: | ||
"""schema upgrade migrations go here.""" | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.create_table('company', | ||
sa.Column('id', sa.GUID(length=16), nullable=False), | ||
sa.Column('name', sa.String(), nullable=False), | ||
sa.Column('description', sa.String(length=500), nullable=True), | ||
sa.Column('type', sa.String(), nullable=True), | ||
sa.Column('industry', sa.String(), nullable=True), | ||
sa.Column('headcount', sa.Integer(), nullable=True), | ||
sa.Column('founded_year', sa.Integer(), nullable=True), | ||
sa.Column('url', sa.String(length=2083), nullable=True), | ||
sa.Column('profile_pic_url', sa.String(), nullable=True), | ||
sa.Column('linkedin_profile_url', sa.String(), nullable=True), | ||
sa.Column('hq_location', LocationType(astext_type=Text()), nullable=True), | ||
sa.Column('last_funding', FundingType(astext_type=Text()), nullable=True), | ||
sa.Column('slug', sa.String(length=100), nullable=False), | ||
sa.Column('sa_orm_sentinel', sa.Integer(), nullable=True), | ||
sa.Column('created_at', sa.DateTimeUTC(timezone=True), nullable=False), | ||
sa.Column('updated_at', sa.DateTimeUTC(timezone=True), nullable=False), | ||
sa.PrimaryKeyConstraint('id', name=op.f('pk_company')), | ||
sa.UniqueConstraint('slug', name='uq_company_slug') | ||
) | ||
with op.batch_alter_table('company', schema=None) as batch_op: | ||
batch_op.create_index(batch_op.f('ix_company_headcount'), ['headcount'], unique=False) | ||
batch_op.create_index(batch_op.f('ix_company_industry'), ['industry'], unique=False) | ||
batch_op.create_index(batch_op.f('ix_company_name'), ['name'], unique=False) | ||
batch_op.create_index('ix_company_slug_unique', ['slug'], unique=True) | ||
batch_op.create_index(batch_op.f('ix_company_type'), ['type'], unique=False) | ||
|
||
op.create_table('job_post', | ||
sa.Column('id', sa.GUID(length=16), nullable=False), | ||
sa.Column('title', sa.String(), nullable=False), | ||
sa.Column('body', sa.Text(), nullable=True), | ||
sa.Column('location', LocationType(astext_type=Text()), nullable=True), | ||
sa.Column('seniority_level', sa.String(), nullable=True), | ||
sa.Column('employment_type', sa.String(), nullable=True), | ||
sa.Column('job_functions', postgresql.JSONB(astext_type=sa.Text()), nullable=True), | ||
sa.Column('total_applicants', sa.Integer(), nullable=True), | ||
sa.Column('url', sa.String(length=2083), nullable=True), | ||
sa.Column('apply_url', sa.String(length=2083), nullable=True), | ||
sa.Column('external_id', sa.String(), nullable=True), | ||
sa.Column('company_id', sa.GUID(length=16), nullable=True), | ||
sa.Column('sa_orm_sentinel', sa.Integer(), nullable=True), | ||
sa.Column('created_at', sa.DateTimeUTC(timezone=True), nullable=False), | ||
sa.Column('updated_at', sa.DateTimeUTC(timezone=True), nullable=False), | ||
sa.ForeignKeyConstraint(['company_id'], ['company.id'], name=op.f('fk_job_post_company_id_company')), | ||
sa.PrimaryKeyConstraint('id', name=op.f('pk_job_post')) | ||
) | ||
with op.batch_alter_table('job_post', schema=None) as batch_op: | ||
batch_op.create_index(batch_op.f('ix_job_post_title'), ['title'], unique=False) | ||
|
||
with op.batch_alter_table('user_account', schema=None) as batch_op: | ||
batch_op.alter_column('tenant_id', | ||
existing_type=sa.UUID(), | ||
nullable=False) | ||
|
||
# ### end Alembic commands ### | ||
|
||
def schema_downgrades() -> None: | ||
"""schema downgrade migrations go here.""" | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
with op.batch_alter_table('user_account', schema=None) as batch_op: | ||
batch_op.alter_column('tenant_id', | ||
existing_type=sa.UUID(), | ||
nullable=True) | ||
|
||
with op.batch_alter_table('job_post', schema=None) as batch_op: | ||
batch_op.drop_index(batch_op.f('ix_job_post_title')) | ||
|
||
op.drop_table('job_post') | ||
with op.batch_alter_table('company', schema=None) as batch_op: | ||
batch_op.drop_index(batch_op.f('ix_company_type')) | ||
batch_op.drop_index('ix_company_slug_unique') | ||
batch_op.drop_index(batch_op.f('ix_company_name')) | ||
batch_op.drop_index(batch_op.f('ix_company_industry')) | ||
batch_op.drop_index(batch_op.f('ix_company_headcount')) | ||
|
||
op.drop_table('company') | ||
# ### end Alembic commands ### | ||
|
||
def data_upgrades() -> None: | ||
"""Add any optional data upgrade migrations here!""" | ||
|
||
def data_downgrades() -> None: | ||
"""Add any optional data downgrade migrations here!""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
from uuid import UUID | ||
from advanced_alchemy.base import SlugKey, UUIDAuditBase | ||
from sqlalchemy import String, Text, ForeignKey | ||
from sqlalchemy.dialects.postgresql import JSONB | ||
from sqlalchemy.orm import Mapped, mapped_column, relationship | ||
|
||
from app.lib.schema import Location, Funding | ||
from .custom_types import LocationType, FundingType | ||
from .company import Company | ||
|
||
|
||
class JobPost(UUIDAuditBase): | ||
"""A job post.""" | ||
|
||
__tablename__ = "job_post" | ||
__pii_columns__ = {} | ||
title: Mapped[str] = mapped_column(nullable=False, index=True) | ||
body: Mapped[str | None] = mapped_column(Text, nullable=True, default=None) | ||
location: Mapped[Location | None] = mapped_column(LocationType, nullable=True, default=None) | ||
seniority_level: Mapped[str | None] = mapped_column(nullable=True, default=None) | ||
employment_type: Mapped[str | None] = mapped_column(nullable=True, default=None) | ||
job_functions: Mapped[list[str] | None] = mapped_column(JSONB, nullable=True, default=None) | ||
total_applicants: Mapped[int | None] = mapped_column(nullable=True, default=None) | ||
url: Mapped[str | None] = mapped_column(String(length=2083), nullable=True, default=None) | ||
apply_url: Mapped[str | None] = mapped_column(String(length=2083), nullable=True, default=None) | ||
external_id: Mapped[str | None] = mapped_column(nullable=True, default=None) | ||
company_id: Mapped[UUID] = mapped_column(ForeignKey("company.id"), nullable=True) | ||
# ----------- | ||
# ORM Relationships | ||
# ------------ | ||
company: Mapped[Company] = relationship( | ||
lazy="joined", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"""Job Application Module.""" | ||
from . import controllers, dependencies, schemas, services | ||
|
||
__all__ = ["controllers", "services", "schemas", "dependencies"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .job_posts import JobPostController | ||
|
||
__all__ = ["JobPostController"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
"""Job Post Controllers.""" | ||
|
||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING, Annotated | ||
|
||
from litestar import Controller, delete, get, patch, post | ||
from litestar.di import Provide | ||
|
||
from app.config import constants | ||
from app.db.models import User as UserModel | ||
from app.domain.accounts.guards import requires_active_user | ||
from app.domain.jobs import urls | ||
from app.domain.jobs.dependencies import provide_job_posts_service | ||
from app.domain.jobs.schemas import JobPost, JobPostCreate, JobPostUpdate | ||
from app.domain.jobs.services import JobPostService | ||
|
||
if TYPE_CHECKING: | ||
from uuid import UUID | ||
|
||
from advanced_alchemy.service.pagination import OffsetPagination | ||
from litestar.params import Dependency, Parameter | ||
|
||
from app.lib.dependencies import FilterTypes | ||
|
||
|
||
class JobPostController(Controller): | ||
"""JobPost operations.""" | ||
|
||
tags = ["Job Posts"] | ||
dependencies = {"job_posts_service": Provide(provide_job_posts_service)} | ||
guards = [requires_active_user] | ||
signature_namespace = { | ||
"JobPostService": JobPostService, | ||
} | ||
dto = None | ||
return_dto = None | ||
|
||
@get( | ||
operation_id="ListJobPosts", | ||
name="jobs:list-post", | ||
summary="List Job Posts", | ||
path=urls.JOBS_LIST, | ||
) | ||
async def list_job_posts( | ||
self, | ||
job_posts_service: JobPostService, | ||
filters: Annotated[list[FilterTypes], Dependency(skip_validation=True)], | ||
) -> OffsetPagination[JobPost]: | ||
"""List job_posts that your account can access..""" | ||
results, total = await job_posts_service.get_job_posts(*filters) | ||
return job_posts_service.to_schema(data=results, total=total, schema_type=JobPost, filters=filters) | ||
|
||
@post( | ||
operation_id="CreateJobPost", | ||
name="jobs:create-post", | ||
summary="Create a new job post.", | ||
path=urls.JOBS_CREATE, | ||
) | ||
async def create_job_post( | ||
self, | ||
job_posts_service: JobPostService, | ||
data: JobPostCreate, | ||
) -> JobPostCreate: | ||
"""Create a new job post.""" | ||
obj = data.to_dict() | ||
db_obj = await job_posts_service.create(obj) | ||
return job_posts_service.to_schema(schema_type=JobPost, data=db_obj) | ||
|
||
@get( | ||
operation_id="GetJobPost", | ||
name="jobs:get-post", | ||
summary="Retrieve the details of a job post.", | ||
path=urls.JOBS_DETAIL, | ||
) | ||
async def get_job_post( | ||
self, | ||
job_posts_service: JobPostService, | ||
job_post_id: Annotated[ | ||
UUID, | ||
Parameter( | ||
title="JobPost ID", | ||
description="The job_post to retrieve.", | ||
), | ||
], | ||
) -> JobPost: | ||
"""Get details about a job post.""" | ||
db_obj = await job_posts_service.get(job_post_id) | ||
return job_posts_service.to_schema(schema_type=JobPost, data=db_obj) | ||
|
||
@patch( | ||
operation_id="UpdateJobPost", | ||
name="jobs:update-post", | ||
path=urls.JOBS_UPDATE, | ||
) | ||
async def update_job_post( | ||
self, | ||
data: JobPostUpdate, | ||
job_posts_service: JobPostService, | ||
job_post_id: Annotated[ | ||
UUID, | ||
Parameter( | ||
title="JobPost ID", | ||
description="The job_post to update.", | ||
), | ||
], | ||
) -> JobPost: | ||
"""Update a job post.""" | ||
db_obj = await job_posts_service.update( | ||
item_id=job_post_id, | ||
data=data.to_dict(), | ||
) | ||
return job_posts_service.to_schema(schema_type=JobPost, data=db_obj) | ||
|
||
@delete( | ||
operation_id="DeleteJobPost", | ||
name="jobs:delete-post", | ||
summary="Remove JobPost", | ||
path=urls.JOBS_DELETE, | ||
) | ||
async def delete_job_post( | ||
self, | ||
job_posts_service: JobPostService, | ||
job_post_id: Annotated[ | ||
UUID, | ||
Parameter(title="JobPost ID", description="The job_post to delete."), | ||
], | ||
) -> None: | ||
"""Delete a job_post.""" | ||
_ = await job_posts_service.delete(job_post_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
"""Job Post Controllers.""" | ||
|
||
from __future__ import annotations | ||
|
||
from typing import TYPE_CHECKING | ||
|
||
from sqlalchemy.orm import joinedload, noload, selectinload | ||
|
||
from app.db.models import JobPost | ||
from app.domain.jobs.services import JobPostService | ||
|
||
__all__ = ("provide_job_posts_service", ) | ||
|
||
|
||
if TYPE_CHECKING: | ||
from collections.abc import AsyncGenerator | ||
|
||
from sqlalchemy.ext.asyncio import AsyncSession | ||
|
||
|
||
async def provide_job_posts_service(db_session: AsyncSession) -> AsyncGenerator[JobPostService, None]: | ||
"""Construct repository and service objects for the request.""" | ||
async with JobPostService.new( | ||
session=db_session, | ||
load=[], | ||
) as service: | ||
yield service |
Oops, something went wrong.