Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update code to reflect domain language #30

Merged
merged 1 commit into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Rename data_providers to data_producers and rename column in data_submissions

Revision ID: 342dce4f5753
Revises: 851709d3a162
Create Date: 2024-02-14 08:40:16.897824

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "342dce4f5753"
down_revision: Union[str, None] = "851709d3a162"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.rename_table("data_providers", "data_producers")
op.alter_column(
"data_submissions", "data_provider_id", new_column_name="data_producer_id"
)


def downgrade() -> None:
op.alter_column(
"data_submissions", "data_producer_id", new_column_name="data_provider_id"
)
op.rename_table("data_producers", "data_providers")
2 changes: 1 addition & 1 deletion alembic/versions/851709d3a162_add_report_column.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ def upgrade():
)


def add_column():
def downgrade():
op.drop_column("data_submissions", "report")
14 changes: 14 additions & 0 deletions documentation/terminology.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# NAD Collaboration Hub Terminology

## Acronyms

- GIS: geographic information system
- NAD: National Address Database

## Key Concepts

- Data Producer: a representative from a state, local, or tribal government
who wants to submit address data for inclusion in the NAD.

- Data Submission: a GIS dataset that a Data Producer submits for inclusion
in the NAD.
6 changes: 3 additions & 3 deletions nad_ch/application/interfaces.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Optional, Protocol
from nad_ch.application.dtos import DownloadResult
from nad_ch.domain.repositories import DataProviderRepository, DataSubmissionRepository
from nad_ch.domain.repositories import DataProducerRepository, DataSubmissionRepository


class Logger(Protocol):
Expand Down Expand Up @@ -37,8 +37,8 @@ def run_load_and_validate(

class ApplicationContext:
@property
def providers(self) -> DataProviderRepository:
return self._providers
def producers(self) -> DataProducerRepository:
return self._producers

@property
def submissions(self) -> DataSubmissionRepository:
Expand Down
72 changes: 36 additions & 36 deletions nad_ch/application/use_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,42 @@
from nad_ch.application.interfaces import ApplicationContext
from nad_ch.application.view_models import (
get_view_model,
DataProviderViewModel,
DataProducerViewModel,
DataSubmissionViewModel,
)
from nad_ch.domain.entities import DataProvider, DataSubmission
from nad_ch.domain.entities import DataProducer, DataSubmission


def add_data_provider(
ctx: ApplicationContext, provider_name: str
) -> DataProviderViewModel:
if not provider_name:
ctx.logger.error("Provider name required")
def add_data_producer(
ctx: ApplicationContext, producer_name: str
) -> DataProducerViewModel:
if not producer_name:
ctx.logger.error("Producer name required")
return

matching_provider = ctx.providers.get_by_name(provider_name)
if matching_provider:
ctx.logger.error("Provider name must be unique")
matching_producer = ctx.producers.get_by_name(producer_name)
if matching_producer:
ctx.logger.error("Producer name must be unique")
return

provider = DataProvider(provider_name)
ctx.providers.add(provider)
ctx.logger.info("Provider added")
producer = DataProducer(producer_name)
saved_producer = ctx.producers.add(producer)
ctx.logger.info("Producer added")

return get_view_model(provider)
return get_view_model(saved_producer)


def list_data_providers(ctx: ApplicationContext) -> List[DataProviderViewModel]:
providers = ctx.providers.get_all()
ctx.logger.info("Data Provider Names:")
for p in providers:
def list_data_producers(ctx: ApplicationContext) -> List[DataProducerViewModel]:
producers = ctx.producers.get_all()
ctx.logger.info("Data Producer Names:")
for p in producers:
ctx.logger.info(p.name)

return get_view_model(providers)
return get_view_model(producers)


def ingest_data_submission(
ctx: ApplicationContext, file_path: str, provider_name: str
ctx: ApplicationContext, file_path: str, producer_name: str
) -> DataSubmissionViewModel:
if not file_path:
ctx.logger.error("File path required")
Expand All @@ -50,20 +50,20 @@ def ingest_data_submission(
ctx.logger.error("Invalid file format. Only ZIP or CSV files are accepted.")
return

provider = ctx.providers.get_by_name(provider_name)
if not provider:
ctx.logger.error("Provider with that name does not exist")
producer = ctx.producers.get_by_name(producer_name)
if not producer:
ctx.logger.error("Producer with that name does not exist")
return

try:
filename = DataSubmission.generate_filename(file_path, provider)
filename = DataSubmission.generate_filename(file_path, producer)
ctx.storage.upload(file_path, filename)

submission = DataSubmission(filename, provider)
ctx.submissions.add(submission)
ctx.logger.info(f"Submission added: {submission.filename}")
submission = DataSubmission(filename, producer)
saved_submission = ctx.submissions.add(submission)
ctx.logger.info(f"Submission added: {saved_submission.filename}")

return get_view_model(submission)
return get_view_model(saved_submission)
except Exception as e:
ctx.storage.delete(filename)
ctx.logger.error(f"Failed to process submission: {e}")
Expand All @@ -80,18 +80,18 @@ def get_data_submission(
return get_view_model(submission)


def list_data_submissions_by_provider(
ctx: ApplicationContext, provider_name: str
def list_data_submissions_by_producer(
ctx: ApplicationContext, producer_name: str
) -> List[DataSubmissionViewModel]:
provider = ctx.providers.get_by_name(provider_name)
if not provider:
ctx.logger.error("Provider with that name does not exist")
producer = ctx.producers.get_by_name(producer_name)
if not producer:
ctx.logger.error("Producer with that name does not exist")
return

submissions = ctx.submissions.get_by_provider(provider)
ctx.logger.info(f"Data submissions for {provider.name}")
submissions = ctx.submissions.get_by_producer(producer)
ctx.logger.info(f"Data submissions for {producer.name}")
for s in submissions:
ctx.logger.info(f"{s.provider.name}: {s.filename}")
ctx.logger.info(f"{s.producer.name}: {s.filename}")

return get_view_model(submissions)

Expand Down
20 changes: 10 additions & 10 deletions nad_ch/application/view_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json
import numpy as np
from typing import Union, List, Tuple
from nad_ch.domain.entities import Entity, DataProvider, DataSubmission
from nad_ch.domain.entities import Entity, DataProducer, DataSubmission


def get_view_model(entity: Union[Entity, List[Entity]]) -> Union[Entity, List[Entity]]:
Expand All @@ -12,7 +12,7 @@ def get_view_model(entity: Union[Entity, List[Entity]]) -> Union[Entity, List[En
get a static view model object that it can return to its caller.
"""
entity_to_vm_function_map = {
DataProvider: create_data_provider_vm,
DataProducer: create_data_producer_vm,
DataSubmission: create_data_submission_vm,
}

Expand All @@ -31,17 +31,17 @@ def get_view_model(entity: Union[Entity, List[Entity]]) -> Union[Entity, List[En


@dataclass
class DataProviderViewModel:
class DataProducerViewModel:
id: int
date_created: str
name: str


def create_data_provider_vm(provider: DataProvider) -> DataProviderViewModel:
return DataProviderViewModel(
id=provider.id,
date_created=present_date(provider.created_at),
name=provider.name,
def create_data_producer_vm(producer: DataProducer) -> DataProducerViewModel:
return DataProducerViewModel(
id=producer.id,
date_created=present_date(producer.created_at),
name=producer.name,
)


Expand All @@ -50,7 +50,7 @@ class DataSubmissionViewModel:
id: int
date_created: str
filename: str
provider_name: str
producer_name: str
report: str


Expand All @@ -65,7 +65,7 @@ def create_data_submission_vm(submission: DataSubmission) -> DataSubmissionViewM
id=submission.id,
date_created=present_date(submission.created_at),
filename=submission.filename,
provider_name=submission.provider.name,
producer_name=submission.producer.name,
report=report_json,
)

Expand Down
8 changes: 4 additions & 4 deletions nad_ch/config/development_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from nad_ch.application.interfaces import ApplicationContext
from nad_ch.infrastructure.database import (
create_session_factory,
SqlAlchemyDataProviderRepository,
SqlAlchemyDataProducerRepository,
SqlAlchemyDataSubmissionRepository,
)
from nad_ch.infrastructure.logger import BasicLogger
Expand Down Expand Up @@ -33,14 +33,14 @@
class DevLocalApplicationContext(ApplicationContext):
def __init__(self):
self._session_factory = create_session_factory(DATABASE_URL)
self._providers = self.create_provider_repository()
self._producers = self.create_producer_repository()
self._submissions = self.create_submission_repository()
self._logger = self.create_logger()
self._storage = self.create_storage()
self._task_queue = self.create_task_queue()

def create_provider_repository(self):
return SqlAlchemyDataProviderRepository(self._session_factory)
def create_producer_repository(self):
return SqlAlchemyDataProducerRepository(self._session_factory)

def create_submission_repository(self):
return SqlAlchemyDataSubmissionRepository(self._session_factory)
Expand Down
8 changes: 4 additions & 4 deletions nad_ch/config/development_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from nad_ch.application.interfaces import ApplicationContext
from nad_ch.infrastructure.database import (
create_session_factory,
SqlAlchemyDataProviderRepository,
SqlAlchemyDataProducerRepository,
SqlAlchemyDataSubmissionRepository,
)
from nad_ch.infrastructure.logger import BasicLogger
Expand Down Expand Up @@ -40,14 +40,14 @@ def get_credentials(service_name, default={}):
class DevRemoteApplicationContext(ApplicationContext):
def __init__(self):
self._session_factory = create_session_factory(DATABASE_URL)
self._providers = self.create_provider_repository()
self._producers = self.create_producer_repository()
self._submissions = self.create_submission_repository()
self._logger = self.create_logger()
self._storage = self.create_storage()
self._task_queue = self.create_task_queue()

def create_provider_repository(self):
return SqlAlchemyDataProviderRepository(self._session_factory)
def create_producer_repository(self):
return SqlAlchemyDataProducerRepository(self._session_factory)

def create_submission_repository(self):
return SqlAlchemyDataSubmissionRepository(self._session_factory)
Expand Down
8 changes: 4 additions & 4 deletions nad_ch/config/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from nad_ch.application.interfaces import ApplicationContext
from nad_ch.infrastructure.logger import BasicLogger
from tests.fakes_and_mocks import (
FakeDataProviderRepository,
FakeDataProducerRepository,
FakeDataSubmissionRepository,
FakeStorage,
)
Expand All @@ -17,14 +17,14 @@
class TestApplicationContext(ApplicationContext):
def __init__(self):
self._session = None
self._providers = self.create_provider_repository()
self._producers = self.create_producer_repository()
self._submissions = self.create_submission_repository()
self._logger = self.create_logger()
self._storage = self.create_storage()
self._task_queue = self.create_task_queue()

def create_provider_repository(self):
return FakeDataProviderRepository()
def create_producer_repository(self):
return FakeDataProducerRepository()

def create_submission_repository(self):
return FakeDataSubmissionRepository()
Expand Down
28 changes: 14 additions & 14 deletions nad_ch/controllers/cli.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import click
from nad_ch.application.use_cases import (
add_data_provider,
list_data_providers,
add_data_producer,
list_data_producers,
ingest_data_submission,
list_data_submissions_by_provider,
list_data_submissions_by_producer,
validate_data_submission,
)

Expand All @@ -16,34 +16,34 @@ def cli(ctx):

@cli.command()
@click.pass_context
@click.argument("provider_name")
def add_provider(ctx, provider_name):
@click.argument("producer_name")
def add_producer(ctx, producer_name):
context = ctx.obj
add_data_provider(context, provider_name)
add_data_producer(context, producer_name)


@cli.command()
@click.pass_context
def list_providers(ctx):
def list_producers(ctx):
context = ctx.obj
list_data_providers(context)
list_data_producers(context)


@cli.command()
@click.pass_context
@click.argument("file_path")
@click.argument("provider")
def ingest(ctx, file_path, provider):
@click.argument("producer")
def ingest(ctx, file_path, producer):
context = ctx.obj
ingest_data_submission(context, file_path, provider)
ingest_data_submission(context, file_path, producer)


@cli.command()
@click.pass_context
@click.argument("provider")
def list_submissions_by_provider(ctx, provider):
@click.argument("producer")
def list_submissions_by_producer(ctx, producer):
context = ctx.obj
list_data_submissions_by_provider(context, provider)
list_data_submissions_by_producer(context, producer)


@cli.command()
Expand Down
Loading
Loading