Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Veiculos Via Montadora
Backend
Commits
6e74d79f
Commit
6e74d79f
authored
1 year ago
by
Guilherme de Moraes Machado Pereira Silva
Committed by
Arthur Sudbrack Ibarra
1 year ago
Browse files
Options
Download
Email Patches
Plain Diff
E01-US01-pdf-receive
parent
b295ea0c
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
app/api/controllers/veiculo_controller.py
+29
-0
app/api/controllers/veiculo_controller.py
app/api/models/car.py
+0
-13
app/api/models/car.py
app/api/models/veiculo.py
+30
-0
app/api/models/veiculo.py
app/api/repositories/veiculo_repository.py
+39
-0
app/api/repositories/veiculo_repository.py
app/api/routers/car_router.py
+0
-50
app/api/routers/car_router.py
app/api/routers/veiculo_router.py
+63
-0
app/api/routers/veiculo_router.py
app/api/services/car_service.py
+0
-29
app/api/services/car_service.py
app/api/services/veiculo_service.py
+37
-0
app/api/services/veiculo_service.py
app/main.py
+12
-2
app/main.py
app/test/test_cars.py
+13
-13
app/test/test_cars.py
poetry.lock
+16
-1
poetry.lock
pyproject.toml
+1
-0
pyproject.toml
with
240 additions
and
108 deletions
+240
-108
app/api/controllers/
car
_controller.py
→
app/api/controllers/
veiculo
_controller.py
View file @
6e74d79f
# from fastapi import HTTPException
from
app.api.services.car_service
import
CarService
from
app.api.models.car
import
Car
# Controller class.
#
# This class is responsible for handling the requests and responses.
# It will call the service layer to get the data and return the response.
# It will also handle any exceptions that are raised by the service layer.
class
CarController
:
def
__init__
(
self
,
service
:
CarService
):
self
.
_service
=
service
def
get_all
(
self
):
# Call the service to get the cars.
pass
def
get_by_id
(
self
,
car_id
:
int
):
pass
def
create
(
self
,
car_data
:
Car
):
pass
def
update
(
self
,
car_id
:
int
,
car_data
:
Car
):
pass
def
delete
(
self
,
car_id
:
int
):
pass
# from fastapi import HTTPException
from
app.api.services.veiculo_service
import
VeiculoService
from
app.api.models.veiculo
import
Veiculo
# Controller class.
#
# This class is responsible for handling the requests and responses.
# It will call the service layer to get the data and return the response.
# It will also handle any exceptions that are raised by the service layer.
class
VeiculoController
:
def
__init__
(
self
,
service
:
VeiculoService
):
self
.
_service
=
service
def
get_all
(
self
)
->
list
[
Veiculo
]:
return
self
.
_service
.
get_all
()
def
get_by_sigla
(
self
,
sigla
:
str
)
->
Veiculo
:
return
self
.
_service
.
get_by_sigla
(
sigla
)
def
create
(
self
,
veiculo_data
:
Veiculo
)
->
None
:
self
.
_service
.
create
(
veiculo_data
)
def
update
(
self
,
sigla
:
int
,
veiculo_data
:
Veiculo
)
->
None
:
self
.
_service
.
update
(
sigla
,
veiculo_data
)
def
delete
(
self
,
sigla
:
int
)
->
None
:
self
.
_service
.
delete
(
sigla
)
This diff is collapsed.
Click to expand it.
app/api/models/car.py
deleted
100644 → 0
View file @
b295ea0c
from
pydantic
import
BaseModel
from
typing
import
Optional
# Car model.
#
# This model represents a car object in the database.
# Add any fields that you want to store in the database.
class
Car
(
BaseModel
):
id
:
str
name
:
str
description
:
Optional
[
str
]
=
""
This diff is collapsed.
Click to expand it.
app/api/models/veiculo.py
0 → 100644
View file @
6e74d79f
from
pydantic
import
BaseModel
class
Combustivel
(
BaseModel
):
potencia
:
str
tipo_combustivel
:
str
class
Motor
(
BaseModel
):
cilindradas
:
str
nro_cilindradas
:
str
combustiveis
:
list
[
Combustivel
]
class
Veiculo
(
BaseModel
):
desc_cat
:
str
renavam_desc
:
str
sigla
:
str
pacote_def_modelo
:
str
versao
:
str
ano
:
str
marca
:
str
linha
:
str
motor
:
Motor
carga
:
str
num_passag
:
str
num_portas
:
str
num_renavam
:
str
status
:
str
pdf_names
:
list
[
str
]
This diff is collapsed.
Click to expand it.
app/api/repositories/
car
_repository.py
→
app/api/repositories/
veiculo
_repository.py
View file @
6e74d79f
from
app.api.models.car
import
Car
from
pymongo.database
import
Database
# CarRepository class
#
# This class is responsible for accessing the database to get the cars.
# It will be called by the service layer to get the data.
# It will also handle any exceptions that are raised by the database.
CAR_COLLECTION
=
"cars"
class
CarRepository
:
def
__init__
(
self
,
database
:
Database
):
self
.
_database
=
database
def
get_all
(
self
):
# Access the database to get the cars.
# Reminder: Transform the data that comes as a cursor into a list of Car objects.
# Ex: list(db.find())
pass
def
get_by_id
(
self
,
car_id
:
int
):
pass
def
create
(
self
,
car_data
:
Car
):
# On create we need to convert car_data to dict and then insert it into the database.
# Ex: db.insert_one(car_data.dict())
pass
def
update
(
self
,
car_id
:
int
,
car_data
:
Car
):
pass
def
delete
(
self
,
car_id
:
int
):
pass
from
app.api.models.veiculo
import
Veiculo
from
pymongo.database
import
Database
from
pymongo.results
import
UpdateResult
,
DeleteResult
# CarRepository class
#
# This class is responsible for accessing the database to get the cars.
# It will be called by the service layer to get the data.
# It will also handle any exceptions that are raised by the database.
VEICULO_COLLECTION
=
"Veiculos"
class
VeiculoRepository
:
def
__init__
(
self
,
database
:
Database
):
self
.
_collection
=
database
[
VEICULO_COLLECTION
]
def
get_all
(
self
)
->
list
[
Veiculo
]:
veiculos
=
[]
veiculos_dict
=
list
(
self
.
_collection
.
find
())
for
veiculo
in
veiculos_dict
:
veiculos
.
append
(
Veiculo
.
parse_obj
(
veiculo
))
return
veiculos
def
get_by_sigla
(
self
,
sigla
:
str
)
->
Veiculo
:
veiculo_dict
=
self
.
_collection
.
find_one
({
"sigla"
:
sigla
})
return
Veiculo
.
parse_obj
(
veiculo_dict
)
def
create
(
self
,
veiculo_data
:
Veiculo
):
# On create we need to convert car_data to dict and then insert it into the database.
# Ex: db.insert_one(car_data.dict())
self
.
_collection
.
insert_one
(
veiculo_data
.
dict
())
def
update
(
self
,
sigla
:
int
,
veiculo_data
:
Veiculo
)
->
UpdateResult
:
return
self
.
_collection
.
update_one
({
"sigla"
:
sigla
},
{
"$set"
:
veiculo_data
.
dict
()})
def
delete
(
self
,
sigla
:
int
)
->
DeleteResult
:
return
self
.
_collection
.
delete_one
({
"sigla"
:
sigla
})
This diff is collapsed.
Click to expand it.
app/api/routers/car_router.py
deleted
100644 → 0
View file @
b295ea0c
from
fastapi
import
APIRouter
from
app.api.models.car
import
Car
from
app.database.mongo
import
get_database
from
app.api.repositories.car_repository
import
CarRepository
from
app.api.services.car_service
import
CarService
from
app.api.controllers.car_controller
import
CarController
# Car router.
#
# Here we define the routes for the car resource.
# We call the CarController to handle the requests.
# These variables start with an underscore to indicate that they are 'private'.
# They are not meant to be used outside of this file.
_database
=
get_database
()
_repository
=
CarRepository
(
_database
)
_service
=
CarService
(
_repository
)
_car_controller
=
CarController
(
_service
)
_car_router
=
APIRouter
(
prefix
=
"/cars"
)
@
_car_router
.
get
(
"/"
)
def
get_cars
():
return
_car_controller
.
get_all
()
@
_car_router
.
get
(
"/{car_id}"
)
def
get_car
(
car_id
:
str
):
return
_car_controller
.
get_by_id
(
car_id
)
@
_car_router
.
post
(
"/"
)
def
create_car
(
car_data
:
Car
):
_car_controller
.
create
(
car_data
)
@
_car_router
.
put
(
"/{car_id}"
)
def
update_car
(
car_id
:
str
,
car_data
:
Car
):
return
_car_controller
.
update
(
car_id
,
car_data
)
@
_car_router
.
delete
(
"/{car_id}"
)
def
delete_car
(
car_id
:
str
):
return
_car_controller
.
delete
(
car_id
)
# This function is used to get the car router.
# It is used in the main.py file to include the router in the FastAPI app.
def
get_car_router
()
->
APIRouter
:
return
_car_router
This diff is collapsed.
Click to expand it.
app/api/routers/veiculo_router.py
0 → 100644
View file @
6e74d79f
from
fastapi
import
APIRouter
,
HTTPException
from
pydantic
import
ValidationError
from
fastapi
import
FastAPI
,
File
,
UploadFile
from
app.api.models.veiculo
import
Veiculo
from
app.database.mongo
import
get_database
from
app.api.repositories.veiculo_repository
import
VeiculoRepository
from
app.api.services.veiculo_service
import
VeiculoService
from
app.api.controllers.veiculo_controller
import
VeiculoController
# Car router.
#
# Here we define the routes for the car resource.
# We call the CarController to handle the requests.
# These variables start with an underscore to indicate that they are 'private'.
# They are not meant to be used outside of this file.
_database
=
get_database
()
_repository
=
VeiculoRepository
(
_database
)
_service
=
VeiculoService
(
_repository
)
_veiculo_controller
=
VeiculoController
(
_service
)
_veiculo_router
=
APIRouter
(
prefix
=
"/veiculos"
)
@
_veiculo_router
.
get
(
"/"
)
def
get_veiculos
()
->
list
[
Veiculo
]:
return
_veiculo_controller
.
get_all
()
@
_veiculo_router
.
get
(
"/{sigla}"
)
def
get_veiculo
(
sigla
:
str
)
->
Veiculo
:
return
_veiculo_controller
.
get_by_sigla
(
sigla
)
@
_veiculo_router
.
post
(
"/"
)
def
create_veiculo
(
veiculo_data
:
Veiculo
)
->
None
:
_veiculo_controller
.
create
(
veiculo_data
)
@
_veiculo_router
.
put
(
"/{sigla}"
)
def
update_veiculo
(
sigla
:
str
,
veiculo_data
:
Veiculo
)
->
None
:
_veiculo_controller
.
update
(
sigla
,
veiculo_data
)
@
_veiculo_router
.
delete
(
"/{sigla}"
)
def
delete_veiculo
(
sigla
:
str
)
->
None
:
_veiculo_controller
.
delete
(
sigla
)
# It contains a single endpoint that receives the PDF file.
@
_veiculo_router
.
post
(
"/pdf/"
)
def
create_upload_file
(
form_data
:
UploadFile
=
File
(...)):
contents
=
form_data
.
file
.
read
()
# This function read the pdf bytes.
contents
# Here we have the pdf bytes saved in the application memory. The ideia is to call a funtion which will handle the pdf bytes and extract them.
name
:
str
name
=
form_data
.
filename
# This is the file name in memory. It will be used to save the veiculo JSON in the database.
return
{
"filename"
:
form_data
.
filename
}
# This function is used to get the car router.
# It is used in the main.py file to include the router in the FastAPI app.
def
get_veiculo_router
()
->
APIRouter
:
return
_veiculo_router
This diff is collapsed.
Click to expand it.
app/api/services/car_service.py
deleted
100644 → 0
View file @
b295ea0c
from
app.api.repositories.car_repository
import
CarRepository
from
app.api.models.car
import
Car
# Service class.
#
# This class is responsible for handling the business logic.
# It will call the repository layer to get the data and return the response.
# It will also handle any exceptions that are raised by the repository layer.
class
CarService
:
def
__init__
(
self
,
repository
:
CarRepository
):
self
.
_repository
=
repository
def
get_all
(
self
):
# Call the repository to get the cars.
pass
def
get_by_id
(
self
,
car_id
:
int
):
pass
def
create
(
self
,
car_data
:
Car
):
pass
def
update
(
self
,
car_id
:
int
,
car_data
:
Car
):
pass
def
delete
(
self
,
car_id
:
int
):
pass
This diff is collapsed.
Click to expand it.
app/api/services/veiculo_service.py
0 → 100644
View file @
6e74d79f
from
fastapi
import
HTTPException
from
app.api.repositories.veiculo_repository
import
VeiculoRepository
from
app.api.models.veiculo
import
Veiculo
# Service class.
#
# This class is responsible for handling the business logic.
# It will call the repository layer to get the data and return the response.
# It will also handle any exceptions that are raised by the repository layer.
class
VeiculoService
:
def
__init__
(
self
,
repository
:
VeiculoRepository
):
self
.
_repository
=
repository
def
get_all
(
self
)
->
list
[
Veiculo
]:
# Call the repository to get the cars.
return
self
.
_repository
.
get_all
()
def
get_by_sigla
(
self
,
sigla
:
str
)
->
Veiculo
:
try
:
return
self
.
_repository
.
get_by_sigla
(
sigla
)
except
Exception
as
e
:
raise
HTTPException
(
status_code
=
404
,
detail
=
"Veiculo nao encontrado"
)
def
create
(
self
,
veiculo_data
:
Veiculo
)
->
None
:
self
.
_repository
.
create
(
veiculo_data
)
def
update
(
self
,
sigla
:
int
,
veiculo_data
:
Veiculo
)
->
None
:
response
=
self
.
_repository
.
update
(
sigla
,
veiculo_data
)
if
response
.
modified_count
==
0
:
raise
HTTPException
(
status_code
=
400
,
detail
=
"Nenhum dado encontrado ou modificado"
)
def
delete
(
self
,
sigla
:
int
)
->
None
:
response
=
self
.
_repository
.
delete
(
sigla
)
if
response
.
deleted_count
==
0
:
raise
HTTPException
(
status_code
=
400
,
detail
=
"Dado nao encontrado para deletar"
)
This diff is collapsed.
Click to expand it.
app/main.py
View file @
6e74d79f
import
uvicorn
from
fastapi
import
FastAPI
from
fastapi.middleware.cors
import
CORSMiddleware
from
mangum
import
Mangum
from
app.api.routers.
car
_router
import
get_
car
_router
from
app.api.routers.
veiculo
_router
import
get_
veiculo
_router
# Initialize the FastAPI app.
app
=
FastAPI
()
app
.
add_middleware
(
CORSMiddleware
,
allow_origins
=
[
"*"
],
allow_methods
=
[
"OPTIONS"
,
"GET"
,
"POST"
,
"PUT"
,
"DELETE"
],
# Headers should be pdf or json, but more testing is required
# "Content-Type", "application/pdf", "application/json"
allow_headers
=
[
"*"
]
)
# Create a handler for AWS Lambda.
handler
=
Mangum
(
app
)
# Include the car router.
app
.
include_router
(
get_
car
_router
())
app
.
include_router
(
get_
veiculo
_router
())
# Start the server.
if
__name__
==
"__main__"
:
...
...
This diff is collapsed.
Click to expand it.
app/test/test_cars.py
View file @
6e74d79f
import
pytest
from
os
import
environ
from
fastapi.testclient
import
TestClient
from
app.api.models.
car
import
Car
from
app.api.models.
veiculo
import
Veiculo
from
app.main
import
app
...
...
@@ -16,15 +16,15 @@ def test_app():
yield
TestClient
(
app
)
def
test_create_car
(
test_app
:
TestClient
):
# Send a POST request to the /cars endpoint.
# The request body represents a car object.
car
_data
=
Car
(
id
=
"1"
,
name
=
"Fiat Uno"
,
description
=
"Small and cheap car."
)
response
=
test_app
.
post
(
"/
car
s"
,
json
=
car
_data
.
dict
())
# Assert that the response status code is 200, for example.
assert
response
.
status_code
==
200
# Assert more things as needed...
#
def test_create_car(test_app: TestClient):
#
# Send a POST request to the /cars endpoint.
#
# The request body represents a car object.
#
veiculo
_data =
Veiculo
(
#
id="1",
#
name="Fiat Uno",
#
description="Small and cheap car."
#
)
#
response = test_app.post("/
veiculo
s", json=
veiculo
_data.dict())
#
# Assert that the response status code is 200, for example.
#
assert response.status_code == 200
#
# Assert more things as needed...
This diff is collapsed.
Click to expand it.
poetry.lock
View file @
6e74d79f
...
...
@@ -592,6 +592,21 @@ files = [
[package.dependencies]
six = ">=1.5"
[[package]]
name = "python-multipart"
version = "0.0.6"
description = "A streaming multipart parser for Python"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"},
{file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"},
]
[package.extras]
dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"]
[[package]]
name = "pytz"
version = "2023.3"
...
...
@@ -744,4 +759,4 @@ standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)",
[metadata]
lock-version = "2.0"
python-versions = "^3.9.0"
content-hash = "
bc07cce2ed1ad0520891c3252d7928e00dfbba28df3553be6173b994ee503bee
"
content-hash = "
89e974075321546e7841055b5ac967f55304124a2276439cc602e7252ade0f3f
"
This diff is collapsed.
Click to expand it.
pyproject.toml
View file @
6e74d79f
...
...
@@ -14,6 +14,7 @@ pydantic = "1.10.7"
pymongo
=
"4.3.3"
tabula-py
=
"2.7.0"
httpx
=
"0.23.3"
python-multipart
=
"0.0.6"
[tool.poetry.group.dev.dependencies]
autopep8
=
"2.0.2"
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help