├── chapter_4
├── itam
│ ├── __init__.py
│ ├── infrastructure
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ └── asset_model.py
│ │ ├── ports
│ │ │ └── asset_rest_port.py
│ │ ├── repository
│ │ │ ├── base_repository.py
│ │ │ ├── sqlalchemy_asset_repository.py
│ │ │ └── in_memory_asset_repository.py
│ │ ├── adapters
│ │ │ ├── asset_rest_adapter.py
│ │ │ └── asset_database_adapter.py
│ │ └── database
│ │ │ └── database_connection.py
│ ├── service
│ │ ├── __init__.py
│ │ └── asset_manager.py
│ ├── visitor
│ │ ├── __init__.py
│ │ └── department_visitor.py
│ └── domain
│ │ ├── department.py
│ │ ├── organization.py
│ │ ├── role.py
│ │ ├── address.py
│ │ ├── snowflake_identifier.py
│ │ ├── budget.py
│ │ ├── location.py
│ │ ├── warranty.py
│ │ ├── maintenance_schedule.py
│ │ ├── __init__.py
│ │ ├── funding_details.py
│ │ ├── user.py
│ │ ├── line_of_business_statistics.py
│ │ ├── factory
│ │ └── asset_factory.py
│ │ ├── asset.py
│ │ ├── software.py
│ │ ├── depreciation_strategy.py
│ │ └── hardware.py
├── README.md
├── requirements.txt
├── main.py
└── diagram2.mmd
├── chapter_5
├── itam
│ ├── __init__.py
│ ├── infrastructure
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ └── asset_model.py
│ │ ├── mediators
│ │ │ └── asset_location_mediator.py
│ │ ├── ports
│ │ │ └── asset_rest_port.py
│ │ ├── repository
│ │ │ ├── base_repository.py
│ │ │ └── in_memory_asset_repository.py
│ │ ├── adapters
│ │ │ ├── asset_rest_adapter.py
│ │ │ └── asset_database_adapter.py
│ │ ├── consumers
│ │ │ └── asset_location_kafka_consumer.py
│ │ └── database
│ │ │ └── database_connection.py
│ ├── service
│ │ ├── __init__.py
│ │ └── asset_manager.py
│ ├── visitor
│ │ ├── __init__.py
│ │ └── department_visitor.py
│ └── domain
│ │ ├── department.py
│ │ ├── events
│ │ └── asset_location_updated.py
│ │ ├── organization.py
│ │ ├── role.py
│ │ ├── location.py
│ │ ├── address.py
│ │ ├── snowflake_identifier.py
│ │ ├── budget.py
│ │ ├── warranty.py
│ │ ├── maintenance_schedule.py
│ │ ├── __init__.py
│ │ ├── funding_details.py
│ │ ├── user.py
│ │ ├── line_of_business_statistics.py
│ │ ├── factory
│ │ └── asset_factory.py
│ │ ├── software.py
│ │ ├── depreciation_strategy.py
│ │ └── hardware.py
├── .gitignore
├── requirements.txt
├── data
│ └── scripts
│ │ └── load.sql
├── README.md
├── docker-compose.yml
├── diagram2.mmd
└── main.py
├── chapter_2
├── chatgpt-fastapi
│ ├── gpt-itam-env
│ │ ├── bin
│ │ │ ├── python
│ │ │ ├── python3
│ │ │ ├── python3.10
│ │ │ ├── flask
│ │ │ ├── uvicorn
│ │ │ ├── pip
│ │ │ ├── pip3
│ │ │ ├── pip3.10
│ │ │ └── activate.csh
│ │ └── pyvenv.cfg
│ ├── requirements.txt
│ ├── requirements.Flask.txt
│ ├── README.md
│ ├── asset.Flask.py
│ ├── asset_manager.Flask.py
│ ├── asset_manager.py
│ └── asset.py
├── chatgpt-flask
│ ├── requirements.txt
│ ├── gpt-itam-env
│ │ ├── pyvenv.cfg
│ │ └── bin
│ │ │ ├── python
│ │ │ ├── python3
│ │ │ ├── python3.10
│ │ │ ├── flask
│ │ │ ├── uvicorn
│ │ │ ├── pip
│ │ │ ├── pip3
│ │ │ ├── pip3.10
│ │ │ └── activate.csh
│ ├── requirements.Flask.txt
│ ├── README.md
│ ├── asset.Flask.py
│ ├── asset_manager.Flask.py
│ ├── asset_manager.py
│ └── asset.py
├── copilot
│ ├── .vscode
│ │ └── settings.json
│ ├── .metals
│ │ └── metals.mv.db
│ ├── requirements.txt
│ ├── asset_manager.py
│ ├── app.py
│ └── asset.py
└── code-whisperer
│ └── asset.py
├── chapter_6
├── .gitignore
├── itam
│ ├── infrastructure
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ └── asset_model.py
│ │ ├── __init__.py
│ │ ├── mediators
│ │ │ └── asset_location_mediator.py
│ │ ├── ports
│ │ │ └── asset_rest_port.py
│ │ ├── repository
│ │ │ ├── base_repository.py
│ │ │ └── in_memory_asset_repository.py
│ │ ├── adapters
│ │ │ ├── asset_rest_adapter.py
│ │ │ └── asset_database_adapter.py
│ │ ├── consumers
│ │ │ └── asset_location_kafka_consumer.py
│ │ └── database
│ │ │ └── database_connection.py
│ ├── service
│ │ ├── __init__.py
│ │ └── asset_manager.py
│ ├── __init__.py
│ ├── visitor
│ │ ├── __init__.py
│ │ └── test_department_visitor.py
│ └── domain
│ │ ├── events
│ │ └── asset_location_updated.py
│ │ ├── department.py
│ │ ├── organization.py
│ │ ├── role.py
│ │ ├── location.py
│ │ ├── address.py
│ │ ├── snowflake_identifier.py
│ │ ├── budget.py
│ │ ├── warranty.py
│ │ ├── maintenance_schedule.py
│ │ ├── __init__.py
│ │ ├── user.py
│ │ ├── funding_details.py
│ │ ├── line_of_business_statistics.py
│ │ ├── factory
│ │ └── asset_factory.py
│ │ ├── software.py
│ │ └── hardware.py
├── requirements.txt
├── features
│ ├── asset_manager.feature
│ └── steps
│ │ └── steps.py
├── data
│ └── scripts
│ │ └── load.sql
├── README.md
├── docker-compose.yml
├── diagram2.mmd
└── main.py
├── chapter_7
├── .gitignore
├── itam
│ ├── infrastructure
│ │ ├── api
│ │ │ ├── __init__.py
│ │ │ └── asset_model.py
│ │ ├── __init__.py
│ │ ├── mediators
│ │ │ └── asset_location_mediator.py
│ │ ├── ports
│ │ │ └── asset_rest_port.py
│ │ ├── repository
│ │ │ ├── base_repository.py
│ │ │ └── in_memory_asset_repository.py
│ │ ├── adapters
│ │ │ ├── asset_rest_adapter.py
│ │ │ └── asset_database_adapter.py
│ │ ├── consumers
│ │ │ └── asset_location_kafka_consumer.py
│ │ └── database
│ │ │ └── database_connection.py
│ ├── service
│ │ ├── __init__.py
│ │ └── asset_manager.py
│ ├── __init__.py
│ ├── visitor
│ │ ├── __init__.py
│ │ └── test_department_visitor.py
│ └── domain
│ │ ├── events
│ │ └── asset_location_updated.py
│ │ ├── department.py
│ │ ├── organization.py
│ │ ├── role.py
│ │ ├── location.py
│ │ ├── address.py
│ │ ├── snowflake_identifier.py
│ │ ├── budget.py
│ │ ├── warranty.py
│ │ ├── maintenance_schedule.py
│ │ ├── __init__.py
│ │ ├── user.py
│ │ ├── funding_details.py
│ │ ├── line_of_business_statistics.py
│ │ ├── factory
│ │ └── asset_factory.py
│ │ ├── software.py
│ │ └── hardware.py
├── README.md
├── requirements.txt
├── features
│ ├── asset_manager.feature
│ └── steps
│ │ └── steps.py
├── data
│ └── scripts
│ │ └── load.sql
├── docker-compose.yml
├── diagram2.mmd
└── main.py
├── README.md
└── chapter_9
├── .idea
├── vcs.xml
├── .gitignore
├── misc.xml
├── inspectionProfiles
│ ├── profiles_settings.xml
│ └── Project_Default.xml
├── modules.xml
└── chapter_9.iml
└── main.py
/chapter_4/itam/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/chapter_5/itam/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/chapter_4/README.md:
--------------------------------------------------------------------------------
1 | # The AI-Assisted Developer Chapter 4
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/python:
--------------------------------------------------------------------------------
1 | python3.10
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/python3:
--------------------------------------------------------------------------------
1 | python3.10
--------------------------------------------------------------------------------
/chapter_5/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | .vscode
4 | .env
5 | .venv
--------------------------------------------------------------------------------
/chapter_6/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | .vscode
4 | .env
5 | .venv
--------------------------------------------------------------------------------
/chapter_7/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | .vscode
4 | .env
5 | .venv
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | The public source code repository for the Manning book - AI Powered Developer
2 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/python3.10:
--------------------------------------------------------------------------------
1 | /opt/homebrew/opt/python@3.10/bin/python3.10
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/requirements.txt:
--------------------------------------------------------------------------------
1 | fastapi==0.70.0
2 | uvicorn==0.15.0
3 | pydantic==1.8.2
4 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/requirements.txt:
--------------------------------------------------------------------------------
1 | fastapi==0.70.0
2 | uvicorn==0.15.0
3 | pydantic==1.8.2
4 |
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/api/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_model import AssetIn
2 |
3 | all = ['AssetIn']
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/api/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_model import AssetIn
2 |
3 | all = ['AssetIn']
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/api/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_model import AssetIn
2 |
3 | all = ['AssetIn']
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/api/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_model import AssetIn
2 |
3 | all = ['AssetIn']
--------------------------------------------------------------------------------
/chapter_2/copilot/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.watcherExclude": {
3 | "**/target": true
4 | }
5 | }
--------------------------------------------------------------------------------
/chapter_4/itam/service/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_manager import AssetManager
2 |
3 | __all__ = [
4 | 'AssetManager',
5 | ]
--------------------------------------------------------------------------------
/chapter_5/itam/service/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_manager import AssetManager
2 |
3 | __all__ = [
4 | 'AssetManager',
5 | ]
--------------------------------------------------------------------------------
/chapter_6/itam/service/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_manager import AssetManager
2 |
3 | __all__ = [
4 | 'AssetManager',
5 | ]
--------------------------------------------------------------------------------
/chapter_7/itam/service/__init__.py:
--------------------------------------------------------------------------------
1 | from .asset_manager import AssetManager
2 |
3 | __all__ = [
4 | 'AssetManager',
5 | ]
--------------------------------------------------------------------------------
/chapter_6/itam/__init__.py:
--------------------------------------------------------------------------------
1 | from .infrastructure import *
2 | from .domain import *
3 | from .service import *
4 | from .visitor import *
5 |
--------------------------------------------------------------------------------
/chapter_7/itam/__init__.py:
--------------------------------------------------------------------------------
1 | from .infrastructure import *
2 | from .domain import *
3 | from .service import *
4 | from .visitor import *
5 |
--------------------------------------------------------------------------------
/chapter_2/copilot/.metals/metals.mv.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathanbcrocker/ai_powered_developer/HEAD/chapter_2/copilot/.metals/metals.mv.db
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/pyvenv.cfg:
--------------------------------------------------------------------------------
1 | home = /opt/homebrew/opt/python@3.10/bin
2 | include-system-site-packages = false
3 | version = 3.10.6
4 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/pyvenv.cfg:
--------------------------------------------------------------------------------
1 | home = /opt/homebrew/opt/python@3.10/bin
2 | include-system-site-packages = false
3 | version = 3.10.6
4 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/python:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathanbcrocker/ai_powered_developer/HEAD/chapter_2/chatgpt-flask/gpt-itam-env/bin/python
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/python3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathanbcrocker/ai_powered_developer/HEAD/chapter_2/chatgpt-flask/gpt-itam-env/bin/python3
--------------------------------------------------------------------------------
/chapter_2/copilot/requirements.txt:
--------------------------------------------------------------------------------
1 | # generate a requirements.txt file for this project
2 | fastapi==0.63.0
3 | uvicorn==0.13.4
4 | pydantic==1.7.3
5 | starlette==0.13.6
--------------------------------------------------------------------------------
/chapter_4/requirements.txt:
--------------------------------------------------------------------------------
1 | # pip install uvicorn
2 | # pip install fastapi
3 |
4 | uvicorn==0.11.8
5 | fastapi==0.61.1
6 | psycopg2-binary==2.9.6
7 | SQLAlchemy==2.0.9
--------------------------------------------------------------------------------
/chapter_7/README.md:
--------------------------------------------------------------------------------
1 | # The AI-Assisted Developer Chapter 7
2 |
3 | Dockerfiles are not currently supported by AWS CodeWhisperer
4 | Copilot does not support Terraform
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/python3.10:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nathanbcrocker/ai_powered_developer/HEAD/chapter_2/chatgpt-flask/gpt-itam-env/bin/python3.10
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/__init__.py:
--------------------------------------------------------------------------------
1 | from .adapters import *
2 | from .api import *
3 | from .consumers import *
4 | from .database import *
5 | from .mediators import *
6 | from .ports import *
7 | from.repository import *
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/__init__.py:
--------------------------------------------------------------------------------
1 | from .adapters import *
2 | from .api import *
3 | from .consumers import *
4 | from .database import *
5 | from .mediators import *
6 | from .ports import *
7 | from.repository import *
--------------------------------------------------------------------------------
/chapter_9/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/requirements.Flask.txt:
--------------------------------------------------------------------------------
1 | click==8.0.3
2 | Flask==2.1.1
3 | importlib-metadata==4.8.1
4 | itsdangerous==2.0.1
5 | Jinja2==3.0.2
6 | MarkupSafe==2.0.1
7 | typing-extensions==3.10.0.2
8 | Werkzeug==2.0.1
9 | zipp==3.6.0
--------------------------------------------------------------------------------
/chapter_9/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/chapter_9/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/requirements.Flask.txt:
--------------------------------------------------------------------------------
1 | click==8.0.3
2 | Flask==2.1.1
3 | importlib-metadata==4.8.1
4 | itsdangerous==2.0.1
5 | Jinja2==3.0.2
6 | MarkupSafe==2.0.1
7 | typing-extensions==3.10.0.2
8 | Werkzeug==2.0.1
9 | zipp==3.6.0
--------------------------------------------------------------------------------
/chapter_9/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/chapter_4/itam/visitor/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the visitor module
2 |
3 | from .department_visitor import DepartmentVisitor, DepartmentStatisticsVisitor
4 |
5 | __all__ = [
6 | "DepartmentVisitor",
7 | "DepartmentStatisticsVisitor"
8 | ]
9 |
--------------------------------------------------------------------------------
/chapter_5/itam/visitor/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the visitor module
2 |
3 | from .department_visitor import DepartmentVisitor, DepartmentStatisticsVisitor
4 |
5 | __all__ = [
6 | "DepartmentVisitor",
7 | "DepartmentStatisticsVisitor"
8 | ]
9 |
--------------------------------------------------------------------------------
/chapter_6/itam/visitor/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the visitor module
2 |
3 | from .department_visitor import DepartmentVisitor, DepartmentStatisticsVisitor
4 |
5 | __all__ = [
6 | "DepartmentVisitor",
7 | "DepartmentStatisticsVisitor"
8 | ]
9 |
--------------------------------------------------------------------------------
/chapter_7/itam/visitor/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the visitor module
2 |
3 | from .department_visitor import DepartmentVisitor, DepartmentStatisticsVisitor
4 |
5 | __all__ = [
6 | "DepartmentVisitor",
7 | "DepartmentStatisticsVisitor"
8 | ]
9 |
--------------------------------------------------------------------------------
/chapter_4/itam/domain/department.py:
--------------------------------------------------------------------------------
1 | # define a class called Department, using Python's built-in dataclass decorator.
2 | # The Department entity has two attributes: id: int, name: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Department:
8 | id: int
9 | name: str
--------------------------------------------------------------------------------
/chapter_5/itam/domain/department.py:
--------------------------------------------------------------------------------
1 | # define a class called Department, using Python's built-in dataclass decorator.
2 | # The Department entity has two attributes: id: int, name: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Department:
8 | id: int
9 | name: str
--------------------------------------------------------------------------------
/chapter_5/requirements.txt:
--------------------------------------------------------------------------------
1 | # pip install uvicorn
2 | # pip install fastapi
3 |
4 | uvicorn==0.22.0
5 | fastapi==0.95.1
6 | psycopg2-binary==2.9.6
7 | SQLAlchemy==2.0.13
8 | pandas==2.0.1
9 | numpy==1.24.3
10 | kafka-python==2.0.2
11 | pyspark==3.4.0
12 | asyncio==3.4.3
13 | geopy==2.2.0
14 |
--------------------------------------------------------------------------------
/chapter_9/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/chapter_9/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/flask:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from flask.cli import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/flask:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from flask.cli import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/uvicorn:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from uvicorn.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/uvicorn:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from uvicorn.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/pip:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from pip._internal.cli.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/pip3:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from pip._internal.cli.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_5/itam/domain/events/asset_location_updated.py:
--------------------------------------------------------------------------------
1 | from datetime import date
2 |
3 | class AssetLocationUpdated:
4 | def __init__(self, asset_id: int, latitude: float, longitude: float, timestamp: date):
5 | self.asset_id = asset_id
6 | self.latitude = latitude
7 | self.longitude = longitude
8 | self.timestamp = timestamp
--------------------------------------------------------------------------------
/chapter_6/itam/domain/events/asset_location_updated.py:
--------------------------------------------------------------------------------
1 | from datetime import date
2 |
3 | class AssetLocationUpdated:
4 | def __init__(self, asset_id: int, latitude: float, longitude: float, timestamp: date):
5 | self.asset_id = asset_id
6 | self.latitude = latitude
7 | self.longitude = longitude
8 | self.timestamp = timestamp
--------------------------------------------------------------------------------
/chapter_6/requirements.txt:
--------------------------------------------------------------------------------
1 | # pip install uvicorn
2 | # pip install fastapi
3 |
4 | uvicorn==0.22.0
5 | fastapi==0.95.1
6 | psycopg2-binary==2.9.6
7 | SQLAlchemy==2.0.13
8 | pandas==2.0.1
9 | numpy==1.24.3
10 | kafka-python==2.0.2
11 | pyspark==3.4.0
12 | asyncio==3.4.3
13 | geopy==2.2.0
14 | httpx==0.19.0
15 | pytest==7.3.1
16 | behave==1.2.6
17 |
--------------------------------------------------------------------------------
/chapter_7/itam/domain/events/asset_location_updated.py:
--------------------------------------------------------------------------------
1 | from datetime import date
2 |
3 | class AssetLocationUpdated:
4 | def __init__(self, asset_id: int, latitude: float, longitude: float, timestamp: date):
5 | self.asset_id = asset_id
6 | self.latitude = latitude
7 | self.longitude = longitude
8 | self.timestamp = timestamp
--------------------------------------------------------------------------------
/chapter_7/requirements.txt:
--------------------------------------------------------------------------------
1 | # pip install uvicorn
2 | # pip install fastapi
3 |
4 | uvicorn==0.22.0
5 | fastapi==0.95.1
6 | psycopg2-binary==2.9.6
7 | SQLAlchemy==2.0.13
8 | pandas==2.0.1
9 | numpy==1.24.3
10 | kafka-python==2.0.2
11 | pyspark==3.4.0
12 | asyncio==3.4.3
13 | geopy==2.2.0
14 | httpx==0.19.0
15 | pytest==7.3.1
16 | behave==1.2.6
17 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/pip:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from pip._internal.cli.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/pip3:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from pip._internal.cli.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/pip3.10:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from pip._internal.cli.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/pip3.10:
--------------------------------------------------------------------------------
1 | #!/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env/bin/python3.10
2 | # -*- coding: utf-8 -*-
3 | import re
4 | import sys
5 | from pip._internal.cli.main import main
6 | if __name__ == '__main__':
7 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8 | sys.exit(main())
9 |
--------------------------------------------------------------------------------
/chapter_6/itam/domain/department.py:
--------------------------------------------------------------------------------
1 | # define a class called Department, using Python's built-in dataclass decorator.
2 | # The Department entity has two attributes: id: int, name: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Department:
8 | id: int
9 | name: str
10 |
11 | def __hash__(self):
12 | return hash(self.id)
--------------------------------------------------------------------------------
/chapter_7/itam/domain/department.py:
--------------------------------------------------------------------------------
1 | # define a class called Department, using Python's built-in dataclass decorator.
2 | # The Department entity has two attributes: id: int, name: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Department:
8 | id: int
9 | name: str
10 |
11 | def __hash__(self):
12 | return hash(self.id)
--------------------------------------------------------------------------------
/chapter_4/itam/domain/organization.py:
--------------------------------------------------------------------------------
1 | # define the Organization entity using Python's built-in dataclass decorator. The Organization entity has two attributes: id and name.
2 |
3 | from dataclasses import dataclass
4 |
5 | @dataclass
6 | class Organization:
7 | id: int
8 | name: str
9 |
10 | def __post_init__(self):
11 | if self.id is None:
12 | raise TypeError("Id cannot be None")
--------------------------------------------------------------------------------
/chapter_5/itam/domain/organization.py:
--------------------------------------------------------------------------------
1 | # define the Organization entity using Python's built-in dataclass decorator. The Organization entity has two attributes: id and name.
2 |
3 | from dataclasses import dataclass
4 |
5 | @dataclass
6 | class Organization:
7 | id: int
8 | name: str
9 |
10 | def __post_init__(self):
11 | if self.id is None:
12 | raise TypeError("Id cannot be None")
--------------------------------------------------------------------------------
/chapter_6/itam/domain/organization.py:
--------------------------------------------------------------------------------
1 | # define the Organization entity using Python's built-in dataclass decorator. The Organization entity has two attributes: id and name.
2 |
3 | from dataclasses import dataclass
4 |
5 | @dataclass
6 | class Organization:
7 | id: int
8 | name: str
9 |
10 | def __post_init__(self):
11 | if self.id is None:
12 | raise TypeError("Id cannot be None")
--------------------------------------------------------------------------------
/chapter_7/itam/domain/organization.py:
--------------------------------------------------------------------------------
1 | # define the Organization entity using Python's built-in dataclass decorator. The Organization entity has two attributes: id and name.
2 |
3 | from dataclasses import dataclass
4 |
5 | @dataclass
6 | class Organization:
7 | id: int
8 | name: str
9 |
10 | def __post_init__(self):
11 | if self.id is None:
12 | raise TypeError("Id cannot be None")
--------------------------------------------------------------------------------
/chapter_9/.idea/chapter_9.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/chapter_4/itam/domain/role.py:
--------------------------------------------------------------------------------
1 | # Create a class called Role.
2 | # The Role entity has the following attributes:
3 | # - id: int,
4 | # - name: str
5 | # none of the attributes can be None
6 |
7 | from dataclasses import dataclass
8 |
9 | @dataclass
10 | class Role:
11 | id: int
12 | name: str
13 |
14 | def __post_init__(self):
15 | if self.id is None:
16 | raise TypeError("Id cannot be None")
17 | if self.name is None:
18 | raise TypeError("Name cannot be None")
--------------------------------------------------------------------------------
/chapter_5/itam/domain/role.py:
--------------------------------------------------------------------------------
1 | # Create a class called Role.
2 | # The Role entity has the following attributes:
3 | # - id: int,
4 | # - name: str
5 | # none of the attributes can be None
6 |
7 | from dataclasses import dataclass
8 |
9 | @dataclass
10 | class Role:
11 | id: int
12 | name: str
13 |
14 | def __post_init__(self):
15 | if self.id is None:
16 | raise TypeError("Id cannot be None")
17 | if self.name is None:
18 | raise TypeError("Name cannot be None")
--------------------------------------------------------------------------------
/chapter_6/itam/domain/role.py:
--------------------------------------------------------------------------------
1 | # Create a class called Role.
2 | # The Role entity has the following attributes:
3 | # - id: int,
4 | # - name: str
5 | # none of the attributes can be None
6 |
7 | from dataclasses import dataclass
8 |
9 | @dataclass
10 | class Role:
11 | id: int
12 | name: str
13 |
14 | def __post_init__(self):
15 | if self.id is None:
16 | raise TypeError("Id cannot be None")
17 | if self.name is None:
18 | raise TypeError("Name cannot be None")
--------------------------------------------------------------------------------
/chapter_7/itam/domain/role.py:
--------------------------------------------------------------------------------
1 | # Create a class called Role.
2 | # The Role entity has the following attributes:
3 | # - id: int,
4 | # - name: str
5 | # none of the attributes can be None
6 |
7 | from dataclasses import dataclass
8 |
9 | @dataclass
10 | class Role:
11 | id: int
12 | name: str
13 |
14 | def __post_init__(self):
15 | if self.id is None:
16 | raise TypeError("Id cannot be None")
17 | if self.name is None:
18 | raise TypeError("Name cannot be None")
--------------------------------------------------------------------------------
/chapter_6/features/asset_manager.feature:
--------------------------------------------------------------------------------
1 | Feature: Asset Manager
2 | As an IT Asset Manager
3 | I want to be able to manage assets
4 | So that I can keep track of all IT assets in my organization
5 |
6 | Scenario: Add two assets to the Asset Manager
7 | Given the Asset Manager is running
8 | And the InMemoryAssetRepository is initialized
9 | And the AssetLocationMediator is mocked
10 | When I create an asset with a cost of $2000.00
11 | And I create another asset with a cost of $2000.00
12 | Then the total cost of all assets should be $4000.00
--------------------------------------------------------------------------------
/chapter_7/features/asset_manager.feature:
--------------------------------------------------------------------------------
1 | Feature: Asset Manager
2 | As an IT Asset Manager
3 | I want to be able to manage assets
4 | So that I can keep track of all IT assets in my organization
5 |
6 | Scenario: Add two assets to the Asset Manager
7 | Given the Asset Manager is running
8 | And the InMemoryAssetRepository is initialized
9 | And the AssetLocationMediator is mocked
10 | When I create an asset with a cost of $2000.00
11 | And I create another asset with a cost of $2000.00
12 | Then the total cost of all assets should be $4000.00
--------------------------------------------------------------------------------
/chapter_5/itam/domain/location.py:
--------------------------------------------------------------------------------
1 | # define the Location entity using Python's built-in dataclass decorator.
2 | # The Location entity has four attributes: id: int, name: str, address: Address, and organization: Organization which is optional.
3 |
4 | from dataclasses import dataclass
5 | from itam.domain.address import Address
6 | from itam.domain.organization import Organization
7 | from typing import Optional
8 | from datetime import date
9 |
10 | @dataclass
11 | class Location:
12 | asset_id: int
13 | latitude: float
14 | longitude: float
15 | timestamp: date
--------------------------------------------------------------------------------
/chapter_6/itam/domain/location.py:
--------------------------------------------------------------------------------
1 | # define the Location entity using Python's built-in dataclass decorator.
2 | # The Location entity has four attributes: id: int, name: str, address: Address, and organization: Organization which is optional.
3 |
4 | from dataclasses import dataclass
5 | from itam.domain.address import Address
6 | from itam.domain.organization import Organization
7 | from typing import Optional
8 | from datetime import date
9 |
10 | @dataclass
11 | class Location:
12 | asset_id: int
13 | latitude: float
14 | longitude: float
15 | timestamp: date
--------------------------------------------------------------------------------
/chapter_7/itam/domain/location.py:
--------------------------------------------------------------------------------
1 | # define the Location entity using Python's built-in dataclass decorator.
2 | # The Location entity has four attributes: id: int, name: str, address: Address, and organization: Organization which is optional.
3 |
4 | from dataclasses import dataclass
5 | from itam.domain.address import Address
6 | from itam.domain.organization import Organization
7 | from typing import Optional
8 | from datetime import date
9 |
10 | @dataclass
11 | class Location:
12 | asset_id: int
13 | latitude: float
14 | longitude: float
15 | timestamp: date
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/mediators/asset_location_mediator.py:
--------------------------------------------------------------------------------
1 |
2 | class AssetLocationMediator:
3 |
4 | def __init__(self):
5 | self.handlers = {}
6 |
7 | def register_handler(self, event_type, handler):
8 | if event_type not in self.handlers:
9 | self.handlers[event_type] = []
10 | self.handlers[event_type].append(handler)
11 |
12 | def publish(self, event):
13 | event_type = type(event)
14 | if event_type in self.handlers:
15 | for handler in self.handlers[event_type]:
16 | handler(event)
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/mediators/asset_location_mediator.py:
--------------------------------------------------------------------------------
1 |
2 | class AssetLocationMediator:
3 |
4 | def __init__(self):
5 | self.handlers = {}
6 |
7 | def register_handler(self, event_type, handler):
8 | if event_type not in self.handlers:
9 | self.handlers[event_type] = []
10 | self.handlers[event_type].append(handler)
11 |
12 | def publish(self, event):
13 | event_type = type(event)
14 | if event_type in self.handlers:
15 | for handler in self.handlers[event_type]:
16 | handler(event)
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/mediators/asset_location_mediator.py:
--------------------------------------------------------------------------------
1 |
2 | class AssetLocationMediator:
3 |
4 | def __init__(self):
5 | self.handlers = {}
6 |
7 | def register_handler(self, event_type, handler):
8 | if event_type not in self.handlers:
9 | self.handlers[event_type] = []
10 | self.handlers[event_type].append(handler)
11 |
12 | def publish(self, event):
13 | event_type = type(event)
14 | if event_type in self.handlers:
15 | for handler in self.handlers[event_type]:
16 | handler(event)
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/ports/asset_rest_port.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestPort
2 | # It should expose all of the methods in AssetManager as abtract methods
3 |
4 | from itam.domain.asset import Asset
5 | from abc import abstractmethod
6 |
7 | class AssetRestPort:
8 | @abstractmethod
9 | def read(self, asset_id: int) -> Asset:
10 | pass
11 |
12 | @abstractmethod
13 | def create(self, asset: Asset) -> None:
14 | pass
15 |
16 | @abstractmethod
17 | def update(self, asset: Asset) -> None:
18 | pass
19 |
20 | @abstractmethod
21 | def delete(self, asset_id: int) -> None:
22 | pass
23 |
24 | @abstractmethod
25 | def get_assets(self):
26 | pass
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/README.md:
--------------------------------------------------------------------------------
1 | # Chapter 2 Using ChatGPT
2 |
3 | To run:
4 |
5 | `pip install virtualenv`
6 |
7 | `python3 -m venv gpt-itam-env`
8 |
9 | `source gpt-itam-env/bin/activate`
10 |
11 | `pip install -r requirements.txt`
12 |
13 |
14 | curl -X POST "http://localhost:8000/assets/" -d "{'asset_id':'003', \
15 | 'asset_type': 'Server', \
16 | 'manufacturer': 'Dell', \
17 | 'model': 'PowerEdge R740', \
18 | 'purchase_date': '2021-03-01', \
19 | 'warranty_end_date': '2024-03-01', \
20 | 'location': 'London' \
21 | }"
22 |
23 | '003', , ', 'PowerEdge R740', '2021-03-01', , )
24 |
25 | curl -X PUT -H "Content-Type: application/json" -d '{"asset_id": "12345", "user": "John"}' http://localhost:8000/assets/12345/assign
26 |
--------------------------------------------------------------------------------
/chapter_4/itam/domain/address.py:
--------------------------------------------------------------------------------
1 | # Define the Address entity using Python's built-in dataclass decorator.
2 | # The Address entity has four attributes: street: str, city: str, state: str, and zip_code: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Address:
8 | street: str
9 | city: str
10 | state: str
11 | zip_code: str
12 |
13 | def __post_init__(self):
14 | if self.street is None:
15 | raise TypeError("Street cannot be None")
16 | if self.city is None:
17 | raise TypeError("City cannot be None")
18 | if self.state is None:
19 | raise TypeError("State cannot be None")
20 | if self.zip_code is None:
21 | raise TypeError("Zip Code cannot be None")
--------------------------------------------------------------------------------
/chapter_5/itam/domain/address.py:
--------------------------------------------------------------------------------
1 | # Define the Address entity using Python's built-in dataclass decorator.
2 | # The Address entity has four attributes: street: str, city: str, state: str, and zip_code: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Address:
8 | street: str
9 | city: str
10 | state: str
11 | zip_code: str
12 |
13 | def __post_init__(self):
14 | if self.street is None:
15 | raise TypeError("Street cannot be None")
16 | if self.city is None:
17 | raise TypeError("City cannot be None")
18 | if self.state is None:
19 | raise TypeError("State cannot be None")
20 | if self.zip_code is None:
21 | raise TypeError("Zip Code cannot be None")
--------------------------------------------------------------------------------
/chapter_6/itam/domain/address.py:
--------------------------------------------------------------------------------
1 | # Define the Address entity using Python's built-in dataclass decorator.
2 | # The Address entity has four attributes: street: str, city: str, state: str, and zip_code: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Address:
8 | street: str
9 | city: str
10 | state: str
11 | zip_code: str
12 |
13 | def __post_init__(self):
14 | if self.street is None:
15 | raise TypeError("Street cannot be None")
16 | if self.city is None:
17 | raise TypeError("City cannot be None")
18 | if self.state is None:
19 | raise TypeError("State cannot be None")
20 | if self.zip_code is None:
21 | raise TypeError("Zip Code cannot be None")
--------------------------------------------------------------------------------
/chapter_7/itam/domain/address.py:
--------------------------------------------------------------------------------
1 | # Define the Address entity using Python's built-in dataclass decorator.
2 | # The Address entity has four attributes: street: str, city: str, state: str, and zip_code: str.
3 |
4 | from dataclasses import dataclass
5 |
6 | @dataclass
7 | class Address:
8 | street: str
9 | city: str
10 | state: str
11 | zip_code: str
12 |
13 | def __post_init__(self):
14 | if self.street is None:
15 | raise TypeError("Street cannot be None")
16 | if self.city is None:
17 | raise TypeError("City cannot be None")
18 | if self.state is None:
19 | raise TypeError("State cannot be None")
20 | if self.zip_code is None:
21 | raise TypeError("Zip Code cannot be None")
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/ports/asset_rest_port.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestPort
2 | # It should expose all of the methods in AssetManager as abtract methods
3 |
4 | from itam.domain.asset import Asset
5 | from abc import abstractmethod
6 | from typing import List
7 |
8 | class AssetRestPort:
9 | @abstractmethod
10 | def read(self, asset_id: int) -> Asset:
11 | pass
12 |
13 | @abstractmethod
14 | def create(self, asset: Asset) -> None:
15 | pass
16 |
17 | @abstractmethod
18 | def update(self, asset: Asset) -> None:
19 | pass
20 |
21 | @abstractmethod
22 | def delete(self, asset_id: int) -> None:
23 | pass
24 |
25 | @abstractmethod
26 | def get_assets(self) -> List[Asset]:
27 | pass
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/ports/asset_rest_port.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestPort
2 | # It should expose all of the methods in AssetManager as abtract methods
3 |
4 | from itam.domain.asset import Asset
5 | from abc import abstractmethod
6 | from typing import List
7 |
8 | class AssetRestPort:
9 | @abstractmethod
10 | def read(self, asset_id: int) -> Asset:
11 | pass
12 |
13 | @abstractmethod
14 | def create(self, asset: Asset) -> None:
15 | pass
16 |
17 | @abstractmethod
18 | def update(self, asset: Asset) -> None:
19 | pass
20 |
21 | @abstractmethod
22 | def delete(self, asset_id: int) -> None:
23 | pass
24 |
25 | @abstractmethod
26 | def get_assets(self) -> List[Asset]:
27 | pass
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/ports/asset_rest_port.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestPort
2 | # It should expose all of the methods in AssetManager as abtract methods
3 |
4 | from itam.domain.asset import Asset
5 | from abc import abstractmethod
6 | from typing import List
7 |
8 | class AssetRestPort:
9 | @abstractmethod
10 | def read(self, asset_id: int) -> Asset:
11 | pass
12 |
13 | @abstractmethod
14 | def create(self, asset: Asset) -> None:
15 | pass
16 |
17 | @abstractmethod
18 | def update(self, asset: Asset) -> None:
19 | pass
20 |
21 | @abstractmethod
22 | def delete(self, asset_id: int) -> None:
23 | pass
24 |
25 | @abstractmethod
26 | def get_assets(self) -> List[Asset]:
27 | pass
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/README.md:
--------------------------------------------------------------------------------
1 | # Chapter 2 Using ChatGPT
2 |
3 | To run:
4 |
5 | `pip install virtualenv`
6 |
7 | `python3 -m venv gpt-itam-env`
8 |
9 | `source gpt-itam-env/bin/activate`
10 |
11 | `pip install -r requirements.txt`
12 |
13 | `uvicorn app:app --reload`
14 |
15 | curl -X POST "http://localhost:8000/assets/" -d "{'asset_id':'003', \
16 | 'asset_type': 'Server', \
17 | 'manufacturer': 'Dell', \
18 | 'model': 'PowerEdge R740', \
19 | 'purchase_date': '2021-03-01', \
20 | 'warranty_end_date': '2024-03-01', \
21 | 'location': 'London' \
22 | }"
23 |
24 | '003', , ', 'PowerEdge R740', '2021-03-01', , )
25 |
26 | curl -X PUT -H "Content-Type: application/json" -d '{"asset_id": "12345", "user": "John"}' http://localhost:8000/assets/12345/assign
27 |
--------------------------------------------------------------------------------
/chapter_4/itam/domain/snowflake_identifier.py:
--------------------------------------------------------------------------------
1 | # Define a class called SnowflakeIdentifier
2 | # It should generate an identifier using the snowflake algorithm
3 | # Combine the current time in milliseconds since the epoch time (January 1, 2021 in this case) with the machine ID and sequence number to create the ID.
4 | # The ID should be a 64-bit integer
5 |
6 | import time
7 | import uuid
8 |
9 | class SnowflakeIdentifier:
10 | def __init__(self):
11 | self._machine_id = uuid.getnode()
12 | self._sequence_number = 0
13 | self._last_timestamp = 0
14 |
15 | def get_id(self):
16 | timestamp = int(time.time() * 1000)
17 | if timestamp == self._last_timestamp:
18 | self._sequence_number += 1
19 | else:
20 | self._sequence_number = 0
21 | self._last_timestamp = timestamp
22 | return (timestamp << 22) + (self._machine_id << 10) + self._sequence_number
--------------------------------------------------------------------------------
/chapter_5/itam/domain/snowflake_identifier.py:
--------------------------------------------------------------------------------
1 | # Define a class called SnowflakeIdentifier
2 | # It should generate an identifier using the snowflake algorithm
3 | # Combine the current time in milliseconds since the epoch time (January 1, 2021 in this case) with the machine ID and sequence number to create the ID.
4 | # The ID should be a 64-bit integer
5 |
6 | import time
7 | import uuid
8 |
9 | class SnowflakeIdentifier:
10 | def __init__(self):
11 | self._machine_id = uuid.getnode()
12 | self._sequence_number = 0
13 | self._last_timestamp = 0
14 |
15 | def get_id(self):
16 | timestamp = int(time.time() * 1000)
17 | if timestamp == self._last_timestamp:
18 | self._sequence_number += 1
19 | else:
20 | self._sequence_number = 0
21 | self._last_timestamp = timestamp
22 | return (timestamp << 22) + (self._machine_id << 10) + self._sequence_number
--------------------------------------------------------------------------------
/chapter_6/itam/domain/snowflake_identifier.py:
--------------------------------------------------------------------------------
1 | # Define a class called SnowflakeIdentifier
2 | # It should generate an identifier using the snowflake algorithm
3 | # Combine the current time in milliseconds since the epoch time (January 1, 2021 in this case) with the machine ID and sequence number to create the ID.
4 | # The ID should be a 64-bit integer
5 |
6 | import time
7 | import uuid
8 |
9 | class SnowflakeIdentifier:
10 | def __init__(self):
11 | self._machine_id = uuid.getnode()
12 | self._sequence_number = 0
13 | self._last_timestamp = 0
14 |
15 | def get_id(self):
16 | timestamp = int(time.time() * 1000)
17 | if timestamp == self._last_timestamp:
18 | self._sequence_number += 1
19 | else:
20 | self._sequence_number = 0
21 | self._last_timestamp = timestamp
22 | return (timestamp << 22) + (self._machine_id << 10) + self._sequence_number
--------------------------------------------------------------------------------
/chapter_7/itam/domain/snowflake_identifier.py:
--------------------------------------------------------------------------------
1 | # Define a class called SnowflakeIdentifier
2 | # It should generate an identifier using the snowflake algorithm
3 | # Combine the current time in milliseconds since the epoch time (January 1, 2021 in this case) with the machine ID and sequence number to create the ID.
4 | # The ID should be a 64-bit integer
5 |
6 | import time
7 | import uuid
8 |
9 | class SnowflakeIdentifier:
10 | def __init__(self):
11 | self._machine_id = uuid.getnode()
12 | self._sequence_number = 0
13 | self._last_timestamp = 0
14 |
15 | def get_id(self):
16 | timestamp = int(time.time() * 1000)
17 | if timestamp == self._last_timestamp:
18 | self._sequence_number += 1
19 | else:
20 | self._sequence_number = 0
21 | self._last_timestamp = timestamp
22 | return (timestamp << 22) + (self._machine_id << 10) + self._sequence_number
--------------------------------------------------------------------------------
/chapter_4/itam/domain/budget.py:
--------------------------------------------------------------------------------
1 | # create a class called Budget
2 | # with the following attributes:
3 | # - id: int, name: str, department_id: int, amount: float, start_date: datetime, end_date: datetime
4 | # id cannot be nil
5 | # deparment cannot be nil
6 | # amount cannot be nil
7 | # automatically generates special methods for a class that are commonly used for data objects
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class Budget:
14 | id: int
15 | name: str
16 | department_id: int
17 | amount: float
18 | start_date: datetime
19 | end_date: datetime
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.department_id is None:
25 | raise TypeError("Department cannot be None")
26 | if self.amount is None:
27 | raise TypeError("Amount cannot be None")
--------------------------------------------------------------------------------
/chapter_5/itam/domain/budget.py:
--------------------------------------------------------------------------------
1 | # create a class called Budget
2 | # with the following attributes:
3 | # - id: int, name: str, department_id: int, amount: float, start_date: datetime, end_date: datetime
4 | # id cannot be nil
5 | # deparment cannot be nil
6 | # amount cannot be nil
7 | # automatically generates special methods for a class that are commonly used for data objects
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class Budget:
14 | id: int
15 | name: str
16 | department_id: int
17 | amount: float
18 | start_date: datetime
19 | end_date: datetime
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.department_id is None:
25 | raise TypeError("Department cannot be None")
26 | if self.amount is None:
27 | raise TypeError("Amount cannot be None")
--------------------------------------------------------------------------------
/chapter_6/itam/domain/budget.py:
--------------------------------------------------------------------------------
1 | # create a class called Budget
2 | # with the following attributes:
3 | # - id: int, name: str, department_id: int, amount: float, start_date: datetime, end_date: datetime
4 | # id cannot be nil
5 | # deparment cannot be nil
6 | # amount cannot be nil
7 | # automatically generates special methods for a class that are commonly used for data objects
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class Budget:
14 | id: int
15 | name: str
16 | department_id: int
17 | amount: float
18 | start_date: datetime
19 | end_date: datetime
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.department_id is None:
25 | raise TypeError("Department cannot be None")
26 | if self.amount is None:
27 | raise TypeError("Amount cannot be None")
--------------------------------------------------------------------------------
/chapter_7/itam/domain/budget.py:
--------------------------------------------------------------------------------
1 | # create a class called Budget
2 | # with the following attributes:
3 | # - id: int, name: str, department_id: int, amount: float, start_date: datetime, end_date: datetime
4 | # id cannot be nil
5 | # deparment cannot be nil
6 | # amount cannot be nil
7 | # automatically generates special methods for a class that are commonly used for data objects
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class Budget:
14 | id: int
15 | name: str
16 | department_id: int
17 | amount: float
18 | start_date: datetime
19 | end_date: datetime
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.department_id is None:
25 | raise TypeError("Department cannot be None")
26 | if self.amount is None:
27 | raise TypeError("Amount cannot be None")
--------------------------------------------------------------------------------
/chapter_4/itam/domain/location.py:
--------------------------------------------------------------------------------
1 | # define the Location entity using Python's built-in dataclass decorator.
2 | # The Location entity has four attributes: id: int, name: str, address: Address, and organization: Organization which is optional.
3 |
4 | from dataclasses import dataclass
5 | from itam.domain.address import Address
6 | from itam.domain.organization import Organization
7 | from typing import Optional
8 |
9 | @dataclass
10 | class Location:
11 | id: int
12 | name: str
13 | address: Address
14 | organization: Optional[Organization]
15 |
16 | def __post_init__(self):
17 | if self.id is None:
18 | raise TypeError("Id cannot be None")
19 | if self.name is None:
20 | raise TypeError("Name cannot be None")
21 | if self.address is None:
22 | raise TypeError("Address cannot be None")
23 | if self.organization is None:
24 | raise TypeError("Organization cannot be None")
--------------------------------------------------------------------------------
/chapter_5/data/scripts/load.sql:
--------------------------------------------------------------------------------
1 | # write the postgres command to load data into the database from a csv
2 | # file named assets.csv in the data directory
3 | # the file should have a header row and the columns should have the data types
4 | # id (int), name (varchar), status (varchar), category (varchar), cost (float), useful_life (float), salvage_value (float), funding_details (varchar), depreciation_strategy (varchar)
5 | # the file should be loaded into a table named assets
6 | # the table should be created if it does not exist
7 | # the table should be truncated before loading the data
8 |
9 | create table if not exists assets (
10 | id int,
11 | name varchar,
12 | status varchar,
13 | category varchar,
14 | cost float,
15 | useful_life float,
16 | salvage_value float,
17 | funding_details varchar,
18 | depreciation_strategy varchar
19 | );
20 |
21 | psql -d postgres -c "copy assets from '/data/assets.csv' delimiter ',' csv header;"
--------------------------------------------------------------------------------
/chapter_6/data/scripts/load.sql:
--------------------------------------------------------------------------------
1 | # write the postgres command to load data into the database from a csv
2 | # file named assets.csv in the data directory
3 | # the file should have a header row and the columns should have the data types
4 | # id (int), name (varchar), status (varchar), category (varchar), cost (float), useful_life (float), salvage_value (float), funding_details (varchar), depreciation_strategy (varchar)
5 | # the file should be loaded into a table named assets
6 | # the table should be created if it does not exist
7 | # the table should be truncated before loading the data
8 |
9 | create table if not exists assets (
10 | id int,
11 | name varchar,
12 | status varchar,
13 | category varchar,
14 | cost float,
15 | useful_life float,
16 | salvage_value float,
17 | funding_details varchar,
18 | depreciation_strategy varchar
19 | );
20 |
21 | psql -d postgres -c "copy assets from '/data/assets.csv' delimiter ',' csv header;"
--------------------------------------------------------------------------------
/chapter_7/data/scripts/load.sql:
--------------------------------------------------------------------------------
1 | # write the postgres command to load data into the database from a csv
2 | # file named assets.csv in the data directory
3 | # the file should have a header row and the columns should have the data types
4 | # id (int), name (varchar), status (varchar), category (varchar), cost (float), useful_life (float), salvage_value (float), funding_details (varchar), depreciation_strategy (varchar)
5 | # the file should be loaded into a table named assets
6 | # the table should be created if it does not exist
7 | # the table should be truncated before loading the data
8 |
9 | create table if not exists assets (
10 | id int,
11 | name varchar,
12 | status varchar,
13 | category varchar,
14 | cost float,
15 | useful_life float,
16 | salvage_value float,
17 | funding_details varchar,
18 | depreciation_strategy varchar
19 | );
20 |
21 | psql -d postgres -c "copy assets from '/data/assets.csv' delimiter ',' csv header;"
--------------------------------------------------------------------------------
/chapter_4/itam/domain/warranty.py:
--------------------------------------------------------------------------------
1 | # Define the Warranty entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date
7 |
8 | from datetime import datetime
9 | from dataclasses import dataclass
10 |
11 |
12 | @dataclass
13 | class Warranty:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.name is None:
25 | raise TypeError("Name cannot be None")
26 | if self.description is None:
27 | raise TypeError("Description cannot be None")
28 | if self.start_date is None:
29 | raise TypeError("Start date cannot be None")
30 | if self.end_date is None:
31 | raise TypeError("End date cannot be None")
32 |
--------------------------------------------------------------------------------
/chapter_5/itam/domain/warranty.py:
--------------------------------------------------------------------------------
1 | # Define the Warranty entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date
7 |
8 | from datetime import datetime
9 | from dataclasses import dataclass
10 |
11 |
12 | @dataclass
13 | class Warranty:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.name is None:
25 | raise TypeError("Name cannot be None")
26 | if self.description is None:
27 | raise TypeError("Description cannot be None")
28 | if self.start_date is None:
29 | raise TypeError("Start date cannot be None")
30 | if self.end_date is None:
31 | raise TypeError("End date cannot be None")
32 |
--------------------------------------------------------------------------------
/chapter_6/itam/domain/warranty.py:
--------------------------------------------------------------------------------
1 | # Define the Warranty entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date
7 |
8 | from datetime import datetime
9 | from dataclasses import dataclass
10 |
11 |
12 | @dataclass
13 | class Warranty:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.name is None:
25 | raise TypeError("Name cannot be None")
26 | if self.description is None:
27 | raise TypeError("Description cannot be None")
28 | if self.start_date is None:
29 | raise TypeError("Start date cannot be None")
30 | if self.end_date is None:
31 | raise TypeError("End date cannot be None")
32 |
--------------------------------------------------------------------------------
/chapter_7/itam/domain/warranty.py:
--------------------------------------------------------------------------------
1 | # Define the Warranty entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date
7 |
8 | from datetime import datetime
9 | from dataclasses import dataclass
10 |
11 |
12 | @dataclass
13 | class Warranty:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 |
21 | def __post_init__(self):
22 | if self.id is None:
23 | raise TypeError("Id cannot be None")
24 | if self.name is None:
25 | raise TypeError("Name cannot be None")
26 | if self.description is None:
27 | raise TypeError("Description cannot be None")
28 | if self.start_date is None:
29 | raise TypeError("Start date cannot be None")
30 | if self.end_date is None:
31 | raise TypeError("End date cannot be None")
32 |
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/repository/base_repository.py:
--------------------------------------------------------------------------------
1 | # Create an abstract base class called BaseRepository that represents a generic data access layer using the Repository pattern.
2 | # The class should define common methods for CRUD operations such as create, read, update, and delete.
3 | # Make sure to use type hints for the input parameters and return values.
4 |
5 | from abc import ABC, abstractmethod
6 | from typing import List, TypeVar, Generic
7 |
8 | T = TypeVar('T')
9 |
10 | class BaseRepository(ABC, Generic[T]):
11 | @abstractmethod
12 | def create(self, entity: T) -> None:
13 | pass
14 |
15 | @abstractmethod
16 | def read(self, entity_id: int) -> T:
17 | pass
18 |
19 | @abstractmethod
20 | def update(self, entity: T) -> None:
21 | pass
22 |
23 | @abstractmethod
24 | def delete(self, entity_id: int) -> None:
25 | pass
26 |
27 | @abstractmethod
28 | def get_entities(self) -> List[T]:
29 | pass
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/repository/base_repository.py:
--------------------------------------------------------------------------------
1 | # Create an abstract base class called BaseRepository that represents a generic data access layer using the Repository pattern.
2 | # The class should define common methods for CRUD operations such as create, read, update, and delete.
3 | # Make sure to use type hints for the input parameters and return values.
4 |
5 | from abc import ABC, abstractmethod
6 | from typing import List, TypeVar, Generic
7 |
8 | T = TypeVar('T')
9 |
10 | class BaseRepository(ABC, Generic[T]):
11 | @abstractmethod
12 | def create(self, entity: T) -> None:
13 | pass
14 |
15 | @abstractmethod
16 | def read(self, entity_id: int) -> T:
17 | pass
18 |
19 | @abstractmethod
20 | def update(self, entity: T) -> None:
21 | pass
22 |
23 | @abstractmethod
24 | def delete(self, entity_id: int) -> None:
25 | pass
26 |
27 | @abstractmethod
28 | def get_entities(self) -> List[T]:
29 | pass
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/repository/base_repository.py:
--------------------------------------------------------------------------------
1 | # Create an abstract base class called BaseRepository that represents a generic data access layer using the Repository pattern.
2 | # The class should define common methods for CRUD operations such as create, read, update, and delete.
3 | # Make sure to use type hints for the input parameters and return values.
4 |
5 | from abc import ABC, abstractmethod
6 | from typing import List, TypeVar, Generic
7 |
8 | T = TypeVar('T')
9 |
10 | class BaseRepository(ABC, Generic[T]):
11 | @abstractmethod
12 | def create(self, entity: T) -> None:
13 | pass
14 |
15 | @abstractmethod
16 | def read(self, entity_id: int) -> T:
17 | pass
18 |
19 | @abstractmethod
20 | def update(self, entity: T) -> None:
21 | pass
22 |
23 | @abstractmethod
24 | def delete(self, entity_id: int) -> None:
25 | pass
26 |
27 | @abstractmethod
28 | def get_entities(self) -> List[T]:
29 | pass
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/repository/base_repository.py:
--------------------------------------------------------------------------------
1 | # Create an abstract base class called BaseRepository that represents a generic data access layer using the Repository pattern.
2 | # The class should define common methods for CRUD operations such as create, read, update, and delete.
3 | # Make sure to use type hints for the input parameters and return values.
4 |
5 | from abc import ABC, abstractmethod
6 | from typing import List, TypeVar, Generic
7 |
8 | T = TypeVar('T')
9 |
10 | class BaseRepository(ABC, Generic[T]):
11 | @abstractmethod
12 | def create(self, entity: T) -> None:
13 | pass
14 |
15 | @abstractmethod
16 | def read(self, entity_id: int) -> T:
17 | pass
18 |
19 | @abstractmethod
20 | def update(self, entity: T) -> None:
21 | pass
22 |
23 | @abstractmethod
24 | def delete(self, entity_id: int) -> None:
25 | pass
26 |
27 | @abstractmethod
28 | def get_entities(self) -> List[T]:
29 | pass
--------------------------------------------------------------------------------
/chapter_4/itam/domain/maintenance_schedule.py:
--------------------------------------------------------------------------------
1 | # Define the MaintenanceSchedule entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date,
7 | # - hardware : Hardware
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class MaintenanceSchedule:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 | def __post_init__(self):
21 | if self.id is None:
22 | raise TypeError("Id cannot be None")
23 | if self.name is None:
24 | raise TypeError("Name cannot be None")
25 | if self.description is None:
26 | raise TypeError("Description cannot be None")
27 | if self.start_date is None:
28 | raise TypeError("Start date cannot be None")
29 | if self.end_date is None:
30 | raise TypeError("End date cannot be None")
--------------------------------------------------------------------------------
/chapter_5/itam/domain/maintenance_schedule.py:
--------------------------------------------------------------------------------
1 | # Define the MaintenanceSchedule entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date,
7 | # - hardware : Hardware
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class MaintenanceSchedule:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 | def __post_init__(self):
21 | if self.id is None:
22 | raise TypeError("Id cannot be None")
23 | if self.name is None:
24 | raise TypeError("Name cannot be None")
25 | if self.description is None:
26 | raise TypeError("Description cannot be None")
27 | if self.start_date is None:
28 | raise TypeError("Start date cannot be None")
29 | if self.end_date is None:
30 | raise TypeError("End date cannot be None")
--------------------------------------------------------------------------------
/chapter_6/itam/domain/maintenance_schedule.py:
--------------------------------------------------------------------------------
1 | # Define the MaintenanceSchedule entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date,
7 | # - hardware : Hardware
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class MaintenanceSchedule:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 | def __post_init__(self):
21 | if self.id is None:
22 | raise TypeError("Id cannot be None")
23 | if self.name is None:
24 | raise TypeError("Name cannot be None")
25 | if self.description is None:
26 | raise TypeError("Description cannot be None")
27 | if self.start_date is None:
28 | raise TypeError("Start date cannot be None")
29 | if self.end_date is None:
30 | raise TypeError("End date cannot be None")
--------------------------------------------------------------------------------
/chapter_7/itam/domain/maintenance_schedule.py:
--------------------------------------------------------------------------------
1 | # Define the MaintenanceSchedule entity. It should have the following attributes:
2 | # - id: int,
3 | # - name: str,
4 | # - description: str,
5 | # - start_date: date,
6 | # - end_date: date,
7 | # - hardware : Hardware
8 |
9 | from datetime import datetime
10 | from dataclasses import dataclass
11 |
12 | @dataclass
13 | class MaintenanceSchedule:
14 | id: int
15 | name: str
16 | description: str
17 | start_date: datetime
18 | end_date: datetime
19 |
20 | def __post_init__(self):
21 | if self.id is None:
22 | raise TypeError("Id cannot be None")
23 | if self.name is None:
24 | raise TypeError("Name cannot be None")
25 | if self.description is None:
26 | raise TypeError("Description cannot be None")
27 | if self.start_date is None:
28 | raise TypeError("Start date cannot be None")
29 | if self.end_date is None:
30 | raise TypeError("End date cannot be None")
--------------------------------------------------------------------------------
/chapter_2/copilot/asset_manager.py:
--------------------------------------------------------------------------------
1 | # Create a class called AssetManager that will allow us to store and retrieve assets.
2 |
3 | class AssetManager:
4 | def __init__(self):
5 | self.assets = []
6 |
7 | def add_asset(self, asset):
8 | self.assets.append(asset)
9 |
10 | def get_assets(self):
11 | return self.assets
12 |
13 | def get_asset(self, asset_id):
14 | for asset in self.assets:
15 | if asset.id == asset_id:
16 | return asset
17 | return None
18 |
19 | def update_asset(self, asset_id, asset):
20 | for index, asset in enumerate(self.assets):
21 | if asset.id == asset_id:
22 | self.assets[index] = asset
23 | return True
24 | return False
25 |
26 | def delete_asset(self, asset_id):
27 | for index, asset in enumerate(self.assets):
28 | if asset.id == asset_id:
29 | del self.assets[index]
30 | return True
31 | return False
--------------------------------------------------------------------------------
/chapter_4/itam/domain/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the domain module
2 |
3 | from .asset import Asset
4 | from .budget import Budget
5 | from .depreciation_strategy import DepreciationStrategy, StraightLineDepreciationStrategy, DecliningBalanceDepreciationStrategy, DoubleDecliningDepreciationStrategy, NoDepreciationStrategy
6 | from .funding_details import FundingDetails
7 | from .hardware import Hardware
8 | from .location import Location, Address
9 | from .organization import Organization
10 | from .software import Software
11 | from .user import User
12 | from .role import Role
13 |
14 | __all__ = [
15 | "Asset",
16 | "Budget",
17 | "Software",
18 | "Hardware",
19 | "Department",
20 | "Organization",
21 | "Location",
22 | "Address",
23 | "DepreciationStrategy",
24 | "DecliningBalanceDepreciationStrategy",
25 | "StraightLineDepreciationStrategy",
26 | "DoubleDecliningDepreciationStrategy",
27 | "NoDepreciationStrategy",
28 | "Organization",
29 | "User",
30 | "Role",
31 | "FundingDetails"
32 | ]
33 |
--------------------------------------------------------------------------------
/chapter_5/itam/domain/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the domain module
2 |
3 | from .asset import Asset
4 | from .budget import Budget
5 | from .depreciation_strategy import DepreciationStrategy, StraightLineDepreciationStrategy, DecliningBalanceDepreciationStrategy, DoubleDecliningDepreciationStrategy, NoDepreciationStrategy
6 | from .funding_details import FundingDetails
7 | from .hardware import Hardware
8 | from .location import Location, Address
9 | from .organization import Organization
10 | from .software import Software
11 | from .user import User
12 | from .role import Role
13 |
14 | __all__ = [
15 | "Asset",
16 | "Budget",
17 | "Software",
18 | "Hardware",
19 | "Department",
20 | "Organization",
21 | "Location",
22 | "Address",
23 | "DepreciationStrategy",
24 | "DecliningBalanceDepreciationStrategy",
25 | "StraightLineDepreciationStrategy",
26 | "DoubleDecliningDepreciationStrategy",
27 | "NoDepreciationStrategy",
28 | "Organization",
29 | "User",
30 | "Role",
31 | "FundingDetails"
32 | ]
33 |
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/adapters/asset_rest_adapter.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestAdapter
2 | # It should take an AssetManager as a parameter in its constructor
3 | # It should expose all of the methods in AssetManager
4 | # It should inherit from AssetRestPort
5 |
6 | from itam.domain.asset import Asset
7 | from itam.infrastructure.ports.asset_rest_port import AssetRestPort
8 | from itam.service.asset_manager import AssetManager
9 |
10 | class AssetRestAdapter(AssetRestPort):
11 | def __init__(self, asset_manager: AssetManager):
12 | self._asset_manager = asset_manager
13 |
14 | def read(self, asset_id: int) -> Asset:
15 | return self._asset_manager.read(asset_id)
16 |
17 | def create(self, asset: Asset) -> None:
18 | self._asset_manager.create(asset)
19 |
20 | def update(self, asset: Asset) -> None:
21 | self._asset_manager.update(asset)
22 |
23 | def delete(self, asset_id: int) -> None:
24 | self._asset_manager.delete(asset_id)
25 |
26 | def get_assets(self):
27 | return self._asset_manager.get_assets()
28 |
--------------------------------------------------------------------------------
/chapter_6/itam/domain/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the domain module
2 |
3 | from .asset import Asset
4 | from .budget import Budget
5 | from .department import Department
6 | from .depreciation_strategy import DepreciationStrategy, StraightLineDepreciationStrategy, DecliningBalanceDepreciationStrategy, DoubleDecliningDepreciationStrategy, NoDepreciationStrategy
7 | from .funding_details import FundingDetails
8 | from .hardware import Hardware
9 | from .location import Location, Address
10 | from .organization import Organization
11 | from .software import Software
12 | from .user import User
13 | from .role import Role
14 |
15 | __all__ = [
16 | "Asset",
17 | "Budget",
18 | "Software",
19 | "Hardware",
20 | "Department",
21 | "Organization",
22 | "Location",
23 | "Address",
24 | "DepreciationStrategy",
25 | "DecliningBalanceDepreciationStrategy",
26 | "StraightLineDepreciationStrategy",
27 | "DoubleDecliningDepreciationStrategy",
28 | "NoDepreciationStrategy",
29 | "Organization",
30 | "User",
31 | "Role",
32 | "FundingDetails"
33 | ]
34 |
--------------------------------------------------------------------------------
/chapter_7/itam/domain/__init__.py:
--------------------------------------------------------------------------------
1 | # import all of the classes from the domain module
2 |
3 | from .asset import Asset
4 | from .budget import Budget
5 | from .department import Department
6 | from .depreciation_strategy import DepreciationStrategy, StraightLineDepreciationStrategy, DecliningBalanceDepreciationStrategy, DoubleDecliningDepreciationStrategy, NoDepreciationStrategy
7 | from .funding_details import FundingDetails
8 | from .hardware import Hardware
9 | from .location import Location, Address
10 | from .organization import Organization
11 | from .software import Software
12 | from .user import User
13 | from .role import Role
14 |
15 | __all__ = [
16 | "Asset",
17 | "Budget",
18 | "Software",
19 | "Hardware",
20 | "Department",
21 | "Organization",
22 | "Location",
23 | "Address",
24 | "DepreciationStrategy",
25 | "DecliningBalanceDepreciationStrategy",
26 | "StraightLineDepreciationStrategy",
27 | "DoubleDecliningDepreciationStrategy",
28 | "NoDepreciationStrategy",
29 | "Organization",
30 | "User",
31 | "Role",
32 | "FundingDetails"
33 | ]
34 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/gpt-itam-env/bin/activate.csh:
--------------------------------------------------------------------------------
1 | # This file must be used with "source bin/activate.csh" *from csh*.
2 | # You cannot run it directly.
3 | # Created by Davide Di Blasi .
4 | # Ported to Python 3.3 venv by Andrew Svetlov
5 |
6 | alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
7 |
8 | # Unset irrelevant variables.
9 | deactivate nondestructive
10 |
11 | setenv VIRTUAL_ENV "/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env"
12 |
13 | set _OLD_VIRTUAL_PATH="$PATH"
14 | setenv PATH "$VIRTUAL_ENV/bin:$PATH"
15 |
16 |
17 | set _OLD_VIRTUAL_PROMPT="$prompt"
18 |
19 | if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
20 | set prompt = "(gpt-itam-env) $prompt"
21 | setenv VIRTUAL_ENV_PROMPT "(gpt-itam-env) "
22 | endif
23 |
24 | alias pydoc python -m pydoc
25 |
26 | rehash
27 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/gpt-itam-env/bin/activate.csh:
--------------------------------------------------------------------------------
1 | # This file must be used with "source bin/activate.csh" *from csh*.
2 | # You cannot run it directly.
3 | # Created by Davide Di Blasi .
4 | # Ported to Python 3.3 venv by Andrew Svetlov
5 |
6 | alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
7 |
8 | # Unset irrelevant variables.
9 | deactivate nondestructive
10 |
11 | setenv VIRTUAL_ENV "/Users/nbcrocker/Desktop/ai_guided_dev/chpt02/chatgpt/gpt-itam-env"
12 |
13 | set _OLD_VIRTUAL_PATH="$PATH"
14 | setenv PATH "$VIRTUAL_ENV/bin:$PATH"
15 |
16 |
17 | set _OLD_VIRTUAL_PROMPT="$prompt"
18 |
19 | if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
20 | set prompt = "(gpt-itam-env) $prompt"
21 | setenv VIRTUAL_ENV_PROMPT "(gpt-itam-env) "
22 | endif
23 |
24 | alias pydoc python -m pydoc
25 |
26 | rehash
27 |
--------------------------------------------------------------------------------
/chapter_4/itam/domain/funding_details.py:
--------------------------------------------------------------------------------
1 | # Define a class called FundingDetails
2 | # It should have the following attributes:
3 | # - depreciation_strategy: DepreciationStrategy,
4 | # - depreciation_rate: float
5 | # - department_allocations: Dict[Department, float]
6 | # The attributes cannot be None and cannot be modified after construction
7 | # However, we should be able to access the attributes using methods
8 |
9 | from dataclasses import dataclass
10 | from itam.domain.depreciation_strategy import DepreciationStrategy
11 | from itam.domain.asset import Asset
12 | from itam.domain.department import Department
13 | from typing import Dict
14 |
15 | @dataclass
16 | class FundingDetails:
17 | asset: Asset
18 | depreciation_strategy: DepreciationStrategy
19 | depreciation_rate: float
20 | department_allocations: Dict[Department, float]
21 |
22 | def get_depreciation_strategy(self):
23 | return self.depreciation_strategy
24 |
25 | def get_depreciation_rate(self):
26 | return self.depreciation_rate
27 |
28 | def get_department_allocations(self):
29 | return self.department_allocations
--------------------------------------------------------------------------------
/chapter_5/itam/domain/funding_details.py:
--------------------------------------------------------------------------------
1 | # Define a class called FundingDetails
2 | # It should have the following attributes:
3 | # - depreciation_strategy: DepreciationStrategy,
4 | # - depreciation_rate: float
5 | # - department_allocations: Dict[Department, float]
6 | # The attributes cannot be None and cannot be modified after construction
7 | # However, we should be able to access the attributes using methods
8 |
9 | from dataclasses import dataclass
10 | from itam.domain.depreciation_strategy import DepreciationStrategy
11 | from itam.domain.asset import Asset
12 | from itam.domain.department import Department
13 | from typing import Dict
14 |
15 | @dataclass
16 | class FundingDetails:
17 | asset: Asset
18 | depreciation_strategy: DepreciationStrategy
19 | depreciation_rate: float
20 | department_allocations: Dict[Department, float]
21 |
22 | def get_depreciation_strategy(self):
23 | return self.depreciation_strategy
24 |
25 | def get_depreciation_rate(self):
26 | return self.depreciation_rate
27 |
28 | def get_department_allocations(self):
29 | return self.department_allocations
--------------------------------------------------------------------------------
/chapter_4/itam/domain/user.py:
--------------------------------------------------------------------------------
1 | # Create a class called User.
2 | # The User entity has the following attributes:
3 | # - username: str,
4 | # - password: str,
5 | # - roles: List[Role]
6 | # none of the attributes can be None
7 | # The User entity should have two methods: has_role() and has_role_by_name().
8 |
9 | from dataclasses import dataclass
10 | from typing import List
11 | from itam.domain.role import Role
12 |
13 | @dataclass
14 | class User:
15 | username: str
16 | password: str
17 | roles: List[Role]
18 |
19 | def __post_init__(self):
20 | if self.username is None:
21 | raise TypeError("Username cannot be None")
22 | if self.password is None:
23 | raise TypeError("Password cannot be None")
24 | if self.roles is None:
25 | raise TypeError("Roles cannot be None")
26 |
27 | def has_role(self, role: Role) -> bool:
28 | return role in self.roles
29 |
30 | def has_role_by_name(self, role_name: str) -> bool:
31 | for role in self.roles:
32 | if role.name == role_name:
33 | return True
34 | return False
--------------------------------------------------------------------------------
/chapter_5/itam/domain/user.py:
--------------------------------------------------------------------------------
1 | # Create a class called User.
2 | # The User entity has the following attributes:
3 | # - username: str,
4 | # - password: str,
5 | # - roles: List[Role]
6 | # none of the attributes can be None
7 | # The User entity should have two methods: has_role() and has_role_by_name().
8 |
9 | from dataclasses import dataclass
10 | from typing import List
11 | from itam.domain.role import Role
12 |
13 | @dataclass
14 | class User:
15 | username: str
16 | password: str
17 | roles: List[Role]
18 |
19 | def __post_init__(self):
20 | if self.username is None:
21 | raise TypeError("Username cannot be None")
22 | if self.password is None:
23 | raise TypeError("Password cannot be None")
24 | if self.roles is None:
25 | raise TypeError("Roles cannot be None")
26 |
27 | def has_role(self, role: Role) -> bool:
28 | return role in self.roles
29 |
30 | def has_role_by_name(self, role_name: str) -> bool:
31 | for role in self.roles:
32 | if role.name == role_name:
33 | return True
34 | return False
--------------------------------------------------------------------------------
/chapter_6/itam/domain/user.py:
--------------------------------------------------------------------------------
1 | # Create a class called User.
2 | # The User entity has the following attributes:
3 | # - username: str,
4 | # - password: str,
5 | # - roles: List[Role]
6 | # none of the attributes can be None
7 | # The User entity should have two methods: has_role() and has_role_by_name().
8 |
9 | from dataclasses import dataclass
10 | from typing import List
11 | from itam.domain.role import Role
12 |
13 | @dataclass
14 | class User:
15 | username: str
16 | password: str
17 | roles: List[Role]
18 |
19 | def __post_init__(self):
20 | if self.username is None:
21 | raise TypeError("Username cannot be None")
22 | if self.password is None:
23 | raise TypeError("Password cannot be None")
24 | if self.roles is None:
25 | raise TypeError("Roles cannot be None")
26 |
27 | def has_role(self, role: Role) -> bool:
28 | return role in self.roles
29 |
30 | def has_role_by_name(self, role_name: str) -> bool:
31 | for role in self.roles:
32 | if role.name == role_name:
33 | return True
34 | return False
--------------------------------------------------------------------------------
/chapter_7/itam/domain/user.py:
--------------------------------------------------------------------------------
1 | # Create a class called User.
2 | # The User entity has the following attributes:
3 | # - username: str,
4 | # - password: str,
5 | # - roles: List[Role]
6 | # none of the attributes can be None
7 | # The User entity should have two methods: has_role() and has_role_by_name().
8 |
9 | from dataclasses import dataclass
10 | from typing import List
11 | from itam.domain.role import Role
12 |
13 | @dataclass
14 | class User:
15 | username: str
16 | password: str
17 | roles: List[Role]
18 |
19 | def __post_init__(self):
20 | if self.username is None:
21 | raise TypeError("Username cannot be None")
22 | if self.password is None:
23 | raise TypeError("Password cannot be None")
24 | if self.roles is None:
25 | raise TypeError("Roles cannot be None")
26 |
27 | def has_role(self, role: Role) -> bool:
28 | return role in self.roles
29 |
30 | def has_role_by_name(self, role_name: str) -> bool:
31 | for role in self.roles:
32 | if role.name == role_name:
33 | return True
34 | return False
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/adapters/asset_rest_adapter.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestAdapter
2 | # It should take an AssetManager as a parameter in its constructor
3 | # It should expose all of the methods in AssetManager
4 | # It should inherit from AssetRestPort
5 |
6 | from itam.domain.asset import Asset
7 | from itam.infrastructure.ports.asset_rest_port import AssetRestPort
8 | from itam.service.asset_manager import AssetManager
9 | from typing import List
10 |
11 | class AssetRestAdapter(AssetRestPort):
12 | def __init__(self, asset_manager: AssetManager):
13 | self._asset_manager = asset_manager
14 |
15 | def read(self, asset_id: int) -> Asset:
16 | return self._asset_manager.read(asset_id)
17 |
18 | def create(self, asset: Asset) -> None:
19 | self._asset_manager.create(asset)
20 |
21 | def update(self, asset: Asset) -> None:
22 | self._asset_manager.update(asset)
23 |
24 | def delete(self, asset_id: int) -> None:
25 | self._asset_manager.delete(asset_id)
26 |
27 | def get_assets(self) -> List[Asset]:
28 | return self._asset_manager.get_assets()
29 |
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/adapters/asset_rest_adapter.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestAdapter
2 | # It should take an AssetManager as a parameter in its constructor
3 | # It should expose all of the methods in AssetManager
4 | # It should inherit from AssetRestPort
5 |
6 | from itam.domain.asset import Asset
7 | from itam.infrastructure.ports.asset_rest_port import AssetRestPort
8 | from itam.service.asset_manager import AssetManager
9 | from typing import List
10 |
11 | class AssetRestAdapter(AssetRestPort):
12 | def __init__(self, asset_manager: AssetManager):
13 | self._asset_manager = asset_manager
14 |
15 | def read(self, asset_id: int) -> Asset:
16 | return self._asset_manager.read(asset_id)
17 |
18 | def create(self, asset: Asset) -> None:
19 | self._asset_manager.create(asset)
20 |
21 | def update(self, asset: Asset) -> None:
22 | self._asset_manager.update(asset)
23 |
24 | def delete(self, asset_id: int) -> None:
25 | self._asset_manager.delete(asset_id)
26 |
27 | def get_assets(self) -> List[Asset]:
28 | return self._asset_manager.get_assets()
29 |
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/adapters/asset_rest_adapter.py:
--------------------------------------------------------------------------------
1 | # Define an interface called AssetRestAdapter
2 | # It should take an AssetManager as a parameter in its constructor
3 | # It should expose all of the methods in AssetManager
4 | # It should inherit from AssetRestPort
5 |
6 | from itam.domain.asset import Asset
7 | from itam.infrastructure.ports.asset_rest_port import AssetRestPort
8 | from itam.service.asset_manager import AssetManager
9 | from typing import List
10 |
11 | class AssetRestAdapter(AssetRestPort):
12 | def __init__(self, asset_manager: AssetManager):
13 | self._asset_manager = asset_manager
14 |
15 | def read(self, asset_id: int) -> Asset:
16 | return self._asset_manager.read(asset_id)
17 |
18 | def create(self, asset: Asset) -> None:
19 | self._asset_manager.create(asset)
20 |
21 | def update(self, asset: Asset) -> None:
22 | self._asset_manager.update(asset)
23 |
24 | def delete(self, asset_id: int) -> None:
25 | self._asset_manager.delete(asset_id)
26 |
27 | def get_assets(self) -> List[Asset]:
28 | return self._asset_manager.get_assets()
29 |
--------------------------------------------------------------------------------
/chapter_5/README.md:
--------------------------------------------------------------------------------
1 | # The AI-Assisted Developer Chapter 5
2 |
3 | {"asset_id": 1, "latitude": 41.8781, "longitude": -87.6298, "timestamp": "2022-01-01T00:00:00Z"}
4 | {"asset_id": 1, "latitude": 41.9000, "longitude": -87.6244, "timestamp": "2022-01-01T00:10:00Z"}
5 | {"asset_id": 1, "latitude": 41.8676, "longitude": -87.6270, "timestamp": "2022-01-01T00:20:00Z"}
6 | {"asset_id": 1, "latitude": 41.8788, "longitude": -87.6359, "timestamp": "2022-01-01T00:30:00Z"}
7 | {"asset_id": 1, "latitude": 41.8740, "longitude": -87.6298, "timestamp": "2022-01-01T00:40:00Z"}
8 | {"asset_id": 1, "latitude": 41.8800, "longitude": -87.6300, "timestamp": "2022-01-01T00:50:00Z"}
9 | {"asset_id": 1, "latitude": 41.8775, "longitude": -87.6244, "timestamp": "2022-01-01T01:00:00Z"}
10 | {"asset_id": 1, "latitude": 41.8745, "longitude": -87.6328, "timestamp": "2022-01-01T01:10:00Z"}
11 | {"asset_id": 1, "latitude": 41.8825, "longitude": -87.6298, "timestamp": "2022-01-01T01:20:00Z"}
12 | {"asset_id": 1, "latitude": 41.8800, "longitude": -87.6250, "timestamp": "2022-01-01T01:30:00Z"}
13 |
14 | {"asset_id": 1, "latitude": 40.7128, "longitude": -74.0060, "timestamp": "2022-01-01T13:30:00Z"}
--------------------------------------------------------------------------------
/chapter_6/README.md:
--------------------------------------------------------------------------------
1 | # The AI-Assisted Developer Chapter 5
2 |
3 | {"asset_id": 1, "latitude": 41.8781, "longitude": -87.6298, "timestamp": "2022-01-01T00:00:00Z"}
4 | {"asset_id": 1, "latitude": 41.9000, "longitude": -87.6244, "timestamp": "2022-01-01T00:10:00Z"}
5 | {"asset_id": 1, "latitude": 41.8676, "longitude": -87.6270, "timestamp": "2022-01-01T00:20:00Z"}
6 | {"asset_id": 1, "latitude": 41.8788, "longitude": -87.6359, "timestamp": "2022-01-01T00:30:00Z"}
7 | {"asset_id": 1, "latitude": 41.8740, "longitude": -87.6298, "timestamp": "2022-01-01T00:40:00Z"}
8 | {"asset_id": 1, "latitude": 41.8800, "longitude": -87.6300, "timestamp": "2022-01-01T00:50:00Z"}
9 | {"asset_id": 1, "latitude": 41.8775, "longitude": -87.6244, "timestamp": "2022-01-01T01:00:00Z"}
10 | {"asset_id": 1, "latitude": 41.8745, "longitude": -87.6328, "timestamp": "2022-01-01T01:10:00Z"}
11 | {"asset_id": 1, "latitude": 41.8825, "longitude": -87.6298, "timestamp": "2022-01-01T01:20:00Z"}
12 | {"asset_id": 1, "latitude": 41.8800, "longitude": -87.6250, "timestamp": "2022-01-01T01:30:00Z"}
13 |
14 | {"asset_id": 1, "latitude": 40.7128, "longitude": -74.0060, "timestamp": "2022-01-01T13:30:00Z"}
15 |
16 |
--------------------------------------------------------------------------------
/chapter_4/itam/visitor/department_visitor.py:
--------------------------------------------------------------------------------
1 | # define an interface called class DepartmentVisitor with the following methods:
2 | # +visit(self, asset: Asset) -> None
3 | # Additionally, define a class called class DepartmentStatisticsVisitor that implements the interface DepartmentVisitor
4 |
5 | from abc import ABC, abstractmethod
6 | from itam.domain.asset import Asset
7 |
8 | class DepartmentVisitor(ABC):
9 | @abstractmethod
10 | def visit(self, asset: Asset) -> None:
11 | pass
12 |
13 | class DepartmentStatisticsVisitor(DepartmentVisitor):
14 | def __init__(self):
15 | self._total_cost = 0
16 | self._total_depreciation = 0
17 | self._total_allocation = 0
18 |
19 | def visit(self, asset: Asset) -> None:
20 | self._total_cost += asset.get_cost()
21 | self._total_depreciation += asset.get_depreciation()
22 | self._total_allocation += asset.get_allocation()
23 |
24 | def get_total_cost(self):
25 | return self._total_cost
26 |
27 | def get_total_depreciation(self):
28 | return self._total_depreciation
29 |
30 | def get_total_allocation(self):
31 | return self._total_allocation
--------------------------------------------------------------------------------
/chapter_5/itam/visitor/department_visitor.py:
--------------------------------------------------------------------------------
1 | # define an interface called class DepartmentVisitor with the following methods:
2 | # +visit(self, asset: Asset) -> None
3 | # Additionally, define a class called class DepartmentStatisticsVisitor that implements the interface DepartmentVisitor
4 |
5 | from abc import ABC, abstractmethod
6 | from itam.domain.asset import Asset
7 |
8 | class DepartmentVisitor(ABC):
9 | @abstractmethod
10 | def visit(self, asset: Asset) -> None:
11 | pass
12 |
13 | class DepartmentStatisticsVisitor(DepartmentVisitor):
14 | def __init__(self):
15 | self._total_cost = 0
16 | self._total_depreciation = 0
17 | self._total_allocation = 0
18 |
19 | def visit(self, asset: Asset) -> None:
20 | self._total_cost += asset.get_cost()
21 | self._total_depreciation += asset.get_depreciation()
22 | self._total_allocation += asset.get_allocation()
23 |
24 | def get_total_cost(self):
25 | return self._total_cost
26 |
27 | def get_total_depreciation(self):
28 | return self._total_depreciation
29 |
30 | def get_total_allocation(self):
31 | return self._total_allocation
--------------------------------------------------------------------------------
/chapter_6/itam/domain/funding_details.py:
--------------------------------------------------------------------------------
1 | # Define a class called FundingDetails
2 | # It should have the following attributes:
3 | # - depreciation_strategy: DepreciationStrategy,
4 | # - depreciation_rate: float
5 | # - department_allocations: Dict[Department, float]
6 | # The attributes cannot be None and cannot be modified after construction
7 | # However, we should be able to access the attributes using methods
8 |
9 | from dataclasses import dataclass
10 | from itam.domain.depreciation_strategy import DepreciationStrategy
11 | from itam.domain.department import Department
12 | from typing import Dict
13 |
14 |
15 | @dataclass
16 | class FundingDetails:
17 | depreciation_rate: float
18 | department_allocations: Dict[Department, float]
19 | depreciation_strategy: DepreciationStrategy or 'itam.domain.depreciation_strategy.DepreciationStrategy'
20 | asset: None or 'itam.domain.asset.Asset'
21 |
22 | def get_depreciation_rate(self):
23 | return self.depreciation_rate
24 |
25 | def get_department_allocations(self):
26 | return self.department_allocations
27 |
28 | def get_depreciation_strategy(self):
29 | return self.depreciation_strategy
30 |
31 | def get_asset(self):
32 | return self.asset
33 |
--------------------------------------------------------------------------------
/chapter_7/itam/domain/funding_details.py:
--------------------------------------------------------------------------------
1 | # Define a class called FundingDetails
2 | # It should have the following attributes:
3 | # - depreciation_strategy: DepreciationStrategy,
4 | # - depreciation_rate: float
5 | # - department_allocations: Dict[Department, float]
6 | # The attributes cannot be None and cannot be modified after construction
7 | # However, we should be able to access the attributes using methods
8 |
9 | from dataclasses import dataclass
10 | from itam.domain.depreciation_strategy import DepreciationStrategy
11 | from itam.domain.department import Department
12 | from typing import Dict
13 |
14 |
15 | @dataclass
16 | class FundingDetails:
17 | depreciation_rate: float
18 | department_allocations: Dict[Department, float]
19 | depreciation_strategy: DepreciationStrategy or 'itam.domain.depreciation_strategy.DepreciationStrategy'
20 | asset: None or 'itam.domain.asset.Asset'
21 |
22 | def get_depreciation_rate(self):
23 | return self.depreciation_rate
24 |
25 | def get_department_allocations(self):
26 | return self.department_allocations
27 |
28 | def get_depreciation_strategy(self):
29 | return self.depreciation_strategy
30 |
31 | def get_asset(self):
32 | return self.asset
33 |
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/database/database_connection.py:
--------------------------------------------------------------------------------
1 | # Create a Python class called DatabaseConnection that uses the Singleton pattern to manage a single database connection to a PostgreSQL database using SQLAlchemy.
2 | # The class should read the database username, password, and connection string from environment variables
3 | # The environment variables should be named: DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, and DB_NAME
4 |
5 | from sqlalchemy import create_engine
6 | from sqlalchemy.orm import sessionmaker
7 | import os
8 |
9 | class DatabaseConnection:
10 | __instance = None
11 | @staticmethod
12 | def get_instance():
13 | if DatabaseConnection.__instance == None:
14 | DatabaseConnection()
15 | return DatabaseConnection.__instance
16 |
17 | def __init__(self):
18 | if DatabaseConnection.__instance != None:
19 | raise Exception("This class is a singleton!")
20 | else:
21 | DatabaseConnection.__instance = self
22 | self.engine = create_engine(f"postgresql://{os.environ['DB_USERNAME']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:{os.environ['DB_PORT']}/{os.environ['DB_NAME']}")
23 | self.Session = sessionmaker(bind=self.engine)
24 |
25 | def get_session(self):
26 | return self.Session()
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/asset.Flask.py:
--------------------------------------------------------------------------------
1 | class Asset:
2 | def __init__(self, asset_id, asset_type, manufacturer, model, purchase_date, warranty_end_date, location):
3 | self.asset_id = asset_id
4 | self.asset_type = asset_type
5 | self.manufacturer = manufacturer
6 | self.model = model
7 | self.purchase_date = purchase_date
8 | self.warranty_end_date = warranty_end_date
9 | self.location = location
10 | self.assigned_to = None
11 | self.status = 'Available'
12 |
13 | def assign_to_user(self, user):
14 | self.assigned_to = user
15 | self.status = 'Assigned'
16 |
17 | def unassign(self):
18 | self.assigned_to = None
19 | self.status = 'Available'
20 |
21 | def get_details(self):
22 | details = f"Asset ID: {self.asset_id}\n"
23 | details += f"Type: {self.asset_type}\n"
24 | details += f"Manufacturer: {self.manufacturer}\n"
25 | details += f"Model: {self.model}\n"
26 | details += f"Purchase Date: {self.purchase_date}\n"
27 | details += f"Warranty End Date: {self.warranty_end_date}\n"
28 | details += f"Location: {self.location}\n"
29 | details += f"Assigned To: {self.assigned_to}\n"
30 | details += f"Status: {self.status}\n"
31 | return details
32 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/asset.Flask.py:
--------------------------------------------------------------------------------
1 | class Asset:
2 | def __init__(self, asset_id, asset_type, manufacturer, model, purchase_date, warranty_end_date, location):
3 | self.asset_id = asset_id
4 | self.asset_type = asset_type
5 | self.manufacturer = manufacturer
6 | self.model = model
7 | self.purchase_date = purchase_date
8 | self.warranty_end_date = warranty_end_date
9 | self.location = location
10 | self.assigned_to = None
11 | self.status = 'Available'
12 |
13 | def assign_to_user(self, user):
14 | self.assigned_to = user
15 | self.status = 'Assigned'
16 |
17 | def unassign(self):
18 | self.assigned_to = None
19 | self.status = 'Available'
20 |
21 | def get_details(self):
22 | details = f"Asset ID: {self.asset_id}\n"
23 | details += f"Type: {self.asset_type}\n"
24 | details += f"Manufacturer: {self.manufacturer}\n"
25 | details += f"Model: {self.model}\n"
26 | details += f"Purchase Date: {self.purchase_date}\n"
27 | details += f"Warranty End Date: {self.warranty_end_date}\n"
28 | details += f"Location: {self.location}\n"
29 | details += f"Assigned To: {self.assigned_to}\n"
30 | details += f"Status: {self.status}\n"
31 | return details
32 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/asset_manager.Flask.py:
--------------------------------------------------------------------------------
1 | class AssetManager:
2 | def __init__(self):
3 | self.assets = []
4 |
5 | def add_asset(self, asset):
6 | self.assets.append(asset)
7 |
8 | def remove_asset(self, asset_id):
9 | for asset in self.assets:
10 | if asset.asset_id == asset_id:
11 | self.assets.remove(asset)
12 | return True
13 | return False
14 |
15 | def get_asset_by_id(self, asset_id):
16 | for asset in self.assets:
17 | if asset.asset_id == asset_id:
18 | return asset
19 | return None
20 |
21 | def assign_asset(self, asset_id, user):
22 | asset = self.get_asset_by_id(asset_id)
23 | if asset and asset.status == 'Available':
24 | asset.assign_to_user(user)
25 | return True
26 | return False
27 |
28 | def unassign_asset(self, asset_id):
29 | asset = self.get_asset_by_id(asset_id)
30 | if asset and asset.status == 'Assigned':
31 | asset.unassign()
32 | return True
33 | return False
34 |
35 | def get_available_assets(self):
36 | return [asset for asset in self.assets if asset.status == 'Available']
37 |
38 | def get_assigned_assets(self):
39 | return [asset for asset in self.assets if asset.status == 'Assigned']
40 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/asset_manager.Flask.py:
--------------------------------------------------------------------------------
1 | class AssetManager:
2 | def __init__(self):
3 | self.assets = []
4 |
5 | def add_asset(self, asset):
6 | self.assets.append(asset)
7 |
8 | def remove_asset(self, asset_id):
9 | for asset in self.assets:
10 | if asset.asset_id == asset_id:
11 | self.assets.remove(asset)
12 | return True
13 | return False
14 |
15 | def get_asset_by_id(self, asset_id):
16 | for asset in self.assets:
17 | if asset.asset_id == asset_id:
18 | return asset
19 | return None
20 |
21 | def assign_asset(self, asset_id, user):
22 | asset = self.get_asset_by_id(asset_id)
23 | if asset and asset.status == 'Available':
24 | asset.assign_to_user(user)
25 | return True
26 | return False
27 |
28 | def unassign_asset(self, asset_id):
29 | asset = self.get_asset_by_id(asset_id)
30 | if asset and asset.status == 'Assigned':
31 | asset.unassign()
32 | return True
33 | return False
34 |
35 | def get_available_assets(self):
36 | return [asset for asset in self.assets if asset.status == 'Available']
37 |
38 | def get_assigned_assets(self):
39 | return [asset for asset in self.assets if asset.status == 'Assigned']
40 |
--------------------------------------------------------------------------------
/chapter_2/copilot/app.py:
--------------------------------------------------------------------------------
1 | # Create a FastAPI app that allows CRUD operations on the Asset class.
2 | from fastapi import FastAPI
3 | from fastapi.responses import JSONResponse
4 | from pydantic import BaseModel
5 | from typing import List, Optional
6 | from asset import Asset
7 | from asset_manager import AssetManager
8 |
9 | app = FastAPI()
10 | asset_manager = AssetManager()
11 |
12 | class AssetIn(BaseModel):
13 | asset_id: str
14 | asset_type: str
15 | manufacturer: str
16 | model: str
17 | purchase_date: str
18 | warranty_end_date: str
19 | location: str
20 |
21 | class AssetOut(BaseModel):
22 | asset_id: str
23 | asset_type: str
24 | manufacturer: str
25 | model: str
26 | purchase_date: str
27 | warranty_end_date: str
28 | location: str
29 | assigned_to: Optional[str]
30 | status: str
31 |
32 | @app.get("/assets/", response_model=List[AssetOut])
33 | async def get_assets():
34 | assets = asset_manager.get_assets()
35 | return JSONResponse(content=[asset.to_dict() for asset in assets])
36 |
37 |
38 | @app.post("/assets/")
39 | async def add_asset(asset: AssetIn):
40 | new_asset = Asset(asset.asset_id, asset.asset_type, asset.manufacturer, asset.model, asset.purchase_date, asset.warranty_end_date, asset.location)
41 | asset_manager.add_asset(new_asset)
42 | return {"message": "Asset added successfully"}
--------------------------------------------------------------------------------
/chapter_4/main.py:
--------------------------------------------------------------------------------
1 | # Importing the necessary modules and packages
2 | # Instantiating the necessary objects and components, such as the FastAPI application and database connection
3 | # Configuring the application settings and environment variables
4 | # Mounting the HTTP controllers and endpoints to the FastAPI application
5 | # Starting the server and running the application
6 |
7 | from fastapi import FastAPI
8 | from itam.infrastructure.api.asset_controller import AssetController
9 | #from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
10 | from itam.infrastructure.repository.sqlalchemy_asset_repository import SQLAlchemyAssetRepository
11 | from itam.infrastructure.database.database_connection import DatabaseConnection
12 | from itam.service.asset_manager import AssetManager
13 | from itam.infrastructure.adapters.asset_rest_adapter import AssetRestAdapter
14 | import uvicorn
15 |
16 | app = FastAPI()
17 | session = DatabaseConnection().get_session()
18 | #repository = InMemoryAssetRepository()
19 | repository = SQLAlchemyAssetRepository(session)
20 | asset_manager = AssetManager(repository)
21 | asset_rest_adapter = AssetRestAdapter(asset_manager)
22 | asset_controller = AssetController(asset_rest_adapter)
23 | app.include_router(asset_controller.get_router())
24 |
25 | if __name__ == '__main__':
26 | uvicorn.run(app, host='0.0.0.0', port=8000)
27 |
--------------------------------------------------------------------------------
/chapter_4/itam/service/asset_manager.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetManager
2 | # with CRUD operations for Asset
3 | # and a method to notify observers whenever an asset is created, updated or deleted
4 | # The AssetManager should accpet an instance of the BaseRepository[Asset] for data access and CRUD operations on Asset objects.
5 | # Implement methods for creating, reading, updating, and deleting assets using the AssetRepository instance.
6 | # Please include type hints for the input parameters and return values.
7 | # The methods should be named create, read, update, get_assets, and delete.
8 |
9 | from itam.domain.asset import Asset
10 | from itam.infrastructure.repository.base_repository import BaseRepository
11 |
12 | class AssetManager:
13 | def __init__(self, base_repository: BaseRepository[Asset]):
14 | self._repository = base_repository
15 |
16 | def create(self, asset: Asset) -> Asset:
17 | self._repository.create(asset)
18 | return asset
19 |
20 | def read(self, asset_id: int) -> Asset:
21 | return self._repository.read(asset_id)
22 |
23 | def update(self, asset: Asset) -> Asset:
24 | self._repository.update(asset)
25 | return asset
26 |
27 | def get_assets(self) -> list[Asset]:
28 | return self._repository.get_entities()
29 |
30 | def delete(self, asset_id: int) -> None:
31 | self._repository.delete(asset_id)
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/repository/sqlalchemy_asset_repository.py:
--------------------------------------------------------------------------------
1 | # Define a class called SQLAlchemyAssetRepository that implements the AssetRepository interface for data access using SQLAlchemy.
2 | # The class should handle the CRUD operations (create, read, update, and delete) for assets, storing and retrieving them in a PostgreSQL database using SQLAlchemy.
3 |
4 | from itam.domain.asset import Asset
5 | from itam.infrastructure.repository.base_repository import BaseRepository
6 | from sqlalchemy.orm import Session
7 |
8 | class SQLAlchemyAssetRepository(BaseRepository[Asset]):
9 | def __init__(self, session: Session):
10 | self._session = session
11 |
12 | def create(self, asset: Asset) -> Asset:
13 | self._session.add(asset)
14 | self._session.commit()
15 | return asset
16 |
17 | def read(self, asset_id: int) -> Asset:
18 | return self._session.query(Asset).filter(Asset.id == asset_id).first()
19 |
20 | def update(self, asset: Asset) -> Asset:
21 | self._session.query(Asset).filter(Asset.id == asset.id).update(asset)
22 | self._session.commit()
23 | return asset
24 |
25 | def get_assets(self) -> list[Asset]:
26 | return self._session.query(Asset).all()
27 |
28 | def delete(self, asset_id: int) -> None:
29 | self._session.query(Asset).filter(Asset.id == asset_id).delete()
30 | self._session.commit()
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/repository/in_memory_asset_repository.py:
--------------------------------------------------------------------------------
1 | # Define a class called InMemoryAssetRepository that inherits from the BaseRepository abstract class.
2 | # The InMemoryAssetRepository should be specific to managing Asset objects sing an in-memory list to store and update the assets.
3 | # Implement the necessary methods for CRUD operations such as create, read, update, and delete for Asset objects using the in-memory list.
4 | # Make sure to use type hints for the input parameters and return values.
5 |
6 | from itam.infrastructure.repository.base_repository import BaseRepository
7 | from itam.domain.asset import Asset
8 |
9 | class InMemoryAssetRepository(BaseRepository[Asset]):
10 | def __init__(self):
11 | self._assets = []
12 |
13 | def create(self, asset: Asset) -> None:
14 | self._assets.append(asset)
15 |
16 | def read(self, asset_id: int) -> Asset:
17 | return next((asset for asset in self._assets if asset.id == asset_id), None)
18 |
19 | def update(self, asset: Asset) -> None:
20 | for i in range(len(self._assets)):
21 | if self._assets[i].id == asset.id:
22 | self._assets[i] = asset
23 | break
24 |
25 | def delete(self, asset_id: int) -> None:
26 | self._assets = [asset for asset in self._assets if asset.id != asset_id]
27 |
28 | def get_entities(self) -> list[Asset]:
29 | return self._assets
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/repository/in_memory_asset_repository.py:
--------------------------------------------------------------------------------
1 | # Define a class called InMemoryAssetRepository that inherits from the BaseRepository abstract class.
2 | # The InMemoryAssetRepository should be specific to managing Asset objects sing an in-memory list to store and update the assets.
3 | # Implement the necessary methods for CRUD operations such as create, read, update, and delete for Asset objects using the in-memory list.
4 | # Make sure to use type hints for the input parameters and return values.
5 |
6 | from itam.infrastructure.repository.base_repository import BaseRepository
7 | from itam.domain.asset import Asset
8 |
9 | class InMemoryAssetRepository(BaseRepository[Asset]):
10 | def __init__(self):
11 | self._assets = []
12 |
13 | def create(self, asset: Asset) -> None:
14 | self._assets.append(asset)
15 |
16 | def read(self, asset_id: int) -> Asset:
17 | return next((asset for asset in self._assets if asset.id == asset_id), None)
18 |
19 | def update(self, asset: Asset) -> None:
20 | for i in range(len(self._assets)):
21 | if self._assets[i].id == asset.id:
22 | self._assets[i] = asset
23 | break
24 |
25 | def delete(self, asset_id: int) -> None:
26 | self._assets = [asset for asset in self._assets if asset.id != asset_id]
27 |
28 | def get_entities(self) -> list[Asset]:
29 | return self._assets
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/repository/in_memory_asset_repository.py:
--------------------------------------------------------------------------------
1 | # Define a class called InMemoryAssetRepository that inherits from the BaseRepository abstract class.
2 | # The InMemoryAssetRepository should be specific to managing Asset objects sing an in-memory list to store and update the assets.
3 | # Implement the necessary methods for CRUD operations such as create, read, update, and delete for Asset objects using the in-memory list.
4 | # Make sure to use type hints for the input parameters and return values.
5 |
6 | from itam.infrastructure.repository.base_repository import BaseRepository
7 | from itam.domain.asset import Asset
8 |
9 | class InMemoryAssetRepository(BaseRepository[Asset]):
10 | def __init__(self):
11 | self._assets = []
12 |
13 | def create(self, asset: Asset) -> None:
14 | self._assets.append(asset)
15 |
16 | def read(self, asset_id: int) -> Asset:
17 | return next((asset for asset in self._assets if asset.id == asset_id), None)
18 |
19 | def update(self, asset: Asset) -> None:
20 | for i in range(len(self._assets)):
21 | if self._assets[i].id == asset.id:
22 | self._assets[i] = asset
23 | break
24 |
25 | def delete(self, asset_id: int) -> None:
26 | self._assets = [asset for asset in self._assets if asset.id != asset_id]
27 |
28 | def get_entities(self) -> list[Asset]:
29 | return self._assets
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/repository/in_memory_asset_repository.py:
--------------------------------------------------------------------------------
1 | # Define a class called InMemoryAssetRepository that inherits from the BaseRepository abstract class.
2 | # The InMemoryAssetRepository should be specific to managing Asset objects sing an in-memory list to store and update the assets.
3 | # Implement the necessary methods for CRUD operations such as create, read, update, and delete for Asset objects using the in-memory list.
4 | # Make sure to use type hints for the input parameters and return values.
5 |
6 | from itam.infrastructure.repository.base_repository import BaseRepository
7 | from itam.domain.asset import Asset
8 |
9 | class InMemoryAssetRepository(BaseRepository[Asset]):
10 | def __init__(self):
11 | self._assets = []
12 |
13 | def create(self, asset: Asset) -> None:
14 | self._assets.append(asset)
15 |
16 | def read(self, asset_id: int) -> Asset:
17 | return next((asset for asset in self._assets if asset.id == asset_id), None)
18 |
19 | def update(self, asset: Asset) -> None:
20 | for i in range(len(self._assets)):
21 | if self._assets[i].id == asset.id:
22 | self._assets[i] = asset
23 | break
24 |
25 | def delete(self, asset_id: int) -> None:
26 | self._assets = [asset for asset in self._assets if asset.id != asset_id]
27 |
28 | def get_entities(self) -> list[Asset]:
29 | return self._assets
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/consumers/asset_location_kafka_consumer.py:
--------------------------------------------------------------------------------
1 | from kafka import KafkaConsumer
2 | from itam.domain.events.asset_location_updated import AssetLocationUpdated
3 | import json
4 | import asyncio
5 |
6 | class AssetLocationKafkaConsumer:
7 | def __init__(self, mediator):
8 | self.mediator = mediator
9 |
10 | self.consumer = KafkaConsumer(
11 | 'asset_location',
12 | bootstrap_servers=['localhost:9092'],
13 | enable_auto_commit=True,
14 | group_id='itam-group',
15 | value_deserializer=lambda m: json.loads(m.decode('utf-8'))
16 | )
17 |
18 | # Define a function to process Kafka messages
19 | async def process_messages_async(self):
20 | for message in self.consumer:
21 | asset_id = message.value['asset_id']
22 | latitude = message.value['latitude']
23 | longitude = message.value['longitude']
24 | timestamp = message.value['timestamp']
25 | event = AssetLocationUpdated(asset_id, latitude, longitude, timestamp)
26 | self.mediator.publish(event)
27 |
28 | async def start_consumer_async(self):
29 | print('Starting Kafka consumer...')
30 | await self.process_messages_async()
31 |
32 | def start_consumer(self):
33 | loop = asyncio.new_event_loop()
34 | asyncio.set_event_loop(loop)
35 | loop.run_until_complete(self.start_consumer_async())
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/consumers/asset_location_kafka_consumer.py:
--------------------------------------------------------------------------------
1 | from kafka import KafkaConsumer
2 | from itam.domain.events.asset_location_updated import AssetLocationUpdated
3 | import json
4 | import asyncio
5 |
6 | class AssetLocationKafkaConsumer:
7 | def __init__(self, mediator):
8 | self.mediator = mediator
9 |
10 | self.consumer = KafkaConsumer(
11 | 'asset_location',
12 | bootstrap_servers=['localhost:9092'],
13 | enable_auto_commit=True,
14 | group_id='itam-group',
15 | value_deserializer=lambda m: json.loads(m.decode('utf-8'))
16 | )
17 |
18 | # Define a function to process Kafka messages
19 | async def process_messages_async(self):
20 | for message in self.consumer:
21 | asset_id = message.value['asset_id']
22 | latitude = message.value['latitude']
23 | longitude = message.value['longitude']
24 | timestamp = message.value['timestamp']
25 | event = AssetLocationUpdated(asset_id, latitude, longitude, timestamp)
26 | self.mediator.publish(event)
27 |
28 | async def start_consumer_async(self):
29 | print('Starting Kafka consumer...')
30 | await self.process_messages_async()
31 |
32 | def start_consumer(self):
33 | loop = asyncio.new_event_loop()
34 | asyncio.set_event_loop(loop)
35 | loop.run_until_complete(self.start_consumer_async())
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/consumers/asset_location_kafka_consumer.py:
--------------------------------------------------------------------------------
1 | from kafka import KafkaConsumer
2 | from itam.domain.events.asset_location_updated import AssetLocationUpdated
3 | import json
4 | import asyncio
5 |
6 | class AssetLocationKafkaConsumer:
7 | def __init__(self, mediator):
8 | self.mediator = mediator
9 |
10 | self.consumer = KafkaConsumer(
11 | 'asset_location',
12 | bootstrap_servers=['localhost:9092'],
13 | enable_auto_commit=True,
14 | group_id='itam-group',
15 | value_deserializer=lambda m: json.loads(m.decode('utf-8'))
16 | )
17 |
18 | # Define a function to process Kafka messages
19 | async def process_messages_async(self):
20 | for message in self.consumer:
21 | asset_id = message.value['asset_id']
22 | latitude = message.value['latitude']
23 | longitude = message.value['longitude']
24 | timestamp = message.value['timestamp']
25 | event = AssetLocationUpdated(asset_id, latitude, longitude, timestamp)
26 | self.mediator.publish(event)
27 |
28 | async def start_consumer_async(self):
29 | print('Starting Kafka consumer...')
30 | await self.process_messages_async()
31 |
32 | def start_consumer(self):
33 | loop = asyncio.new_event_loop()
34 | asyncio.set_event_loop(loop)
35 | loop.run_until_complete(self.start_consumer_async())
--------------------------------------------------------------------------------
/chapter_5/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.1'
2 |
3 | services:
4 | zookeeper:
5 | image: confluentinc/cp-zookeeper:7.3.2
6 | container_name: zookeeper
7 | ports:
8 | - "2181:2181"
9 | environment:
10 | ZOOKEEPER_CLIENT_PORT: 2181
11 | ZOOKEEPER_SERVER_ID: 1
12 | ZOOKEEPER_SERVERS: zoo1:2888:3888
13 |
14 | kafka:
15 | image: confluentinc/cp-kafka:7.3.2
16 | hostname: kafka
17 | container_name: kafka
18 | ports:
19 | - "9092:9092"
20 | - "29092:29092"
21 | - "9999:9999"
22 | environment:
23 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092
24 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
25 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
26 | KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
27 | KAFKA_BROKER_ID: 1
28 | KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
29 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
30 | KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
31 | KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
32 | KAFKA_JMX_PORT: 9999
33 | KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1}
34 | KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
35 | KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
36 | depends_on:
37 | - zookeeper
--------------------------------------------------------------------------------
/chapter_6/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.1'
2 |
3 | services:
4 | zookeeper:
5 | image: confluentinc/cp-zookeeper:7.3.2
6 | container_name: zookeeper
7 | ports:
8 | - "2181:2181"
9 | environment:
10 | ZOOKEEPER_CLIENT_PORT: 2181
11 | ZOOKEEPER_SERVER_ID: 1
12 | ZOOKEEPER_SERVERS: zoo1:2888:3888
13 |
14 | kafka:
15 | image: confluentinc/cp-kafka:7.3.2
16 | hostname: kafka
17 | container_name: kafka
18 | ports:
19 | - "9092:9092"
20 | - "29092:29092"
21 | - "9999:9999"
22 | environment:
23 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092
24 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
25 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
26 | KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
27 | KAFKA_BROKER_ID: 1
28 | KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
29 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
30 | KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
31 | KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
32 | KAFKA_JMX_PORT: 9999
33 | KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1}
34 | KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
35 | KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
36 | depends_on:
37 | - zookeeper
--------------------------------------------------------------------------------
/chapter_7/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2.1'
2 |
3 | services:
4 | zookeeper:
5 | image: confluentinc/cp-zookeeper:7.3.2
6 | container_name: zookeeper
7 | ports:
8 | - "2181:2181"
9 | environment:
10 | ZOOKEEPER_CLIENT_PORT: 2181
11 | ZOOKEEPER_SERVER_ID: 1
12 | ZOOKEEPER_SERVERS: zoo1:2888:3888
13 |
14 | kafka:
15 | image: confluentinc/cp-kafka:7.3.2
16 | hostname: kafka
17 | container_name: kafka
18 | ports:
19 | - "9092:9092"
20 | - "29092:29092"
21 | - "9999:9999"
22 | environment:
23 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092
24 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
25 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
26 | KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
27 | KAFKA_BROKER_ID: 1
28 | KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
29 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
30 | KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
31 | KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
32 | KAFKA_JMX_PORT: 9999
33 | KAFKA_JMX_HOSTNAME: ${DOCKER_HOST_IP:-127.0.0.1}
34 | KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
35 | KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
36 | depends_on:
37 | - zookeeper
--------------------------------------------------------------------------------
/chapter_2/code-whisperer/asset.py:
--------------------------------------------------------------------------------
1 | # Create a class named Asset
2 | # Add the following attributes: id, asset_type, manufacturer, model, purchase_date, purchase_price, warranty_end_date, location, and status.
3 | # The class should have a function named get_details returns a string which is the concatenation of all of the attributes.
4 | # The class should have a function named to_dict that returns a dictionary of all of the attributes.
5 |
6 | class Asset():
7 | def __init__(self, id, asset_type, manufacturer, model, purchase_date, purchase_price, warranty_end_date, location, status):
8 | self.id = id
9 | self.asset_type = asset_type
10 | self.manufacturer = manufacturer
11 | self.model = model
12 | self.purchase_date = purchase_date
13 | self.purchase_price = purchase_price
14 | self.warranty_end_date = warranty_end_date
15 | self.location = location
16 | self.status = status
17 |
18 | def get_details(self):
19 | return f"{self.id}, {self.asset_type}, {self.manufacturer}, {self.model}, {self.purchase_date}, {self.purchase_price}, {self.warranty_end_date}, {self.location}, {self.status}"
20 |
21 | def to_dict(self):
22 | return {"id": self.id, "asset_type": self.asset_type, "manufacturer": self.manufacturer, "model": self.model, "purchase_date": self.purchase_date, "purchase_price": self.purchase_price, "warranty_end_date": self.warranty_end_date, "location": self.location, "status": self.status}
--------------------------------------------------------------------------------
/chapter_2/copilot/asset.py:
--------------------------------------------------------------------------------
1 | # Create a class named Asset
2 | # Add the following attributes:
3 | # id, asset_type, manufacturer, model, purchase_date, purchase_price, warranty_end_date, location, and status.
4 | # The class should have a function named get_details returns a string which is the concatenation of all of the attributes.
5 | # The class should have a function named to_dict that returns a dictionary of all of the attributes.
6 |
7 | class Asset:
8 | def __init__(self):
9 | self.id = None
10 | self.asset_type = None
11 | self.manufacturer = None
12 | self.model = None
13 | self.purchase_date = None
14 | self.purchase_price = None
15 | self.warranty_end_date = None
16 | self.location = None
17 | self.status = None
18 |
19 | def get_details(self):
20 | return f"{self.id}, {self.asset_type}, {self.manufacturer}, {self.model}, {self.purchase_date}, {self.purchase_price}, {self.warranty_end_date}, {self.location}, {self.status}"
21 |
22 | def to_dict(self):
23 | return {
24 | "id": self.id,
25 | "asset_type": self.asset_type,
26 | "manufacturer": self.manufacturer,
27 | "model": self.model,
28 | "purchase_date": self.purchase_date,
29 | "purchase_price": self.purchase_price,
30 | "warranty_end_date": self.warranty_end_date,
31 | "location": self.location,
32 | "status": self.status
33 | }
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/database/database_connection.py:
--------------------------------------------------------------------------------
1 | # Create a Python class called DatabaseConnection that uses the Singleton pattern to manage a single database connection to a PostgreSQL database using SQLAlchemy.
2 | # The class should read the database username, password, and connection string from environment variables
3 | # The environment variables should be named: DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, and DB_NAME
4 |
5 | from sqlalchemy import create_engine
6 | from sqlalchemy.orm import sessionmaker
7 | import os
8 |
9 | class DatabaseConnection:
10 | __instance = None
11 | @staticmethod
12 | def get_instance():
13 | if DatabaseConnection.__instance == None:
14 | DatabaseConnection()
15 | return DatabaseConnection.__instance
16 |
17 | def __init__(self):
18 | if DatabaseConnection.__instance != None:
19 | raise Exception("This class is a singleton!")
20 | else:
21 | DatabaseConnection.__instance = self
22 | self.engine = create_engine(f"postgresql://itam_user:itam_user@localhost:5432/postgres", connect_args={'options': '-csearch_path=itam'})
23 | #self.engine = create_engine(f"postgresql://{os.environ['DB_USERNAME']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:{os.environ['DB_PORT']}/{os.environ['DB_NAME']}", connect_args={'options': '-csearch_path={}'.format(os.environ['DB_SCHEMA'])})
24 | self.Session = sessionmaker(bind=self.engine)
25 |
26 | def get_session(self):
27 | return self.Session()
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/database/database_connection.py:
--------------------------------------------------------------------------------
1 | # Create a Python class called DatabaseConnection that uses the Singleton pattern to manage a single database connection to a PostgreSQL database using SQLAlchemy.
2 | # The class should read the database username, password, and connection string from environment variables
3 | # The environment variables should be named: DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, and DB_NAME
4 |
5 | from sqlalchemy import create_engine
6 | from sqlalchemy.orm import sessionmaker
7 | import os
8 |
9 | class DatabaseConnection:
10 | __instance = None
11 | @staticmethod
12 | def get_instance():
13 | if DatabaseConnection.__instance == None:
14 | DatabaseConnection()
15 | return DatabaseConnection.__instance
16 |
17 | def __init__(self):
18 | if DatabaseConnection.__instance != None:
19 | raise Exception("This class is a singleton!")
20 | else:
21 | DatabaseConnection.__instance = self
22 | self.engine = create_engine(f"postgresql://itam_user:itam_user@localhost:5432/postgres", connect_args={'options': '-csearch_path=itam'})
23 | #self.engine = create_engine(f"postgresql://{os.environ['DB_USERNAME']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:{os.environ['DB_PORT']}/{os.environ['DB_NAME']}", connect_args={'options': '-csearch_path={}'.format(os.environ['DB_SCHEMA'])})
24 | self.Session = sessionmaker(bind=self.engine)
25 |
26 | def get_session(self):
27 | return self.Session()
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/database/database_connection.py:
--------------------------------------------------------------------------------
1 | # Create a Python class called DatabaseConnection that uses the Singleton pattern to manage a single database connection to a PostgreSQL database using SQLAlchemy.
2 | # The class should read the database username, password, and connection string from environment variables
3 | # The environment variables should be named: DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, and DB_NAME
4 |
5 | from sqlalchemy import create_engine
6 | from sqlalchemy.orm import sessionmaker
7 | import os
8 |
9 | class DatabaseConnection:
10 | __instance = None
11 | @staticmethod
12 | def get_instance():
13 | if DatabaseConnection.__instance == None:
14 | DatabaseConnection()
15 | return DatabaseConnection.__instance
16 |
17 | def __init__(self):
18 | if DatabaseConnection.__instance != None:
19 | raise Exception("This class is a singleton!")
20 | else:
21 | DatabaseConnection.__instance = self
22 | self.engine = create_engine(f"postgresql://itam_user:itam_user@localhost:5432/postgres", connect_args={'options': '-csearch_path=itam'})
23 | #self.engine = create_engine(f"postgresql://{os.environ['DB_USERNAME']}:{os.environ['DB_PASSWORD']}@{os.environ['DB_HOST']}:{os.environ['DB_PORT']}/{os.environ['DB_NAME']}", connect_args={'options': '-csearch_path={}'.format(os.environ['DB_SCHEMA'])})
24 | self.Session = sessionmaker(bind=self.engine)
25 |
26 | def get_session(self):
27 | return self.Session()
--------------------------------------------------------------------------------
/chapter_4/diagram2.mmd:
--------------------------------------------------------------------------------
1 | graph LR
2 | User[User] --> ITAM_UI[ITAM User Interface]
3 | ITAM_UI --> AssetController[Asset Controller]
4 | ITAM_UI --> UserController[User Controller]
5 |
6 | AssetController --> AssetService[Asset Service]
7 | UserController --> UserService[User Service]
8 |
9 | AssetService --> HardwareRepository[Hardware Repository]
10 | AssetService --> VendorRepository[Vendor Repository]
11 | AssetService --> ProcurementRepository[Procurement Repository]
12 | UserService --> UserRepository[User Repository]
13 |
14 | HardwareRepository --> HardwareAPI[Hardware API]
15 | VendorRepository --> VendorAPI[Vendor API]
16 | ProcurementRepository --> ProcurementAPI[Procurement API]
17 | UserRepository --> AuthAPI[Authentication & Authorization API]
18 |
19 | HardwareAPI --> DB1[(Hardware Database)]
20 | VendorAPI --> DB2[(Vendor Database)]
21 | ProcurementAPI --> DB3[(Procurement Database)]
22 | AuthAPI --> DB4[(User Database)]
23 |
24 | class User user;
25 | class ITAM_UI ui;
26 | class AssetController assetController;
27 | class UserController userController;
28 | class AssetService assetService;
29 | class UserService userService;
30 | class HardwareRepository hardwareRepository;
31 | class VendorRepository vendorRepository;
32 | class ProcurementRepository procurementRepository;
33 | class UserRepository userRepository;
34 | class HardwareAPI hardwareAPI;
35 | class VendorAPI vendorAPI;
36 | class ProcurementAPI procurementAPI;
37 | class DB1 db1;
38 | class DB2 db2;
39 | class DB3 db3;
40 | class DB4 db4;
--------------------------------------------------------------------------------
/chapter_5/diagram2.mmd:
--------------------------------------------------------------------------------
1 | graph LR
2 | User[User] --> ITAM_UI[ITAM User Interface]
3 | ITAM_UI --> AssetController[Asset Controller]
4 | ITAM_UI --> UserController[User Controller]
5 |
6 | AssetController --> AssetService[Asset Service]
7 | UserController --> UserService[User Service]
8 |
9 | AssetService --> HardwareRepository[Hardware Repository]
10 | AssetService --> VendorRepository[Vendor Repository]
11 | AssetService --> ProcurementRepository[Procurement Repository]
12 | UserService --> UserRepository[User Repository]
13 |
14 | HardwareRepository --> HardwareAPI[Hardware API]
15 | VendorRepository --> VendorAPI[Vendor API]
16 | ProcurementRepository --> ProcurementAPI[Procurement API]
17 | UserRepository --> AuthAPI[Authentication & Authorization API]
18 |
19 | HardwareAPI --> DB1[(Hardware Database)]
20 | VendorAPI --> DB2[(Vendor Database)]
21 | ProcurementAPI --> DB3[(Procurement Database)]
22 | AuthAPI --> DB4[(User Database)]
23 |
24 | class User user;
25 | class ITAM_UI ui;
26 | class AssetController assetController;
27 | class UserController userController;
28 | class AssetService assetService;
29 | class UserService userService;
30 | class HardwareRepository hardwareRepository;
31 | class VendorRepository vendorRepository;
32 | class ProcurementRepository procurementRepository;
33 | class UserRepository userRepository;
34 | class HardwareAPI hardwareAPI;
35 | class VendorAPI vendorAPI;
36 | class ProcurementAPI procurementAPI;
37 | class DB1 db1;
38 | class DB2 db2;
39 | class DB3 db3;
40 | class DB4 db4;
--------------------------------------------------------------------------------
/chapter_6/diagram2.mmd:
--------------------------------------------------------------------------------
1 | graph LR
2 | User[User] --> ITAM_UI[ITAM User Interface]
3 | ITAM_UI --> AssetController[Asset Controller]
4 | ITAM_UI --> UserController[User Controller]
5 |
6 | AssetController --> AssetService[Asset Service]
7 | UserController --> UserService[User Service]
8 |
9 | AssetService --> HardwareRepository[Hardware Repository]
10 | AssetService --> VendorRepository[Vendor Repository]
11 | AssetService --> ProcurementRepository[Procurement Repository]
12 | UserService --> UserRepository[User Repository]
13 |
14 | HardwareRepository --> HardwareAPI[Hardware API]
15 | VendorRepository --> VendorAPI[Vendor API]
16 | ProcurementRepository --> ProcurementAPI[Procurement API]
17 | UserRepository --> AuthAPI[Authentication & Authorization API]
18 |
19 | HardwareAPI --> DB1[(Hardware Database)]
20 | VendorAPI --> DB2[(Vendor Database)]
21 | ProcurementAPI --> DB3[(Procurement Database)]
22 | AuthAPI --> DB4[(User Database)]
23 |
24 | class User user;
25 | class ITAM_UI ui;
26 | class AssetController assetController;
27 | class UserController userController;
28 | class AssetService assetService;
29 | class UserService userService;
30 | class HardwareRepository hardwareRepository;
31 | class VendorRepository vendorRepository;
32 | class ProcurementRepository procurementRepository;
33 | class UserRepository userRepository;
34 | class HardwareAPI hardwareAPI;
35 | class VendorAPI vendorAPI;
36 | class ProcurementAPI procurementAPI;
37 | class DB1 db1;
38 | class DB2 db2;
39 | class DB3 db3;
40 | class DB4 db4;
--------------------------------------------------------------------------------
/chapter_7/diagram2.mmd:
--------------------------------------------------------------------------------
1 | graph LR
2 | User[User] --> ITAM_UI[ITAM User Interface]
3 | ITAM_UI --> AssetController[Asset Controller]
4 | ITAM_UI --> UserController[User Controller]
5 |
6 | AssetController --> AssetService[Asset Service]
7 | UserController --> UserService[User Service]
8 |
9 | AssetService --> HardwareRepository[Hardware Repository]
10 | AssetService --> VendorRepository[Vendor Repository]
11 | AssetService --> ProcurementRepository[Procurement Repository]
12 | UserService --> UserRepository[User Repository]
13 |
14 | HardwareRepository --> HardwareAPI[Hardware API]
15 | VendorRepository --> VendorAPI[Vendor API]
16 | ProcurementRepository --> ProcurementAPI[Procurement API]
17 | UserRepository --> AuthAPI[Authentication & Authorization API]
18 |
19 | HardwareAPI --> DB1[(Hardware Database)]
20 | VendorAPI --> DB2[(Vendor Database)]
21 | ProcurementAPI --> DB3[(Procurement Database)]
22 | AuthAPI --> DB4[(User Database)]
23 |
24 | class User user;
25 | class ITAM_UI ui;
26 | class AssetController assetController;
27 | class UserController userController;
28 | class AssetService assetService;
29 | class UserService userService;
30 | class HardwareRepository hardwareRepository;
31 | class VendorRepository vendorRepository;
32 | class ProcurementRepository procurementRepository;
33 | class UserRepository userRepository;
34 | class HardwareAPI hardwareAPI;
35 | class VendorAPI vendorAPI;
36 | class ProcurementAPI procurementAPI;
37 | class DB1 db1;
38 | class DB2 db2;
39 | class DB3 db3;
40 | class DB4 db4;
--------------------------------------------------------------------------------
/chapter_4/itam/domain/line_of_business_statistics.py:
--------------------------------------------------------------------------------
1 | # Define a class called LineOfBusinessStatistics
2 | # with the following attributes
3 | # -line_of_business: LineOfBusiness
4 | # -total_cost: float
5 | # -total_depreciation: float
6 | # and with the following methods:
7 | # +__init__(self, line_of_business: LineOfBusiness, total_cost: float, total_depreciation: float)
8 | # +get_line_of_business(self) -> Department
9 | # +get_total_cost(self) -> float
10 | # +get_total_depreciation(self) -> float
11 | # +set_line_of_business(self, line_of_business: LineOfBusiness)
12 | # +set_total_cost(self, total_cost: float)
13 | # +set_total_depreciation(self, total_depreciation: float)
14 |
15 | class LineOfBusinessStatistics:
16 | def __init__(self, line_of_business, total_cost, total_depreciation):
17 | self.line_of_business = line_of_business
18 | self.total_cost = total_cost
19 | self.total_depreciation = total_depreciation
20 |
21 | def get_line_of_business(self):
22 | return self.line_of_business
23 |
24 | def get_total_cost(self):
25 | return self.total_cost
26 |
27 | def get_total_depreciation(self):
28 | return self.total_depreciation
29 |
30 | def set_line_of_business(self, line_of_business):
31 | self.line_of_business = line_of_business
32 |
33 | def set_total_cost(self, total_cost):
34 | self.total_cost = total_cost
35 |
36 | def set_total_depreciation(self, total_depreciation):
37 | self.total_depreciation = total_depreciation
--------------------------------------------------------------------------------
/chapter_5/itam/domain/line_of_business_statistics.py:
--------------------------------------------------------------------------------
1 | # Define a class called LineOfBusinessStatistics
2 | # with the following attributes
3 | # -line_of_business: LineOfBusiness
4 | # -total_cost: float
5 | # -total_depreciation: float
6 | # and with the following methods:
7 | # +__init__(self, line_of_business: LineOfBusiness, total_cost: float, total_depreciation: float)
8 | # +get_line_of_business(self) -> Department
9 | # +get_total_cost(self) -> float
10 | # +get_total_depreciation(self) -> float
11 | # +set_line_of_business(self, line_of_business: LineOfBusiness)
12 | # +set_total_cost(self, total_cost: float)
13 | # +set_total_depreciation(self, total_depreciation: float)
14 |
15 | class LineOfBusinessStatistics:
16 | def __init__(self, line_of_business, total_cost, total_depreciation):
17 | self.line_of_business = line_of_business
18 | self.total_cost = total_cost
19 | self.total_depreciation = total_depreciation
20 |
21 | def get_line_of_business(self):
22 | return self.line_of_business
23 |
24 | def get_total_cost(self):
25 | return self.total_cost
26 |
27 | def get_total_depreciation(self):
28 | return self.total_depreciation
29 |
30 | def set_line_of_business(self, line_of_business):
31 | self.line_of_business = line_of_business
32 |
33 | def set_total_cost(self, total_cost):
34 | self.total_cost = total_cost
35 |
36 | def set_total_depreciation(self, total_depreciation):
37 | self.total_depreciation = total_depreciation
--------------------------------------------------------------------------------
/chapter_6/itam/domain/line_of_business_statistics.py:
--------------------------------------------------------------------------------
1 | # Define a class called LineOfBusinessStatistics
2 | # with the following attributes
3 | # -line_of_business: LineOfBusiness
4 | # -total_cost: float
5 | # -total_depreciation: float
6 | # and with the following methods:
7 | # +__init__(self, line_of_business: LineOfBusiness, total_cost: float, total_depreciation: float)
8 | # +get_line_of_business(self) -> Department
9 | # +get_total_cost(self) -> float
10 | # +get_total_depreciation(self) -> float
11 | # +set_line_of_business(self, line_of_business: LineOfBusiness)
12 | # +set_total_cost(self, total_cost: float)
13 | # +set_total_depreciation(self, total_depreciation: float)
14 |
15 | class LineOfBusinessStatistics:
16 | def __init__(self, line_of_business, total_cost, total_depreciation):
17 | self.line_of_business = line_of_business
18 | self.total_cost = total_cost
19 | self.total_depreciation = total_depreciation
20 |
21 | def get_line_of_business(self):
22 | return self.line_of_business
23 |
24 | def get_total_cost(self):
25 | return self.total_cost
26 |
27 | def get_total_depreciation(self):
28 | return self.total_depreciation
29 |
30 | def set_line_of_business(self, line_of_business):
31 | self.line_of_business = line_of_business
32 |
33 | def set_total_cost(self, total_cost):
34 | self.total_cost = total_cost
35 |
36 | def set_total_depreciation(self, total_depreciation):
37 | self.total_depreciation = total_depreciation
--------------------------------------------------------------------------------
/chapter_7/itam/domain/line_of_business_statistics.py:
--------------------------------------------------------------------------------
1 | # Define a class called LineOfBusinessStatistics
2 | # with the following attributes
3 | # -line_of_business: LineOfBusiness
4 | # -total_cost: float
5 | # -total_depreciation: float
6 | # and with the following methods:
7 | # +__init__(self, line_of_business: LineOfBusiness, total_cost: float, total_depreciation: float)
8 | # +get_line_of_business(self) -> Department
9 | # +get_total_cost(self) -> float
10 | # +get_total_depreciation(self) -> float
11 | # +set_line_of_business(self, line_of_business: LineOfBusiness)
12 | # +set_total_cost(self, total_cost: float)
13 | # +set_total_depreciation(self, total_depreciation: float)
14 |
15 | class LineOfBusinessStatistics:
16 | def __init__(self, line_of_business, total_cost, total_depreciation):
17 | self.line_of_business = line_of_business
18 | self.total_cost = total_cost
19 | self.total_depreciation = total_depreciation
20 |
21 | def get_line_of_business(self):
22 | return self.line_of_business
23 |
24 | def get_total_cost(self):
25 | return self.total_cost
26 |
27 | def get_total_depreciation(self):
28 | return self.total_depreciation
29 |
30 | def set_line_of_business(self, line_of_business):
31 | self.line_of_business = line_of_business
32 |
33 | def set_total_cost(self, total_cost):
34 | self.total_cost = total_cost
35 |
36 | def set_total_depreciation(self, total_depreciation):
37 | self.total_depreciation = total_depreciation
--------------------------------------------------------------------------------
/chapter_6/itam/visitor/test_department_visitor.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from itam.visitor import DepartmentStatisticsVisitor
3 | from itam.domain.asset import Asset
4 | from itam.domain.department import Department
5 | from itam.domain.funding_details import FundingDetails
6 | from itam.domain.depreciation_strategy import StraightLineDepreciationStrategy, DoubleDecliningDepreciationStrategy
7 | from datetime import date
8 | from typing import List, Dict
9 |
10 | class TestDepartmentStatisticsVisitor(unittest.TestCase):
11 | def test_visit(self):
12 | visitor = DepartmentStatisticsVisitor()
13 | dept_it = Department(1, 'IT')
14 | dept_hr = Department(2, 'HR')
15 |
16 |
17 | funding_details1 = FundingDetails(0.33, { dept_it: 0.5, dept_hr: 0.5 }, StraightLineDepreciationStrategy(), None)
18 | funding_details2 = FundingDetails(0.25, { dept_it: 0.3, dept_hr: 0.7 }, DoubleDecliningDepreciationStrategy(), None)
19 |
20 | asset1 = Asset(id=1, name='Computer', status='In use', category='Hardware', cost=1000.0, useful_life=3, salvage_value=100.0, purchase_date=date.today(), locations=[], funding_details=funding_details1)
21 | asset2 = Asset(id=2, name='Printer', status='In use', category='Hardware', cost=500.0, useful_life=2,salvage_value=50.0, purchase_date=date.today(), locations=[], funding_details=funding_details2)
22 |
23 |
24 | #asset1.set_funding_details(funding_details1)
25 | #asset2.set_funding_details(funding_details2)
26 |
27 | visitor.visit(asset1)
28 | visitor.visit(asset2)
29 | self.assertEqual(visitor.get_total_cost(), 1500.0)
30 | self.assertEqual(visitor.get_total_depreciation(), 1300.0)
31 | #self.assertEqual(visitor.get_total_allocation(), 0.8)
--------------------------------------------------------------------------------
/chapter_7/itam/visitor/test_department_visitor.py:
--------------------------------------------------------------------------------
1 | import unittest
2 | from itam.visitor import DepartmentStatisticsVisitor
3 | from itam.domain.asset import Asset
4 | from itam.domain.department import Department
5 | from itam.domain.funding_details import FundingDetails
6 | from itam.domain.depreciation_strategy import StraightLineDepreciationStrategy, DoubleDecliningDepreciationStrategy
7 | from datetime import date
8 | from typing import List, Dict
9 |
10 | class TestDepartmentStatisticsVisitor(unittest.TestCase):
11 | def test_visit(self):
12 | visitor = DepartmentStatisticsVisitor()
13 | dept_it = Department(1, 'IT')
14 | dept_hr = Department(2, 'HR')
15 |
16 |
17 | funding_details1 = FundingDetails(0.33, { dept_it: 0.5, dept_hr: 0.5 }, StraightLineDepreciationStrategy(), None)
18 | funding_details2 = FundingDetails(0.25, { dept_it: 0.3, dept_hr: 0.7 }, DoubleDecliningDepreciationStrategy(), None)
19 |
20 | asset1 = Asset(id=1, name='Computer', status='In use', category='Hardware', cost=1000.0, useful_life=3, salvage_value=100.0, purchase_date=date.today(), locations=[], funding_details=funding_details1)
21 | asset2 = Asset(id=2, name='Printer', status='In use', category='Hardware', cost=500.0, useful_life=2,salvage_value=50.0, purchase_date=date.today(), locations=[], funding_details=funding_details2)
22 |
23 |
24 | #asset1.set_funding_details(funding_details1)
25 | #asset2.set_funding_details(funding_details2)
26 |
27 | visitor.visit(asset1)
28 | visitor.visit(asset2)
29 | self.assertEqual(visitor.get_total_cost(), 1500.0)
30 | self.assertEqual(visitor.get_total_depreciation(), 1300.0)
31 | #self.assertEqual(visitor.get_total_allocation(), 0.8)
--------------------------------------------------------------------------------
/chapter_4/itam/domain/factory/asset_factory.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetFactory
2 | # It should have the following methods:
3 | # +new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset
4 | # Create a function that will take a string and return a datetime
5 | # Use the AssetBuilder to create the Asset and use the FundingDetailsBuilder to create the FundingDetails
6 |
7 | from datetime import datetime
8 | from itam.domain.asset import Asset
9 | from itam.domain.hardware import Hardware
10 | from itam.domain.software import Software
11 | from itam.domain.funding_details import FundingDetails
12 | from itam.domain.builder.asset_builder import AssetBuilder, FundingDetailsBuilder
13 |
14 | class AssetFactory:
15 | def __init__(self):
16 | self.id = 0
17 |
18 | def date_from_string(self, date_string: str) -> datetime:
19 | return datetime.strptime(date_string, "%Y-%m-%d")
20 |
21 | def new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset:
22 | self.id += 1
23 | purchase_date = self.date_from_string(asset_purchase_date)
24 | a = AssetBuilder().with_id(self.id).with_name(asset_name).with_category(asset_type).with_cost(asset_cost).with_useful_life(useful_life).with_status("active").with_salvage_value(salvage_value).with_purchase_date(purchase_date).build()
25 | f = FundingDetailsBuilder().with_asset(a).with_depreciation_strategy(depreciation_strategy).with_depreciation_rate(depreciation_rate).build()
26 |
27 | a.funding_details = f
28 | return a
--------------------------------------------------------------------------------
/chapter_5/itam/domain/factory/asset_factory.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetFactory
2 | # It should have the following methods:
3 | # +new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset
4 | # Create a function that will take a string and return a datetime
5 | # Use the AssetBuilder to create the Asset and use the FundingDetailsBuilder to create the FundingDetails
6 |
7 | from datetime import datetime
8 | from itam.domain.asset import Asset
9 | from itam.domain.hardware import Hardware
10 | from itam.domain.software import Software
11 | from itam.domain.funding_details import FundingDetails
12 | from itam.domain.builder.asset_builder import AssetBuilder, FundingDetailsBuilder
13 |
14 | class AssetFactory:
15 | def __init__(self):
16 | self.id = 0
17 |
18 | def date_from_string(self, date_string: str) -> datetime:
19 | return datetime.strptime(date_string, "%Y-%m-%d")
20 |
21 | def new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset:
22 | self.id += 1
23 | purchase_date = self.date_from_string(asset_purchase_date)
24 | a = AssetBuilder().with_id(self.id).with_name(asset_name).with_category(asset_type).with_cost(asset_cost).with_useful_life(useful_life).with_status("active").with_salvage_value(salvage_value).with_purchase_date(purchase_date).build()
25 | f = FundingDetailsBuilder().with_asset(a).with_depreciation_strategy(depreciation_strategy).with_depreciation_rate(depreciation_rate).build()
26 |
27 | a.funding_details = f
28 | return a
--------------------------------------------------------------------------------
/chapter_6/itam/domain/factory/asset_factory.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetFactory
2 | # It should have the following methods:
3 | # +new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset
4 | # Create a function that will take a string and return a datetime
5 | # Use the AssetBuilder to create the Asset and use the FundingDetailsBuilder to create the FundingDetails
6 |
7 | from datetime import datetime
8 | from itam.domain.asset import Asset
9 | from itam.domain.hardware import Hardware
10 | from itam.domain.software import Software
11 | from itam.domain.funding_details import FundingDetails
12 | from itam.domain.builder.asset_builder import AssetBuilder, FundingDetailsBuilder
13 |
14 | class AssetFactory:
15 | def __init__(self):
16 | self.id = 0
17 |
18 | def date_from_string(self, date_string: str) -> datetime:
19 | return datetime.strptime(date_string, "%Y-%m-%d")
20 |
21 | def new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset:
22 | self.id += 1
23 | purchase_date = self.date_from_string(asset_purchase_date)
24 | a = AssetBuilder().with_id(self.id).with_name(asset_name).with_category(asset_type).with_cost(asset_cost).with_useful_life(useful_life).with_status("active").with_salvage_value(salvage_value).with_purchase_date(purchase_date).build()
25 | f = FundingDetailsBuilder().with_asset(a).with_depreciation_strategy(depreciation_strategy).with_depreciation_rate(depreciation_rate).build()
26 |
27 | a.funding_details = f
28 | return a
--------------------------------------------------------------------------------
/chapter_7/itam/domain/factory/asset_factory.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetFactory
2 | # It should have the following methods:
3 | # +new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset
4 | # Create a function that will take a string and return a datetime
5 | # Use the AssetBuilder to create the Asset and use the FundingDetailsBuilder to create the FundingDetails
6 |
7 | from datetime import datetime
8 | from itam.domain.asset import Asset
9 | from itam.domain.hardware import Hardware
10 | from itam.domain.software import Software
11 | from itam.domain.funding_details import FundingDetails
12 | from itam.domain.builder.asset_builder import AssetBuilder, FundingDetailsBuilder
13 |
14 | class AssetFactory:
15 | def __init__(self):
16 | self.id = 0
17 |
18 | def date_from_string(self, date_string: str) -> datetime:
19 | return datetime.strptime(date_string, "%Y-%m-%d")
20 |
21 | def new(self, asset_type: str, asset_name: str, asset_cost: float, useful_life: int, depreciation_strategy: str, depreciation_rate: float, salvage_value: float, asset_purchase_date: str) -> Asset:
22 | self.id += 1
23 | purchase_date = self.date_from_string(asset_purchase_date)
24 | a = AssetBuilder().with_id(self.id).with_name(asset_name).with_category(asset_type).with_cost(asset_cost).with_useful_life(useful_life).with_status("active").with_salvage_value(salvage_value).with_purchase_date(purchase_date).build()
25 | f = FundingDetailsBuilder().with_asset(a).with_depreciation_strategy(depreciation_strategy).with_depreciation_rate(depreciation_rate).build()
26 |
27 | a.funding_details = f
28 | return a
--------------------------------------------------------------------------------
/chapter_9/main.py:
--------------------------------------------------------------------------------
1 | import math
2 | import statistics
3 |
4 | def std_dev_chat_gpt_attempt_1(lst):
5 | # Step 1: Calculate the mean
6 | mean = sum(lst) / len(lst)
7 |
8 | # Step 2: Find squared differences
9 | squared_diffs = [(x - mean) ** 2 for x in lst]
10 |
11 | # Step 3: Compute the mean of squared differences
12 | mean_squared_diffs = sum(squared_diffs) / len(lst)
13 |
14 | # Step 4: Square root of the mean squared differences
15 | std_dev = mean_squared_diffs ** 0.5
16 |
17 | return std_dev
18 |
19 |
20 | def std_dev_llama_attempt_1(numbers):
21 | n = len(numbers)
22 | sum = 0
23 | for i in range(n):
24 | sum += numbers[i] ** 2
25 | return math.sqrt(sum / (n - 1))
26 |
27 |
28 | def std_dev_llama_attempt_2(numbers):
29 | sum_squared = 0
30 | mean = statistics.mean(numbers)
31 | for num in numbers:
32 | sum_squared += (num - mean) ** 2
33 |
34 | # Compute the square root of the sum of the squares to get the standard deviation
35 | std_dev = math.sqrt(sum_squared/len(numbers))
36 | return std_dev
37 |
38 |
39 | def std_dev_mistrail_attempt_1(numbers):
40 | mean = sum(numbers) / len(numbers)
41 |
42 | differences = [x - mean for x in numbers] # Subtract the mean from each number.
43 | squared_differences = [y * y for y in differences] # Square each difference.
44 |
45 | variance = sum(squared_differences) / len(numbers) # Calculate average of squared differences (variance).
46 | return math.sqrt(variance) # Return the standard deviation.
47 |
48 |
49 |
50 | if __name__ == '__main__':
51 | numbers = [1, 2, 3, 4, 5]
52 | print(std_dev_chat_gpt_attempt_1(numbers))
53 | print(std_dev_llama_attempt_1(numbers))
54 | print(std_dev_llama_attempt_2(numbers))
55 | print(std_dev_mistrail_attempt_1(numbers))
56 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/asset_manager.py:
--------------------------------------------------------------------------------
1 | from typing import List, Optional
2 | from asset import Asset
3 |
4 | class AssetManager:
5 | def __init__(self):
6 | self.assets: List[Asset] = []
7 |
8 | def add_asset(self, asset: Asset):
9 | self.assets.append(asset)
10 |
11 | def remove_asset(self, asset_id: str) -> bool:
12 | for asset in self.assets:
13 | if asset.asset_id == asset_id:
14 | self.assets.remove(asset)
15 | return True
16 | return False
17 |
18 | def get_asset_by_id(self, asset_id: str) -> Optional[Asset]:
19 | for asset in self.assets:
20 | if asset.asset_id == asset_id:
21 | return asset
22 | return None
23 |
24 | def assign_asset(self, asset_id: str, user: str) -> bool:
25 | for asset in self.assets:
26 | if asset.asset_id == asset_id:
27 | if asset.status == 'Available':
28 | asset.assign_to_user(user)
29 | return True
30 | else:
31 | return False
32 | return False
33 |
34 | def unassign_asset(self, asset_id: str) -> bool:
35 | for asset in self.assets:
36 | if asset.asset_id == asset_id:
37 | if asset.status == 'Assigned':
38 | asset.unassign()
39 | return True
40 | else:
41 | return False
42 | return False
43 |
44 | def get_available_assets(self) -> List[Asset]:
45 | return [asset for asset in self.assets if asset.status == 'Available']
46 |
47 | def get_assigned_assets(self) -> List[Asset]:
48 | return [asset for asset in self.assets if asset.status == 'Assigned']
49 |
50 | def get_all_assets(self) -> List[Asset]:
51 | return self.assets
52 |
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/asset_manager.py:
--------------------------------------------------------------------------------
1 | from typing import List, Optional
2 | from asset import Asset
3 |
4 | class AssetManager:
5 | def __init__(self):
6 | self.assets: List[Asset] = []
7 |
8 | def add_asset(self, asset: Asset):
9 | self.assets.append(asset)
10 |
11 | def remove_asset(self, asset_id: str) -> bool:
12 | for asset in self.assets:
13 | if asset.asset_id == asset_id:
14 | self.assets.remove(asset)
15 | return True
16 | return False
17 |
18 | def get_asset_by_id(self, asset_id: str) -> Optional[Asset]:
19 | for asset in self.assets:
20 | if asset.asset_id == asset_id:
21 | return asset
22 | return None
23 |
24 | def assign_asset(self, asset_id: str, user: str) -> bool:
25 | for asset in self.assets:
26 | if asset.asset_id == asset_id:
27 | if asset.status == 'Available':
28 | asset.assign_to_user(user)
29 | return True
30 | else:
31 | return False
32 | return False
33 |
34 | def unassign_asset(self, asset_id: str) -> bool:
35 | for asset in self.assets:
36 | if asset.asset_id == asset_id:
37 | if asset.status == 'Assigned':
38 | asset.unassign()
39 | return True
40 | else:
41 | return False
42 | return False
43 |
44 | def get_available_assets(self) -> List[Asset]:
45 | return [asset for asset in self.assets if asset.status == 'Available']
46 |
47 | def get_assigned_assets(self) -> List[Asset]:
48 | return [asset for asset in self.assets if asset.status == 'Assigned']
49 |
50 | def get_all_assets(self) -> List[Asset]:
51 | return self.assets
52 |
--------------------------------------------------------------------------------
/chapter_6/features/steps/steps.py:
--------------------------------------------------------------------------------
1 | from behave import given, when, then
2 | from itam.service.asset_manager import AssetManager
3 | from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
4 | from itam.domain.asset import Asset
5 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
6 | from unittest.mock import Mock
7 |
8 | @given('the Asset Manager is running')
9 | def step_impl(context):
10 | context.asset_repository = InMemoryAssetRepository()
11 | context.asset_location_mediator = Mock(spec=AssetLocationMediator)
12 | context.asset_manager = AssetManager(context.asset_repository, context.asset_location_mediator)
13 |
14 | @given('the InMemoryAssetRepository is initialized')
15 | def step_impl(context):
16 | pass
17 |
18 | @given('the AssetLocationMediator is mocked')
19 | def step_impl(context):
20 | pass
21 |
22 | @when('I create an asset with a cost of ${cost}')
23 | def step_impl(context, cost):
24 | asset = Asset(id=1, name='Test Asset 1', status='Available', category='Test Category', cost=float(cost), useful_life=5, salvage_value=0, purchase_date='2022-01-01', locations=['Test Location'], funding_details={'Test Funding': 1000})
25 | context.asset_manager.create(asset)
26 |
27 | @when('I create another asset with a cost of ${cost}')
28 | def step_impl(context, cost):
29 | asset = Asset(id=2, name='Test Asset 2', status='Available', category='Test Category', cost=float(cost), useful_life=5, salvage_value=0, purchase_date='2022-01-01', locations=['Test Location'], funding_details={'Test Funding': 1000})
30 | context.asset_manager.create(asset)
31 |
32 | @then('the total cost of all assets should be ${total_cost}')
33 | def step_impl(context, total_cost):
34 | assets = context.asset_manager.get_assets()
35 | assert sum(asset.cost for asset in assets) == float(total_cost)
--------------------------------------------------------------------------------
/chapter_7/features/steps/steps.py:
--------------------------------------------------------------------------------
1 | from behave import given, when, then
2 | from itam.service.asset_manager import AssetManager
3 | from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
4 | from itam.domain.asset import Asset
5 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
6 | from unittest.mock import Mock
7 |
8 | @given('the Asset Manager is running')
9 | def step_impl(context):
10 | context.asset_repository = InMemoryAssetRepository()
11 | context.asset_location_mediator = Mock(spec=AssetLocationMediator)
12 | context.asset_manager = AssetManager(context.asset_repository, context.asset_location_mediator)
13 |
14 | @given('the InMemoryAssetRepository is initialized')
15 | def step_impl(context):
16 | pass
17 |
18 | @given('the AssetLocationMediator is mocked')
19 | def step_impl(context):
20 | pass
21 |
22 | @when('I create an asset with a cost of ${cost}')
23 | def step_impl(context, cost):
24 | asset = Asset(id=1, name='Test Asset 1', status='Available', category='Test Category', cost=float(cost), useful_life=5, salvage_value=0, purchase_date='2022-01-01', locations=['Test Location'], funding_details={'Test Funding': 1000})
25 | context.asset_manager.create(asset)
26 |
27 | @when('I create another asset with a cost of ${cost}')
28 | def step_impl(context, cost):
29 | asset = Asset(id=2, name='Test Asset 2', status='Available', category='Test Category', cost=float(cost), useful_life=5, salvage_value=0, purchase_date='2022-01-01', locations=['Test Location'], funding_details={'Test Funding': 1000})
30 | context.asset_manager.create(asset)
31 |
32 | @then('the total cost of all assets should be ${total_cost}')
33 | def step_impl(context, total_cost):
34 | assets = context.asset_manager.get_assets()
35 | assert sum(asset.cost for asset in assets) == float(total_cost)
--------------------------------------------------------------------------------
/chapter_2/chatgpt-flask/asset.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | class Asset():
4 | def __init__(self, asset_id: str, asset_type: str, manufacturer: str, model: str, purchase_date: str, warranty_end_date: str, location: str):
5 | self.asset_id = asset_id
6 | self.asset_type = asset_type
7 | self.manufacturer = manufacturer
8 | self.model = model
9 | self.purchase_date = purchase_date
10 | self.warranty_end_date = warranty_end_date
11 | self.location = location
12 | self.assigned_to: Optional[str] = None
13 | self.status: str = 'Available'
14 |
15 | def assign_to_user(self, user: str):
16 | self.assigned_to = user
17 | self.status = 'Assigned'
18 |
19 | def unassign(self):
20 | self.assigned_to = None
21 | self.status = 'Available'
22 |
23 | def get_details(self):
24 | details = f"Asset ID: {self.asset_id}\n"
25 | details += f"Type: {self.asset_type}\n"
26 | details += f"Manufacturer: {self.manufacturer}\n"
27 | details += f"Model: {self.model}\n"
28 | details += f"Purchase Date: {self.purchase_date}\n"
29 | details += f"Warranty End Date: {self.warranty_end_date}\n"
30 | details += f"Location: {self.location}\n"
31 | details += f"Assigned To: {self.assigned_to}\n"
32 | details += f"Status: {self.status}\n"
33 | return details
34 |
35 | def to_dict(self):
36 | return {
37 | "asset_id": self.asset_id,
38 | "asset_type": self.asset_type,
39 | "manufacturer": self.manufacturer,
40 | "model": self.model,
41 | "purchase_date": self.purchase_date,
42 | "warranty_end_date": self.warranty_end_date,
43 | "location": self.location,
44 | "assigned_to": self.assigned_to,
45 | "status": self.status
46 | }
--------------------------------------------------------------------------------
/chapter_2/chatgpt-fastapi/asset.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | class Asset():
4 | def __init__(self, asset_id: str, asset_type: str, manufacturer: str, model: str, purchase_date: str, warranty_end_date: str, location: str):
5 | self.asset_id = asset_id
6 | self.asset_type = asset_type
7 | self.manufacturer = manufacturer
8 | self.model = model
9 | self.purchase_date = purchase_date
10 | self.warranty_end_date = warranty_end_date
11 | self.location = location
12 | self.assigned_to: Optional[str] = None
13 | self.status: str = 'Available'
14 |
15 | def assign_to_user(self, user: str):
16 | self.assigned_to = user
17 | self.status = 'Assigned'
18 |
19 | def unassign(self):
20 | self.assigned_to = None
21 | self.status = 'Available'
22 |
23 | def get_details(self):
24 | details = f"Asset ID: {self.asset_id}\n"
25 | details += f"Type: {self.asset_type}\n"
26 | details += f"Manufacturer: {self.manufacturer}\n"
27 | details += f"Model: {self.model}\n"
28 | details += f"Purchase Date: {self.purchase_date}\n"
29 | details += f"Warranty End Date: {self.warranty_end_date}\n"
30 | details += f"Location: {self.location}\n"
31 | details += f"Assigned To: {self.assigned_to}\n"
32 | details += f"Status: {self.status}\n"
33 | return details
34 |
35 | def to_dict(self):
36 | return {
37 | "asset_id": self.asset_id,
38 | "asset_type": self.asset_type,
39 | "manufacturer": self.manufacturer,
40 | "model": self.model,
41 | "purchase_date": self.purchase_date,
42 | "warranty_end_date": self.warranty_end_date,
43 | "location": self.location,
44 | "assigned_to": self.assigned_to,
45 | "status": self.status
46 | }
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/api/asset_model.py:
--------------------------------------------------------------------------------
1 | # Define a pydantic model for AssetIn
2 | # It should have the following attributes:
3 | # name: str
4 | # asset_type: str
5 | # department: str
6 | # depreciation_strategy: str
7 | # useful_life: int
8 | # unit_cost: float
9 | # depreciation_rate: float
10 | # salvage_value: float
11 |
12 | # Define a pydantic model for AssetOut
13 | # It should have the following attributes:
14 | # id: int
15 | # name: str
16 | # asset_type: str
17 | # department: str
18 | # depreciation_strategy: str
19 | # useful_life: int
20 | # unit_cost: float
21 | # depreciation_rate: float
22 | # salvage_value: float
23 | # It should have a method that transforms an Asset into an AssetOut
24 |
25 | from pydantic import BaseModel
26 | from itam.domain.asset import Asset
27 |
28 | class AssetIn(BaseModel):
29 | name: str
30 | asset_type: str
31 | department: str
32 | depreciation_strategy: str
33 | useful_life: int
34 | unit_cost: float
35 | depreciation_rate: float
36 | salvage_value: float
37 | purchase_date: str
38 |
39 | class AssetOut(BaseModel):
40 | id: int
41 | name: str
42 | asset_type: str
43 | depreciation_strategy: str
44 | useful_life: int
45 | unit_cost: float
46 | depreciation_rate: float
47 | salvage_value: float
48 | purchase_date: str
49 |
50 | @staticmethod
51 | def from_asset(asset: Asset) -> AssetOut:
52 | return AssetOut(
53 | id=asset.id,
54 | name=asset.name,
55 | asset_type=asset.category,
56 | depreciation_strategy=str(asset.funding_details.depreciation_strategy),
57 | useful_life=asset.useful_life,
58 | unit_cost=asset.cost,
59 | depreciation_rate=asset.funding_details.depreciation_rate,
60 | salvage_value=asset.salvage_value,
61 | purchase_date=asset.purchase_date.strftime("%Y-%m-%d"),
62 | )
--------------------------------------------------------------------------------
/chapter_5/main.py:
--------------------------------------------------------------------------------
1 | # Importing the necessary modules and packages
2 | # Instantiating the necessary objects and components, such as the FastAPI application and database connection
3 | # Configuring the application settings and environment variables
4 | # Mounting the HTTP controllers and endpoints to the FastAPI application
5 | # Starting the server and running the application
6 | from pyspark.sql import SparkSession
7 | from fastapi import FastAPI
8 | from itam.infrastructure.api.asset_controller import AssetController
9 | #from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
10 | from itam.infrastructure.repository.sqlalchemy_asset_repository import SQLAlchemyAssetRepository
11 | from itam.infrastructure.database.database_connection import DatabaseConnection
12 | from itam.service.asset_manager import AssetManager
13 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
14 | from itam.infrastructure.adapters.asset_rest_adapter import AssetRestAdapter
15 | from itam.infrastructure.consumers.asset_location_kafka_consumer import AssetLocationKafkaConsumer
16 | from itam.infrastructure.adapters.asset_location_spark_adapter import AssetLocationSparkAdapter
17 | import uvicorn
18 |
19 | app = FastAPI()
20 | session = DatabaseConnection().get_session()
21 | #repository = InMemoryAssetRepository()
22 | repository = SQLAlchemyAssetRepository(session)
23 | mediator = AssetLocationMediator()
24 | asset_manager = AssetManager(repository, mediator)
25 | asset_rest_adapter = AssetRestAdapter(asset_manager)
26 | asset_controller = AssetController(asset_rest_adapter)
27 |
28 | app.include_router(asset_controller.get_router())
29 |
30 | #consumer = AssetLocationKafkaConsumer(mediator)
31 | #consumer.start_consumer()
32 |
33 | spark_adapter = AssetLocationSparkAdapter()
34 | spark_adapter.run()
35 | app.include_router(asset_controller.get_router())
36 |
37 | if __name__ == '__main__':
38 | uvicorn.run(app, host='0.0.0.0', port=8000)
--------------------------------------------------------------------------------
/chapter_7/main.py:
--------------------------------------------------------------------------------
1 | # Importing the necessary modules and packages
2 | # Instantiating the necessary objects and components, such as the FastAPI application and database connection
3 | # Configuring the application settings and environment variables
4 | # Mounting the HTTP controllers and endpoints to the FastAPI application
5 | # Starting the server and running the application
6 | from pyspark.sql import SparkSession
7 | from fastapi import FastAPI
8 | from itam.infrastructure.api.asset_controller import AssetController
9 | #from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
10 | from itam.infrastructure.repository.sqlalchemy_asset_repository import SQLAlchemyAssetRepository
11 | from itam.infrastructure.database.database_connection import DatabaseConnection
12 | from itam.service.asset_manager import AssetManager
13 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
14 | from itam.infrastructure.adapters.asset_rest_adapter import AssetRestAdapter
15 | from itam.infrastructure.consumers.asset_location_kafka_consumer import AssetLocationKafkaConsumer
16 | from itam.infrastructure.adapters.asset_location_spark_adapter import AssetLocationSparkAdapter
17 | import uvicorn
18 |
19 | app = FastAPI()
20 | session = DatabaseConnection().get_session()
21 | #repository = InMemoryAssetRepository()
22 | repository = SQLAlchemyAssetRepository(session)
23 | mediator = AssetLocationMediator()
24 | asset_manager = AssetManager(repository, mediator)
25 | asset_rest_adapter = AssetRestAdapter(asset_manager)
26 | asset_controller = AssetController(asset_rest_adapter)
27 |
28 | app.include_router(asset_controller.get_router())
29 |
30 | #consumer = AssetLocationKafkaConsumer(mediator)
31 | #consumer.start_consumer()
32 |
33 | #spark_adapter = AssetLocationSparkAdapter()
34 | #spark_adapter.run()
35 | app.include_router(asset_controller.get_router())
36 |
37 | if __name__ == '__main__':
38 | uvicorn.run(app, host='0.0.0.0', port=8000)
--------------------------------------------------------------------------------
/chapter_6/main.py:
--------------------------------------------------------------------------------
1 | # Importing the necessary modules and packages
2 | # Instantiating the necessary objects and components, such as the FastAPI application and database connection
3 | # Configuring the application settings and environment variables
4 | # Mounting the HTTP controllers and endpoints to the FastAPI application
5 | # Starting the server and running the application
6 | #from pyspark.sql import SparkSession
7 | from fastapi import FastAPI
8 | from itam.infrastructure.api.asset_controller import AssetController
9 | #from itam.infrastructure.repository.in_memory_asset_repository import InMemoryAssetRepository
10 | from itam.infrastructure.repository.sqlalchemy_asset_repository import SQLAlchemyAssetRepository
11 | from itam.infrastructure.database.database_connection import DatabaseConnection
12 | from itam.service.asset_manager import AssetManager
13 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
14 | from itam.infrastructure.adapters.asset_rest_adapter import AssetRestAdapter
15 | from itam.infrastructure.consumers.asset_location_kafka_consumer import AssetLocationKafkaConsumer
16 | from itam.infrastructure.adapters.asset_location_spark_adapter import AssetLocationSparkAdapter
17 | import uvicorn
18 |
19 | #app = FastAPI()
20 | #session = DatabaseConnection().get_session()
21 | #repository = InMemoryAssetRepository()
22 | #repository = SQLAlchemyAssetRepository(session)
23 | #mediator = AssetLocationMediator()
24 | #asset_manager = AssetManager(repository, mediator)
25 | #asset_rest_adapter = AssetRestAdapter(asset_manager)
26 | #asset_controller = AssetController(asset_rest_adapter)
27 |
28 | #app.include_router(asset_controller.get_router())
29 |
30 | #consumer = AssetLocationKafkaConsumer(mediator)
31 | #consumer.start_consumer()
32 |
33 | #spark_adapter = AssetLocationSparkAdapter()
34 | #spark_adapter.run()
35 | #app.include_router(asset_controller.get_router())
36 |
37 | #if __name__ == '__main__':
38 | # uvicorn.run(app, host='0.0.0.0', port=8000)
39 |
40 |
41 |
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/api/asset_model.py:
--------------------------------------------------------------------------------
1 | # Define a pydantic model for AssetIn
2 | # It should have the following attributes:
3 | # name: str
4 | # asset_type: str
5 | # department: str
6 | # depreciation_strategy: str
7 | # useful_life: int
8 | # unit_cost: float
9 | # depreciation_rate: float
10 | # salvage_value: float
11 |
12 | # Define a pydantic model for AssetOut
13 | # It should have the following attributes:
14 | # id: int
15 | # name: str
16 | # asset_type: str
17 | # department: str
18 | # depreciation_strategy: str
19 | # useful_life: int
20 | # unit_cost: float
21 | # depreciation_rate: float
22 | # salvage_value: float
23 | # It should have a method that transforms an Asset into an AssetOut
24 |
25 | from pydantic import BaseModel
26 | from itam.domain.asset import Asset
27 |
28 | class AssetIn(BaseModel):
29 | name: str
30 | asset_type: str
31 | department: str
32 | depreciation_strategy: str
33 | useful_life: int
34 | unit_cost: float
35 | depreciation_rate: float
36 | salvage_value: float
37 | purchase_date: str
38 |
39 | class AssetOut(BaseModel):
40 | id: int
41 | name: str
42 | asset_type: str
43 | depreciation_strategy: str
44 | useful_life: int
45 | unit_cost: float
46 | depreciation_rate: float
47 | salvage_value: float
48 | purchase_date: str
49 |
50 | @staticmethod
51 | def from_asset(asset: Asset) -> AssetOut:
52 | return AssetOut(
53 | id=asset.id,
54 | name=asset.name,
55 | asset_type=asset.category,
56 | depreciation_strategy = str(asset.funding_details.depreciation_strategy) if asset.funding_details is not None else "",
57 | useful_life=asset.useful_life,
58 | unit_cost=asset.cost,
59 | depreciation_rate=asset.funding_details.depreciation_rate if asset.funding_details is not None else 0.0,
60 | salvage_value=asset.salvage_value,
61 | purchase_date=asset.purchase_date.strftime("%Y-%m-%d"),
62 | )
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/api/asset_model.py:
--------------------------------------------------------------------------------
1 | # Define a pydantic model for AssetIn
2 | # It should have the following attributes:
3 | # name: str
4 | # asset_type: str
5 | # department: str
6 | # depreciation_strategy: str
7 | # useful_life: int
8 | # unit_cost: float
9 | # depreciation_rate: float
10 | # salvage_value: float
11 |
12 | # Define a pydantic model for AssetOut
13 | # It should have the following attributes:
14 | # id: int
15 | # name: str
16 | # asset_type: str
17 | # department: str
18 | # depreciation_strategy: str
19 | # useful_life: int
20 | # unit_cost: float
21 | # depreciation_rate: float
22 | # salvage_value: float
23 | # It should have a method that transforms an Asset into an AssetOut
24 |
25 | from pydantic import BaseModel
26 | from itam.domain.asset import Asset
27 |
28 | class AssetIn(BaseModel):
29 | name: str
30 | asset_type: str
31 | department: str
32 | depreciation_strategy: str
33 | useful_life: int
34 | unit_cost: float
35 | depreciation_rate: float
36 | salvage_value: float
37 | purchase_date: str
38 |
39 | class AssetOut(BaseModel):
40 | id: int
41 | name: str
42 | asset_type: str
43 | depreciation_strategy: str
44 | useful_life: int
45 | unit_cost: float
46 | depreciation_rate: float
47 | salvage_value: float
48 | purchase_date: str
49 |
50 | @staticmethod
51 | def from_asset(asset: Asset) -> AssetOut:
52 | return AssetOut(
53 | id=asset.id,
54 | name=asset.name,
55 | asset_type=asset.category,
56 | depreciation_strategy = str(asset.funding_details.depreciation_strategy) if asset.funding_details is not None else "",
57 | useful_life=asset.useful_life,
58 | unit_cost=asset.cost,
59 | depreciation_rate=asset.funding_details.depreciation_rate if asset.funding_details is not None else 0.0,
60 | salvage_value=asset.salvage_value,
61 | purchase_date=asset.purchase_date.strftime("%Y-%m-%d"),
62 | )
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/api/asset_model.py:
--------------------------------------------------------------------------------
1 | # Define a pydantic model for AssetIn
2 | # It should have the following attributes:
3 | # name: str
4 | # asset_type: str
5 | # department: str
6 | # depreciation_strategy: str
7 | # useful_life: int
8 | # unit_cost: float
9 | # depreciation_rate: float
10 | # salvage_value: float
11 |
12 | # Define a pydantic model for AssetOut
13 | # It should have the following attributes:
14 | # id: int
15 | # name: str
16 | # asset_type: str
17 | # department: str
18 | # depreciation_strategy: str
19 | # useful_life: int
20 | # unit_cost: float
21 | # depreciation_rate: float
22 | # salvage_value: float
23 | # It should have a method that transforms an Asset into an AssetOut
24 |
25 | from pydantic import BaseModel
26 | from itam.domain.asset import Asset
27 |
28 | class AssetIn(BaseModel):
29 | name: str
30 | asset_type: str
31 | department: str
32 | depreciation_strategy: str
33 | useful_life: int
34 | unit_cost: float
35 | depreciation_rate: float
36 | salvage_value: float
37 | purchase_date: str
38 |
39 | class AssetOut(BaseModel):
40 | id: int
41 | name: str
42 | asset_type: str
43 | depreciation_strategy: str
44 | useful_life: int
45 | unit_cost: float
46 | depreciation_rate: float
47 | salvage_value: float
48 | purchase_date: str
49 |
50 | @staticmethod
51 | def from_asset(asset: Asset) -> AssetOut:
52 | return AssetOut(
53 | id=asset.id,
54 | name=asset.name,
55 | asset_type=asset.category,
56 | depreciation_strategy = str(asset.funding_details.depreciation_strategy) if asset.funding_details is not None else "",
57 | useful_life=asset.useful_life,
58 | unit_cost=asset.cost,
59 | depreciation_rate=asset.funding_details.depreciation_rate if asset.funding_details is not None else 0.0,
60 | salvage_value=asset.salvage_value,
61 | purchase_date=asset.purchase_date.strftime("%Y-%m-%d"),
62 | )
--------------------------------------------------------------------------------
/chapter_5/itam/service/asset_manager.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetManager
2 | # with CRUD operations for Asset
3 | # and a method to notify observers whenever an asset is created, updated or deleted
4 | # The AssetManager should accpet an instance of the BaseRepository[Asset] for data access and CRUD operations on Asset objects.
5 | # Implement methods for creating, reading, updating, and deleting assets using the AssetRepository instance.
6 | # Please include type hints for the input parameters and return values.
7 | # The methods should be named create, read, update, get_assets, and delete.
8 |
9 | from itam.domain.asset import Asset
10 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
11 | from itam.domain.events.asset_location_updated import AssetLocationUpdated
12 | from itam.infrastructure.repository.base_repository import BaseRepository
13 |
14 | class AssetManager:
15 | def __init__(self, base_repository: BaseRepository[Asset], mediator: AssetLocationMediator):
16 | self._repository = base_repository
17 | self.mediator = mediator
18 | self.mediator.register_handler(AssetLocationUpdated, self.update_asset_location)
19 |
20 | def create(self, asset: Asset) -> Asset:
21 | self._repository.create(asset)
22 | return asset
23 |
24 | def read(self, asset_id: int) -> Asset:
25 | return self._repository.read(asset_id)
26 |
27 | def update(self, asset: Asset) -> Asset:
28 | self._repository.update(asset)
29 | return asset
30 |
31 | def get_assets(self) -> list[Asset]:
32 | return self._repository.get_entities()
33 |
34 | def delete(self, asset_id: int) -> None:
35 | self._repository.delete(asset_id)
36 |
37 | def update_asset_location(self, event: AssetLocationUpdated) -> None:
38 | asset = self.read(event.asset_id)
39 | asset.add_location(event.latitude, event.longitude, event.timestamp)
40 | #self.update(asset)
41 | print(f"Asset {asset.id} location updated to {event.latitude}, {event.longitude} at {event.timestamp}")
--------------------------------------------------------------------------------
/chapter_6/itam/service/asset_manager.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetManager
2 | # with CRUD operations for Asset
3 | # and a method to notify observers whenever an asset is created, updated or deleted
4 | # The AssetManager should accpet an instance of the BaseRepository[Asset] for data access and CRUD operations on Asset objects.
5 | # Implement methods for creating, reading, updating, and deleting assets using the AssetRepository instance.
6 | # Please include type hints for the input parameters and return values.
7 | # The methods should be named create, read, update, get_assets, and delete.
8 |
9 | from itam.domain.asset import Asset
10 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
11 | from itam.domain.events.asset_location_updated import AssetLocationUpdated
12 | from itam.infrastructure.repository.base_repository import BaseRepository
13 |
14 | class AssetManager:
15 | def __init__(self, base_repository: BaseRepository[Asset], mediator: AssetLocationMediator):
16 | self._repository = base_repository
17 | self.mediator = mediator
18 | self.mediator.register_handler(AssetLocationUpdated, self.update_asset_location)
19 |
20 | def create(self, asset: Asset) -> Asset:
21 | self._repository.create(asset)
22 | return asset
23 |
24 | def read(self, asset_id: int) -> Asset:
25 | return self._repository.read(asset_id)
26 |
27 | def update(self, asset: Asset) -> Asset:
28 | self._repository.update(asset)
29 | return asset
30 |
31 | def get_assets(self) -> list[Asset]:
32 | return self._repository.get_entities()
33 |
34 | def delete(self, asset_id: int) -> None:
35 | self._repository.delete(asset_id)
36 |
37 | def update_asset_location(self, event: AssetLocationUpdated) -> None:
38 | asset = self.read(event.asset_id)
39 | asset.add_location(event.latitude, event.longitude, event.timestamp)
40 | #self.update(asset)
41 | print(f"Asset {asset.id} location updated to {event.latitude}, {event.longitude} at {event.timestamp}")
--------------------------------------------------------------------------------
/chapter_7/itam/service/asset_manager.py:
--------------------------------------------------------------------------------
1 | # Define a class called AssetManager
2 | # with CRUD operations for Asset
3 | # and a method to notify observers whenever an asset is created, updated or deleted
4 | # The AssetManager should accpet an instance of the BaseRepository[Asset] for data access and CRUD operations on Asset objects.
5 | # Implement methods for creating, reading, updating, and deleting assets using the AssetRepository instance.
6 | # Please include type hints for the input parameters and return values.
7 | # The methods should be named create, read, update, get_assets, and delete.
8 |
9 | from itam.domain.asset import Asset
10 | from itam.infrastructure.mediators.asset_location_mediator import AssetLocationMediator
11 | from itam.domain.events.asset_location_updated import AssetLocationUpdated
12 | from itam.infrastructure.repository.base_repository import BaseRepository
13 |
14 | class AssetManager:
15 | def __init__(self, base_repository: BaseRepository[Asset], mediator: AssetLocationMediator):
16 | self._repository = base_repository
17 | self.mediator = mediator
18 | self.mediator.register_handler(AssetLocationUpdated, self.update_asset_location)
19 |
20 | def create(self, asset: Asset) -> Asset:
21 | self._repository.create(asset)
22 | return asset
23 |
24 | def read(self, asset_id: int) -> Asset:
25 | return self._repository.read(asset_id)
26 |
27 | def update(self, asset: Asset) -> Asset:
28 | self._repository.update(asset)
29 | return asset
30 |
31 | def get_assets(self) -> list[Asset]:
32 | return self._repository.get_entities()
33 |
34 | def delete(self, asset_id: int) -> None:
35 | self._repository.delete(asset_id)
36 |
37 | def update_asset_location(self, event: AssetLocationUpdated) -> None:
38 | asset = self.read(event.asset_id)
39 | asset.add_location(event.latitude, event.longitude, event.timestamp)
40 | #self.update(asset)
41 | print(f"Asset {asset.id} location updated to {event.latitude}, {event.longitude} at {event.timestamp}")
--------------------------------------------------------------------------------
/chapter_4/itam/domain/asset.py:
--------------------------------------------------------------------------------
1 | # Define a class named Asset
2 | # It should have the following attributes:
3 | # - id: int
4 | # - name: str
5 | # - status: str
6 | # - category: str
7 | # - cost: float
8 | # - useful_life: float
9 | # - salvage_value: float
10 | # - funding_details: FundingDetails
11 | #
12 | # The attributes cannot be None and cannot be added after construction
13 | # However, we should be able to access the attributes using methods
14 |
15 | from dataclasses import dataclass
16 | from datetime import date
17 |
18 | @dataclass
19 | class Asset():
20 | id: int
21 | name: str
22 | status: str
23 | category: str
24 | cost: float
25 | useful_life: float
26 | salvage_value: float
27 | purchase_date: date
28 |
29 | def __post_init__(self):
30 | if self.id is None:
31 | raise TypeError("ID cannot be None")
32 | if self.name is None:
33 | raise TypeError("Name cannot be None")
34 | if self.status is None:
35 | raise TypeError("Status cannot be None")
36 | if self.category is None:
37 | raise TypeError("Category cannot be None")
38 | if self.cost is None:
39 | raise TypeError("Cost cannot be None")
40 | if self.useful_life is None:
41 | raise TypeError("Useful life cannot be None")
42 | if self.salvage_value is None:
43 | raise TypeError("Salvage value cannot be None")
44 |
45 | def get_id(self):
46 | return self.id
47 |
48 | def get_name(self):
49 | return self.name
50 |
51 | def get_status(self):
52 | return self.status
53 |
54 | def get_category(self):
55 | return self.category
56 |
57 | def get_cost(self):
58 | return self.cost
59 |
60 | def get_useful_life(self):
61 | return self.useful_life
62 |
63 | def get_salvage_value(self):
64 | return self.salvage_value
65 |
66 | def set_funding_details(self, funding_details):
67 | if (self.funding_details is None):
68 | self.funding_details = funding_details
69 |
70 | def get_funding_details(self):
71 | return self.funding_details
--------------------------------------------------------------------------------
/chapter_4/itam/infrastructure/adapters/asset_database_adapter.py:
--------------------------------------------------------------------------------
1 | # Create a class called AssetDatabaseAdapter that implements the DatabasePort interface
2 | # This class will handle the database operations using a SQLAlchemy session.
3 | # The adapter should interact with Asset.
4 | # Implement methods for creating, getting, updating, and deleting assets, as well as listing all assets.
5 | # The adapter should not interact with the domain model directly.
6 | # The get_asset method should return a single Asset based off of the asset_id parameter.
7 | # The get_assets method should return a list of all assets from the database.
8 | # The create method should take an Asset object as a parameter and create a new row in the database as well as return the new Asset object.
9 | # The update method should take an asset_id and an Asset object as parameters and update the row in the database that matches the asset_id.
10 | # The delete method should take an asset_id as a parameter and delete the row in the database that matches the asset_id.
11 | # Create, update, and detele methods should return the updated Asset object.
12 |
13 | from itam.domain.asset import Asset
14 | from itam.infrastructure.ports.asset_database_port import AssetDatabasePort
15 | from sqlalchemy.orm import Session
16 |
17 | class AssetDatabaseAdapter(AssetDatabasePort):
18 | def __init__(self, session: Session):
19 | self._session = session
20 |
21 | def get_asset(self, asset_id: int) -> Asset:
22 | return self._session.query(Asset).filter(Asset.id == asset_id).first()
23 |
24 | def get_assets(self) -> list:
25 | return self._session.query(Asset).all()
26 |
27 | def create(self, asset: Asset) -> Asset:
28 | self._session.add(asset)
29 | self._session.commit()
30 | return asset
31 |
32 | def update(self, asset_id: int, asset: Asset) -> Asset:
33 | self._session.query(Asset).filter(Asset.id == asset_id).update(asset)
34 | self._session.commit()
35 | return asset
36 |
37 | def delete(self, asset_id: int) -> None:
38 | self._session.query(Asset).filter(Asset.id == asset_id).delete()
39 | self._session.commit()
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/chapter_5/itam/infrastructure/adapters/asset_database_adapter.py:
--------------------------------------------------------------------------------
1 | # Create a class called AssetDatabaseAdapter that implements the DatabasePort interface
2 | # This class will handle the database operations using a SQLAlchemy session.
3 | # The adapter should interact with Asset.
4 | # Implement methods for creating, getting, updating, and deleting assets, as well as listing all assets.
5 | # The adapter should not interact with the domain model directly.
6 | # The get_asset method should return a single Asset based off of the asset_id parameter.
7 | # The get_assets method should return a list of all assets from the database.
8 | # The create method should take an Asset object as a parameter and create a new row in the database as well as return the new Asset object.
9 | # The update method should take an asset_id and an Asset object as parameters and update the row in the database that matches the asset_id.
10 | # The delete method should take an asset_id as a parameter and delete the row in the database that matches the asset_id.
11 | # Create, update, and detele methods should return the updated Asset object.
12 |
13 | from itam.domain.asset import Asset
14 | from itam.infrastructure.ports.asset_database_port import AssetDatabasePort
15 | from sqlalchemy.orm import Session
16 |
17 | class AssetDatabaseAdapter(AssetDatabasePort):
18 | def __init__(self, session: Session):
19 | self._session = session
20 |
21 | def get_asset(self, asset_id: int) -> Asset:
22 | return self._session.query(Asset).filter(Asset.id == asset_id).first()
23 |
24 | def get_assets(self) -> list:
25 | return self._session.query(Asset).all()
26 |
27 | def create(self, asset: Asset) -> Asset:
28 | self._session.add(asset)
29 | self._session.commit()
30 | return asset
31 |
32 | def update(self, asset_id: int, asset: Asset) -> Asset:
33 | self._session.query(Asset).filter(Asset.id == asset_id).update(asset)
34 | self._session.commit()
35 | return asset
36 |
37 | def delete(self, asset_id: int) -> None:
38 | self._session.query(Asset).filter(Asset.id == asset_id).delete()
39 | self._session.commit()
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/chapter_6/itam/infrastructure/adapters/asset_database_adapter.py:
--------------------------------------------------------------------------------
1 | # Create a class called AssetDatabaseAdapter that implements the DatabasePort interface
2 | # This class will handle the database operations using a SQLAlchemy session.
3 | # The adapter should interact with Asset.
4 | # Implement methods for creating, getting, updating, and deleting assets, as well as listing all assets.
5 | # The adapter should not interact with the domain model directly.
6 | # The get_asset method should return a single Asset based off of the asset_id parameter.
7 | # The get_assets method should return a list of all assets from the database.
8 | # The create method should take an Asset object as a parameter and create a new row in the database as well as return the new Asset object.
9 | # The update method should take an asset_id and an Asset object as parameters and update the row in the database that matches the asset_id.
10 | # The delete method should take an asset_id as a parameter and delete the row in the database that matches the asset_id.
11 | # Create, update, and detele methods should return the updated Asset object.
12 |
13 | from itam.domain.asset import Asset
14 | from itam.infrastructure.ports.asset_database_port import AssetDatabasePort
15 | from sqlalchemy.orm import Session
16 |
17 | class AssetDatabaseAdapter(AssetDatabasePort):
18 | def __init__(self, session: Session):
19 | self._session = session
20 |
21 | def get_asset(self, asset_id: int) -> Asset:
22 | return self._session.query(Asset).filter(Asset.id == asset_id).first()
23 |
24 | def get_assets(self) -> list:
25 | return self._session.query(Asset).all()
26 |
27 | def create(self, asset: Asset) -> Asset:
28 | self._session.add(asset)
29 | self._session.commit()
30 | return asset
31 |
32 | def update(self, asset_id: int, asset: Asset) -> Asset:
33 | self._session.query(Asset).filter(Asset.id == asset_id).update(asset)
34 | self._session.commit()
35 | return asset
36 |
37 | def delete(self, asset_id: int) -> None:
38 | self._session.query(Asset).filter(Asset.id == asset_id).delete()
39 | self._session.commit()
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/chapter_7/itam/infrastructure/adapters/asset_database_adapter.py:
--------------------------------------------------------------------------------
1 | # Create a class called AssetDatabaseAdapter that implements the DatabasePort interface
2 | # This class will handle the database operations using a SQLAlchemy session.
3 | # The adapter should interact with Asset.
4 | # Implement methods for creating, getting, updating, and deleting assets, as well as listing all assets.
5 | # The adapter should not interact with the domain model directly.
6 | # The get_asset method should return a single Asset based off of the asset_id parameter.
7 | # The get_assets method should return a list of all assets from the database.
8 | # The create method should take an Asset object as a parameter and create a new row in the database as well as return the new Asset object.
9 | # The update method should take an asset_id and an Asset object as parameters and update the row in the database that matches the asset_id.
10 | # The delete method should take an asset_id as a parameter and delete the row in the database that matches the asset_id.
11 | # Create, update, and detele methods should return the updated Asset object.
12 |
13 | from itam.domain.asset import Asset
14 | from itam.infrastructure.ports.asset_database_port import AssetDatabasePort
15 | from sqlalchemy.orm import Session
16 |
17 | class AssetDatabaseAdapter(AssetDatabasePort):
18 | def __init__(self, session: Session):
19 | self._session = session
20 |
21 | def get_asset(self, asset_id: int) -> Asset:
22 | return self._session.query(Asset).filter(Asset.id == asset_id).first()
23 |
24 | def get_assets(self) -> list:
25 | return self._session.query(Asset).all()
26 |
27 | def create(self, asset: Asset) -> Asset:
28 | self._session.add(asset)
29 | self._session.commit()
30 | return asset
31 |
32 | def update(self, asset_id: int, asset: Asset) -> Asset:
33 | self._session.query(Asset).filter(Asset.id == asset_id).update(asset)
34 | self._session.commit()
35 | return asset
36 |
37 | def delete(self, asset_id: int) -> None:
38 | self._session.query(Asset).filter(Asset.id == asset_id).delete()
39 | self._session.commit()
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/chapter_4/itam/domain/software.py:
--------------------------------------------------------------------------------
1 | # create a class called Software, which is an instance of Asset. The Software entity has the following attributes:
2 | # - id: int,
3 | # - name: str
4 | # - version: str
5 | # - license_key: str
6 | # - vendor: str
7 | # - status: str
8 | # - department_percentages: Dict[Department, float]
9 | # none of the attributes can be None
10 | # define two methods specific to the Software entity: get_department_cost() and calculate_depreciation(). The get_department_cost() method calculates the cost of the asset for a given department, based on the percentages assigned to each department in the get_department_cost attribute. The calculate_depreciation() method calculates the depreciation of the asset using a given depreciation strategy.
11 | # automatically generates special methods for a class that are commonly used for data objects
12 |
13 | from typing import Dict
14 | from dataclasses import dataclass
15 | from itam.domain.department import Department
16 | from itam.domain.depreciation_strategy import DepreciationStrategy
17 | from itam.domain.asset import Asset
18 |
19 | @dataclass
20 | class Software(Asset):
21 | name: str
22 | version: str
23 | license_key: str
24 | vendor: str
25 | status: str
26 | department_percentages: Dict[Department, float]
27 |
28 | def __post_init__(self):
29 | if self.name is None:
30 | raise TypeError("Name cannot be None")
31 | if self.version is None:
32 | raise TypeError("Version cannot be None")
33 | if self.license_key is None:
34 | raise TypeError("License Key cannot be None")
35 | if self.vendor is None:
36 | raise TypeError("Vendor cannot be None")
37 | if self.status is None:
38 | raise TypeError("Status cannot be None")
39 | if self.department_percentages is None:
40 | raise TypeError("Line of Department Percentages cannot be None")
41 |
42 | def get_department_cost(self, department: Department) -> float:
43 | return self.cost * self.department_percentages[department]
44 |
45 | def calculate_depreciation(self, depreciation_strategy: DepreciationStrategy) -> float:
46 | return depreciation_strategy.calculate_depreciation(self.cost, self.purchase_date)
--------------------------------------------------------------------------------
/chapter_5/itam/domain/software.py:
--------------------------------------------------------------------------------
1 | # create a class called Software, which is an instance of Asset. The Software entity has the following attributes:
2 | # - id: int,
3 | # - name: str
4 | # - version: str
5 | # - license_key: str
6 | # - vendor: str
7 | # - status: str
8 | # - department_percentages: Dict[Department, float]
9 | # none of the attributes can be None
10 | # define two methods specific to the Software entity: get_department_cost() and calculate_depreciation(). The get_department_cost() method calculates the cost of the asset for a given department, based on the percentages assigned to each department in the get_department_cost attribute. The calculate_depreciation() method calculates the depreciation of the asset using a given depreciation strategy.
11 | # automatically generates special methods for a class that are commonly used for data objects
12 |
13 | from typing import Dict
14 | from dataclasses import dataclass
15 | from itam.domain.department import Department
16 | from itam.domain.depreciation_strategy import DepreciationStrategy
17 | from itam.domain.asset import Asset
18 |
19 | @dataclass
20 | class Software(Asset):
21 | name: str
22 | version: str
23 | license_key: str
24 | vendor: str
25 | status: str
26 | department_percentages: Dict[Department, float]
27 |
28 | def __post_init__(self):
29 | if self.name is None:
30 | raise TypeError("Name cannot be None")
31 | if self.version is None:
32 | raise TypeError("Version cannot be None")
33 | if self.license_key is None:
34 | raise TypeError("License Key cannot be None")
35 | if self.vendor is None:
36 | raise TypeError("Vendor cannot be None")
37 | if self.status is None:
38 | raise TypeError("Status cannot be None")
39 | if self.department_percentages is None:
40 | raise TypeError("Line of Department Percentages cannot be None")
41 |
42 | def get_department_cost(self, department: Department) -> float:
43 | return self.cost * self.department_percentages[department]
44 |
45 | def calculate_depreciation(self, depreciation_strategy: DepreciationStrategy) -> float:
46 | return depreciation_strategy.calculate_depreciation(self.cost, self.purchase_date)
--------------------------------------------------------------------------------
/chapter_6/itam/domain/software.py:
--------------------------------------------------------------------------------
1 | # create a class called Software, which is an instance of Asset. The Software entity has the following attributes:
2 | # - id: int,
3 | # - name: str
4 | # - version: str
5 | # - license_key: str
6 | # - vendor: str
7 | # - status: str
8 | # - department_percentages: Dict[Department, float]
9 | # none of the attributes can be None
10 | # define two methods specific to the Software entity: get_department_cost() and calculate_depreciation(). The get_department_cost() method calculates the cost of the asset for a given department, based on the percentages assigned to each department in the get_department_cost attribute. The calculate_depreciation() method calculates the depreciation of the asset using a given depreciation strategy.
11 | # automatically generates special methods for a class that are commonly used for data objects
12 |
13 | from typing import Dict
14 | from dataclasses import dataclass
15 | from itam.domain.department import Department
16 | from itam.domain.depreciation_strategy import DepreciationStrategy
17 | from itam.domain.asset import Asset
18 |
19 | @dataclass
20 | class Software(Asset):
21 | name: str
22 | version: str
23 | license_key: str
24 | vendor: str
25 | status: str
26 | department_percentages: Dict[Department, float]
27 |
28 | def __post_init__(self):
29 | if self.name is None:
30 | raise TypeError("Name cannot be None")
31 | if self.version is None:
32 | raise TypeError("Version cannot be None")
33 | if self.license_key is None:
34 | raise TypeError("License Key cannot be None")
35 | if self.vendor is None:
36 | raise TypeError("Vendor cannot be None")
37 | if self.status is None:
38 | raise TypeError("Status cannot be None")
39 | if self.department_percentages is None:
40 | raise TypeError("Line of Department Percentages cannot be None")
41 |
42 | def get_department_cost(self, department: Department) -> float:
43 | return self.cost * self.department_percentages[department]
44 |
45 | def calculate_depreciation(self, depreciation_strategy: DepreciationStrategy) -> float:
46 | return depreciation_strategy.calculate_depreciation(self.cost, self.purchase_date)
--------------------------------------------------------------------------------
/chapter_7/itam/domain/software.py:
--------------------------------------------------------------------------------
1 | # create a class called Software, which is an instance of Asset. The Software entity has the following attributes:
2 | # - id: int,
3 | # - name: str
4 | # - version: str
5 | # - license_key: str
6 | # - vendor: str
7 | # - status: str
8 | # - department_percentages: Dict[Department, float]
9 | # none of the attributes can be None
10 | # define two methods specific to the Software entity: get_department_cost() and calculate_depreciation(). The get_department_cost() method calculates the cost of the asset for a given department, based on the percentages assigned to each department in the get_department_cost attribute. The calculate_depreciation() method calculates the depreciation of the asset using a given depreciation strategy.
11 | # automatically generates special methods for a class that are commonly used for data objects
12 |
13 | from typing import Dict
14 | from dataclasses import dataclass
15 | from itam.domain.department import Department
16 | from itam.domain.depreciation_strategy import DepreciationStrategy
17 | from itam.domain.asset import Asset
18 |
19 | @dataclass
20 | class Software(Asset):
21 | name: str
22 | version: str
23 | license_key: str
24 | vendor: str
25 | status: str
26 | department_percentages: Dict[Department, float]
27 |
28 | def __post_init__(self):
29 | if self.name is None:
30 | raise TypeError("Name cannot be None")
31 | if self.version is None:
32 | raise TypeError("Version cannot be None")
33 | if self.license_key is None:
34 | raise TypeError("License Key cannot be None")
35 | if self.vendor is None:
36 | raise TypeError("Vendor cannot be None")
37 | if self.status is None:
38 | raise TypeError("Status cannot be None")
39 | if self.department_percentages is None:
40 | raise TypeError("Line of Department Percentages cannot be None")
41 |
42 | def get_department_cost(self, department: Department) -> float:
43 | return self.cost * self.department_percentages[department]
44 |
45 | def calculate_depreciation(self, depreciation_strategy: DepreciationStrategy) -> float:
46 | return depreciation_strategy.calculate_depreciation(self.cost, self.purchase_date)
--------------------------------------------------------------------------------
/chapter_4/itam/domain/depreciation_strategy.py:
--------------------------------------------------------------------------------
1 | # Define an interface called DepreciationStrategy.
2 | # It should have four concrete implementations of the interface: StraightLineDepreciationStrategy, DecliningBalanceDepreciationStrategy, DoubleDecliningDepreciationStrategy, and NoDepreciationStrategy.
3 | # Each implementation overrides the calculate_depreciation() method to provide a specific way of calculating depreciation for an asset based on its funding details.
4 | # The calculate_depreciation() method should take a FundingDetails object as a parameter and return a float value representing the depreciation amount.
5 | # NoDepreciationStrategy should return 0 for all assets.
6 | # The other three strategies should return the depreciation amount based on the following formulas:
7 | # - Straight Line: (cost - salvage value) / useful_life
8 | # - Declining Balance: cost * (1-rate/100)^(current_year - purchase_year)
9 | # - Double Declining: Declining Balance * 2
10 |
11 | from abc import ABC, abstractmethod
12 | from itam.domain.asset import Asset
13 | from math import pow
14 | from datetime import datetime
15 |
16 | class DepreciationStrategy(ABC):
17 | @abstractmethod
18 | def calculate_depreciation(self, asset: Asset) -> float:
19 | pass
20 |
21 | class StraightLineDepreciationStrategy(DepreciationStrategy):
22 | def calculate_depreciation(self, asset: Asset) -> float:
23 | cost = asset.get_cost()
24 | salvage_value = asset.get_salvage_value()
25 | useful_life = asset.get_useful_life()
26 | return (cost - salvage_value) / useful_life
27 |
28 | class DecliningBalanceDepreciationStrategy(DepreciationStrategy):
29 | def calculate_depreciation(self, asset: Asset) -> float:
30 | cost = asset.get_cost()
31 | depreciation_rate = asset.get_depreciation_rate()
32 | return cost * pow(1 - (depreciation_rate / 100), datetime.now().year - asset.get_purchase_date().year)
33 |
34 | class DoubleDecliningDepreciationStrategy(DepreciationStrategy):
35 | def calculate_depreciation(self, asset: Asset) -> float:
36 | return DecliningBalanceDepreciationStrategy().calculate_depreciation(asset) * 2
37 |
38 | class NoDepreciationStrategy(DepreciationStrategy):
39 | def calculate_depreciation(self, asset: Asset) -> float:
40 | return 0
--------------------------------------------------------------------------------
/chapter_5/itam/domain/depreciation_strategy.py:
--------------------------------------------------------------------------------
1 | # Define an interface called DepreciationStrategy.
2 | # It should have four concrete implementations of the interface: StraightLineDepreciationStrategy, DecliningBalanceDepreciationStrategy, DoubleDecliningDepreciationStrategy, and NoDepreciationStrategy.
3 | # Each implementation overrides the calculate_depreciation() method to provide a specific way of calculating depreciation for an asset based on its funding details.
4 | # The calculate_depreciation() method should take a FundingDetails object as a parameter and return a float value representing the depreciation amount.
5 | # NoDepreciationStrategy should return 0 for all assets.
6 | # The other three strategies should return the depreciation amount based on the following formulas:
7 | # - Straight Line: (cost - salvage value) / useful_life
8 | # - Declining Balance: cost * (1-rate/100)^(current_year - purchase_year)
9 | # - Double Declining: Declining Balance * 2
10 |
11 | from abc import ABC, abstractmethod
12 | from itam.domain.asset import Asset
13 | from math import pow
14 | from datetime import datetime
15 |
16 | class DepreciationStrategy(ABC):
17 | @abstractmethod
18 | def calculate_depreciation(self, asset: Asset) -> float:
19 | pass
20 |
21 | class StraightLineDepreciationStrategy(DepreciationStrategy):
22 | def calculate_depreciation(self, asset: Asset) -> float:
23 | cost = asset.get_cost()
24 | salvage_value = asset.get_salvage_value()
25 | useful_life = asset.get_useful_life()
26 | return (cost - salvage_value) / useful_life
27 |
28 | class DecliningBalanceDepreciationStrategy(DepreciationStrategy):
29 | def calculate_depreciation(self, asset: Asset) -> float:
30 | cost = asset.get_cost()
31 | depreciation_rate = asset.get_depreciation_rate()
32 | return cost * pow(1 - (depreciation_rate / 100), datetime.now().year - asset.get_purchase_date().year)
33 |
34 | class DoubleDecliningDepreciationStrategy(DepreciationStrategy):
35 | def calculate_depreciation(self, asset: Asset) -> float:
36 | return DecliningBalanceDepreciationStrategy().calculate_depreciation(asset) * 2
37 |
38 | class NoDepreciationStrategy(DepreciationStrategy):
39 | def calculate_depreciation(self, asset: Asset) -> float:
40 | return 0
--------------------------------------------------------------------------------
/chapter_4/itam/domain/hardware.py:
--------------------------------------------------------------------------------
1 | # Define a class called Hardware, which is an instance of Asset.
2 | # The Hardware entity has the following attributes:
3 | # - serial_number: str,
4 | # - location: Location,
5 | # - warranty_expiration_date: date,
6 | # - notes: str
7 | # - maintenance_schedules: List[MaintenanceSchedule]
8 | # - warranty: Warranty
9 | # - retirement_date: date
10 | # - retirement_reason: str
11 | # - usage_statistics: UsageStatistics
12 | # - budget: Budget
13 | # The attributes can be None and the class should have a constructor that takes all attributes as parameters.
14 | # The attributes should be private and the class should have accessor methods for all attributes.
15 |
16 | from datetime import datetime
17 | from itam.domain.asset import Asset
18 | from itam.domain.location import Location
19 | from itam.domain.warranty import Warranty
20 | from itam.domain.maintenance_schedule import MaintenanceSchedule
21 | from itam.domain.usage_statistics import UsageStatistics
22 | from itam.domain.budget import Budget
23 |
24 | class Hardware(Asset):
25 | serial_number: str
26 | location: Location
27 | warranty_expiration_date: datetime
28 | notes: str
29 | maintenance_schedules: list[MaintenanceSchedule]
30 | warranty: Warranty
31 | retirement_date: datetime
32 | retirement_reason: str
33 | usage_statistics: UsageStatistics
34 | budget: Budget
35 |
36 | def get_serial_number(self) -> str:
37 | return self.serial_number
38 |
39 | def get_location(self) -> Location:
40 | return self.location
41 |
42 | def get_warranty_expiration_date(self) -> datetime:
43 | return self.warranty_expiration_date
44 |
45 | def get_notes(self) -> str:
46 | return self.notes
47 |
48 | def get_maintenance_schedules(self) -> list[MaintenanceSchedule]:
49 | return self.maintenance_schedules
50 |
51 | def get_warranty(self) -> Warranty:
52 | return self.warranty
53 |
54 | def get_retirement_date(self) -> datetime:
55 | return self.retirement_date
56 |
57 | def get_retirement_reason(self) -> str:
58 | return self.retirement_reason
59 |
60 | def get_usage_statistics(self) -> UsageStatistics:
61 | return self.usage_statistics
62 |
63 | def get_budget(self) -> Budget:
64 | return self.budget
65 |
66 |
--------------------------------------------------------------------------------
/chapter_5/itam/domain/hardware.py:
--------------------------------------------------------------------------------
1 | # Define a class called Hardware, which is an instance of Asset.
2 | # The Hardware entity has the following attributes:
3 | # - serial_number: str,
4 | # - location: Location,
5 | # - warranty_expiration_date: date,
6 | # - notes: str
7 | # - maintenance_schedules: List[MaintenanceSchedule]
8 | # - warranty: Warranty
9 | # - retirement_date: date
10 | # - retirement_reason: str
11 | # - usage_statistics: UsageStatistics
12 | # - budget: Budget
13 | # The attributes can be None and the class should have a constructor that takes all attributes as parameters.
14 | # The attributes should be private and the class should have accessor methods for all attributes.
15 |
16 | from datetime import datetime
17 | from itam.domain.asset import Asset
18 | #from itam.domain.location import Location
19 | from itam.domain.warranty import Warranty
20 | from itam.domain.maintenance_schedule import MaintenanceSchedule
21 | from itam.domain.usage_statistics import UsageStatistics
22 | from itam.domain.budget import Budget
23 |
24 | class Hardware(Asset):
25 | serial_number: str
26 | #location: Location
27 | warranty_expiration_date: datetime
28 | notes: str
29 | maintenance_schedules: list[MaintenanceSchedule]
30 | warranty: Warranty
31 | retirement_date: datetime
32 | retirement_reason: str
33 | usage_statistics: UsageStatistics
34 | budget: Budget
35 |
36 | def get_serial_number(self) -> str:
37 | return self.serial_number
38 |
39 | #def get_location(self) -> Location:
40 | # return self.location
41 |
42 | def get_warranty_expiration_date(self) -> datetime:
43 | return self.warranty_expiration_date
44 |
45 | def get_notes(self) -> str:
46 | return self.notes
47 |
48 | def get_maintenance_schedules(self) -> list[MaintenanceSchedule]:
49 | return self.maintenance_schedules
50 |
51 | def get_warranty(self) -> Warranty:
52 | return self.warranty
53 |
54 | def get_retirement_date(self) -> datetime:
55 | return self.retirement_date
56 |
57 | def get_retirement_reason(self) -> str:
58 | return self.retirement_reason
59 |
60 | def get_usage_statistics(self) -> UsageStatistics:
61 | return self.usage_statistics
62 |
63 | def get_budget(self) -> Budget:
64 | return self.budget
65 |
66 |
--------------------------------------------------------------------------------
/chapter_6/itam/domain/hardware.py:
--------------------------------------------------------------------------------
1 | # Define a class called Hardware, which is an instance of Asset.
2 | # The Hardware entity has the following attributes:
3 | # - serial_number: str,
4 | # - location: Location,
5 | # - warranty_expiration_date: date,
6 | # - notes: str
7 | # - maintenance_schedules: List[MaintenanceSchedule]
8 | # - warranty: Warranty
9 | # - retirement_date: date
10 | # - retirement_reason: str
11 | # - usage_statistics: UsageStatistics
12 | # - budget: Budget
13 | # The attributes can be None and the class should have a constructor that takes all attributes as parameters.
14 | # The attributes should be private and the class should have accessor methods for all attributes.
15 |
16 | from datetime import datetime
17 | from itam.domain.asset import Asset
18 | #from itam.domain.location import Location
19 | from itam.domain.warranty import Warranty
20 | from itam.domain.maintenance_schedule import MaintenanceSchedule
21 | from itam.domain.usage_statistics import UsageStatistics
22 | from itam.domain.budget import Budget
23 |
24 | class Hardware(Asset):
25 | serial_number: str
26 | #location: Location
27 | warranty_expiration_date: datetime
28 | notes: str
29 | maintenance_schedules: list[MaintenanceSchedule]
30 | warranty: Warranty
31 | retirement_date: datetime
32 | retirement_reason: str
33 | usage_statistics: UsageStatistics
34 | budget: Budget
35 |
36 | def get_serial_number(self) -> str:
37 | return self.serial_number
38 |
39 | #def get_location(self) -> Location:
40 | # return self.location
41 |
42 | def get_warranty_expiration_date(self) -> datetime:
43 | return self.warranty_expiration_date
44 |
45 | def get_notes(self) -> str:
46 | return self.notes
47 |
48 | def get_maintenance_schedules(self) -> list[MaintenanceSchedule]:
49 | return self.maintenance_schedules
50 |
51 | def get_warranty(self) -> Warranty:
52 | return self.warranty
53 |
54 | def get_retirement_date(self) -> datetime:
55 | return self.retirement_date
56 |
57 | def get_retirement_reason(self) -> str:
58 | return self.retirement_reason
59 |
60 | def get_usage_statistics(self) -> UsageStatistics:
61 | return self.usage_statistics
62 |
63 | def get_budget(self) -> Budget:
64 | return self.budget
65 |
66 |
--------------------------------------------------------------------------------
/chapter_7/itam/domain/hardware.py:
--------------------------------------------------------------------------------
1 | # Define a class called Hardware, which is an instance of Asset.
2 | # The Hardware entity has the following attributes:
3 | # - serial_number: str,
4 | # - location: Location,
5 | # - warranty_expiration_date: date,
6 | # - notes: str
7 | # - maintenance_schedules: List[MaintenanceSchedule]
8 | # - warranty: Warranty
9 | # - retirement_date: date
10 | # - retirement_reason: str
11 | # - usage_statistics: UsageStatistics
12 | # - budget: Budget
13 | # The attributes can be None and the class should have a constructor that takes all attributes as parameters.
14 | # The attributes should be private and the class should have accessor methods for all attributes.
15 |
16 | from datetime import datetime
17 | from itam.domain.asset import Asset
18 | #from itam.domain.location import Location
19 | from itam.domain.warranty import Warranty
20 | from itam.domain.maintenance_schedule import MaintenanceSchedule
21 | from itam.domain.usage_statistics import UsageStatistics
22 | from itam.domain.budget import Budget
23 |
24 | class Hardware(Asset):
25 | serial_number: str
26 | #location: Location
27 | warranty_expiration_date: datetime
28 | notes: str
29 | maintenance_schedules: list[MaintenanceSchedule]
30 | warranty: Warranty
31 | retirement_date: datetime
32 | retirement_reason: str
33 | usage_statistics: UsageStatistics
34 | budget: Budget
35 |
36 | def get_serial_number(self) -> str:
37 | return self.serial_number
38 |
39 | #def get_location(self) -> Location:
40 | # return self.location
41 |
42 | def get_warranty_expiration_date(self) -> datetime:
43 | return self.warranty_expiration_date
44 |
45 | def get_notes(self) -> str:
46 | return self.notes
47 |
48 | def get_maintenance_schedules(self) -> list[MaintenanceSchedule]:
49 | return self.maintenance_schedules
50 |
51 | def get_warranty(self) -> Warranty:
52 | return self.warranty
53 |
54 | def get_retirement_date(self) -> datetime:
55 | return self.retirement_date
56 |
57 | def get_retirement_reason(self) -> str:
58 | return self.retirement_reason
59 |
60 | def get_usage_statistics(self) -> UsageStatistics:
61 | return self.usage_statistics
62 |
63 | def get_budget(self) -> Budget:
64 | return self.budget
65 |
66 |
--------------------------------------------------------------------------------