Skip to content

Commit

Permalink
Feature/73 new post service order (#100)
Browse files Browse the repository at this point in the history
* [@adrilene/@denisousa] Issue #73 - Iniciando testes.

* [@Adrilene/@denisousa] issue #73 atualizacao no requirements

* [@Adrilene/@denisousa] issue #73 validacao do post

* [@Adrilene/@denisousa] issue #73 validacao com schemas

* [@adrilene/@denisousa] issue #73 WIP testes do post

* [@adrilene/@denisousa] Issue #73 - Testes de validação.

* [@adrilene/@denisousa] Issue #73 - Iniciando registro da ordem de serviço.

* [@adrilene/@denisousa] issue #73 alterações no model e no schema (required/fields)

Alguns arquivos fora do escopo descrito no card tiveram de ser alterados. Ainda não começamos a usar o repository, pois haveria conflito da arquitetura da v2 proposta inicialmente com a  da atual.

* [@adrilene/@denisousa] Issue #73 - Inserção de nova ordem de serviço com validações de Ids de equipamento e item.

* [@adrilene/@denisousa] Issue #73 - Resolvendo comentários do PR.

* [@adrilene/@denisousa] Issue #73 - Correção testes de itens.

Co-authored-by: Denis Menezes <[email protected]>
  • Loading branch information
Adrilene and denisousa authored Jun 29, 2020
1 parent 3c27c61 commit 11b404a
Show file tree
Hide file tree
Showing 16 changed files with 491 additions and 32 deletions.
65 changes: 59 additions & 6 deletions api/v2/controllers/service_orders_many_controller.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,73 @@
from flask_restful import Resource
from ..helpers.helper_response import get_response, error_response
from ..validation.validation_request import invalid_deleted_parameter
from ..services.service_order_service import ServiceOrderService
from http import HTTPStatus
from flask import request
from flask_restful import Resource
from ..helpers.helper_response import get_response
from ..validation.validation_request import invalid_deleted_parameter
from api.v2.controllers.validators.validation_request import validate_request
from api.v2.services.service_order_service import ServiceOrderService
from api.v2.models.schemas.service_order_schema import ServiceOrderSchema
from api.v2.utils.util_response import error_response, post_response
from .validators.validation_request import validate_request_id


class ServiceOrdersManyController(Resource):
def get(self):
deleted_included = request.args.get("deleted")
if invalid_deleted_parameter(deleted_included):
return error_response(
"Parameter deleted is not equal true.", HTTPStatus.BAD_REQUEST)
"Parameter deleted is not equal true.", HTTPStatus.BAD_REQUEST
)
if deleted_included:
service_orders = ServiceOrderService().fetch_all()
service_orders = ServiceOrderService().fetch_all()
else:
service_orders = ServiceOrderService().fetch_active()

return get_response(service_orders, deleted_included)

def post(self):
body = request.get_json()

validate, message = validate_request(body)
if not validate:
return error_response(message)

errors = []
for index, service_order in enumerate(body["content"]):
validate, message = ServiceOrderSchema().validate_save(service_order)
if not validate:
errors.append({index: message})
continue

validate, message = validate_request_id(
"equipamento", service_order["equipamento_id"]
)
if not validate:
errors.append({index: message})

accessories = service_order["triagem"]["acessorios"]
for accessory in accessories:
validate, message = validate_request_id("item", accessory["item_id"])
if not validate:
errors.append({index: message})

items = service_order["diagnostico"]["itens"]
for item in items:
validate, message = validate_request_id("item", item["item_id"])
if not validate:
errors.append({index: message})

service_order["numero_ordem_servico"] = ServiceOrderService().format_service_order_number(
service_order["numero_ordem_servico"]
)

if ServiceOrderService().check_duplicates_service_order_number(service_order["numero_ordem_servico"]):
errors.append({index: 'Service Order number already exists'})

if errors:
return error_response(errors)

content = []
for service_order in body["content"]:
content.append(ServiceOrderService().save_service_order(service_order))

return post_response(content)
88 changes: 88 additions & 0 deletions api/v2/controllers/validators/validation_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from bson import ObjectId
from api.v2.services.item_service import ItemService
from api.services.equipamento_service import listar_equipamento_by_id


def invalid_deleted_parameter(param):
return param and param != "true"


def validate_is_list(body):
if isinstance(type(body), list):
return (False, "Not a list.")
return (True, "OK")


def validate_post(body):
if "_id" in body:
return (False, "ID must not be sent")
return (True, "OK")


def validate_request(body):
if not body:
return (False, "No body found")

if not "content" in body:
return (False, "No content found")

if not isinstance(body["content"], list):
return (False, "No list found.")

if not len(body["content"]):
return (False, "Empty list. Nothing to do.")
for item in body["content"]:
if not item:
return (False, "Some entry has no data.")

return (True, "OK")


def validate_id_included(entity):
if "_id" not in entity:
return (False, "Missing ID")
return (True, "OK")


def validate_id_objectID(_id):
try:
ObjectId(_id)
except Exception:
return (False, "Invalid ID")
return (True, "OK")


def validate_id_exists(entity, _id):
if entity == "item":
if not ItemService().fetch_item_by_id(_id):
return (False, "Nonexistent item ID")

if entity == "equipamento":
if not listar_equipamento_by_id(_id):
return (False, "Nonexistent equipamento ID")

return (True, "OK")


def validate_request_dict_id(entity):
validate, message = validate_id_included(entity)
if not validate:
return (validate, message)

validate, message = validate_request_id(entity["_id"])
if not validate:
return (validate, message)

return (True, "OK")


def validate_request_id(entity, _id):
validate, message = validate_id_objectID(_id)
if not validate:
return (validate, message)

validate, message = validate_id_exists(entity, _id)
if not validate:
return (validate, message)

return (True, "OK")
1 change: 0 additions & 1 deletion api/v2/migrations/items_from_diagnostico_service_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ def fetch_items_from_diagnostico(self):
items[reference_key] = item
continue
items[reference_key]['quantidade'] += item['quantidade']
print(items)
return items

def generate_reference_key(self, item):
Expand Down
20 changes: 20 additions & 0 deletions api/v2/models/schemas/schema_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from marshmallow import ValidationError


class SchemaBase:
def validate_save(self, body):
if "_id" in body:
return False, "Id must not be sent"

if "updated_at" in body:
return False, "Updated must not be sent"

if "deleted_at" in body:
return False, "Deleted must not be sent"

try:
self.load(body)
except ValidationError as err:
return False, err.messages

return True, "OK"
92 changes: 92 additions & 0 deletions api/v2/models/schemas/service_order_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from api.v2.models import service_order_model
from .schema_base import SchemaBase
from marshmallow import Schema, fields, validate


class AccessorySchema(Schema):
class Meta:
model = service_order_model.Acessorio
fields = ("item_id",
"acompanha",
"quantidade",
"estado_de_conservacao")

item_id = fields.String(required=True)
acompanha = fields.Boolean(required=True)
quantidade = fields.Integer(required=True)
estado_de_conservacao = fields.String(required=False)


class ScreeningSchema(Schema):
class Meta:
model = service_order_model.Triagem
fields = ("estado_de_conservacao",
"foto_antes_limpeza",
"acessorios",
"foto_apos_limpeza")

foto_antes_limpeza = fields.String(required=False)
estado_de_conservacao = fields.String(required=False)
acessorios = fields.List(fields.Nested(AccessorySchema), required=False)
foto_apos_limpeza = fields.String(required=False)


class ItemDiganotico(Schema):
class Meta:
model = service_order_model.Item
fields = ("item_id",
"quantidade")

item_id = fields.String(required=True)
quantidade = fields.Integer(required=True)


class DiagnosticSchema(Schema):
class Meta:
model = service_order_model.Triagem
fields = ("resultado_tecnico",
"demanda_servicos",
"observacoes",
"itens")

resultado_tecnico = fields.String(required=False)
demanda_servicos = fields.String(required=False)
observacoes = fields.String(required=False)
itens = fields.List(fields.Nested(ItemDiganotico), required=False)


class CalibrationSchema(Schema):
class Meta:
model = service_order_model.Calibragem
fields = (
"status",
)

status = fields.String(required=False)


class ServiceOrderSchema(Schema, SchemaBase):
class Meta:
model = service_order_model.OrdemServico
fields = ("_id",
"equipamento_id",
"numero_ordem_servico",
"created_at",
"updated_at",
"triagem",
"clinico",
"tecnico",
"foto_equipamento_chegada",
"status",
"diagnostico",
"calibragem")

equipamento_id = fields.String(required=False)
numero_ordem_servico = fields.Integer(required=True)
created_at = fields.DateTime(required=False)
updated_at = fields.DateTime(required=False)
triagem = fields.Nested(ScreeningSchema, required=False)
diagnostico = fields.Nested(DiagnosticSchema, required=False)
calibragem = fields.Nested(CalibrationSchema, required=True)
status = fields.String(validate=validate.OneOf(["triagem", "diagnostico"]),
required=True)
6 changes: 3 additions & 3 deletions api/v2/models/service_order_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ class Calibragem(db.EmbeddedDocument):

class OrdemServico(db.Document):
equipamento_id = db.ReferenceField(Equipamento)
numero_ordem_servico = db.StringField(required=False, unique=True)
status = db.StringField(required=False)
numero_ordem_servico = db.StringField(required=True, unique=True)
status = db.StringField(required=True)
triagem = db.EmbeddedDocumentField(Triagem, required=False)
diagnostico = db.EmbeddedDocumentField(Diagnostico, required=False)
calibragem = db.EmbeddedDocumentField(Calibragem, required=False)
calibragem = db.EmbeddedDocumentField(Calibragem, required=True)
created_at = db.DateTimeField(default=datetime.utcnow(), required=False)
updated_at = db.DateTimeField(default=datetime.utcnow(), required=False)
deleted_at = db.DateTimeField(required=False)
17 changes: 13 additions & 4 deletions api/v2/services/service_order_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@


class ServiceOrderService(ServiceBase):

def fetch_active(self):
return self.parser_mongo_response_to_list(
OrdemServico.objects(deleted_at__exists=False))
OrdemServico.objects(deleted_at__exists=False)
)

def fetch_all(self):
return self.parser_mongo_response_to_list(
OrdemServico.objects())
return self.parser_mongo_response_to_list(OrdemServico.objects())

def save_service_order(self, service_order):
service_order = OrdemServico(**service_order).save()
return str(service_order.id)

def format_service_order_number(self, service_order_number):
return str(service_order_number).zfill(4)

def check_duplicates_service_order_number(self, service_order_number):
return OrdemServico.objects(numero_ordem_servico=service_order_number)
22 changes: 22 additions & 0 deletions api/v2/utils/util_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from flask import make_response, jsonify
from http import HTTPStatus

def error_response(message, status=400):
return make_response(
jsonify({
"error": message,
}),
status
)


def get_response(content, deleted):
response = {'content': content}

response['deleted'] = True if deleted else False

return make_response(jsonify(response), HTTPStatus.OK)


def post_response(content):
return make_response(jsonify({'content': content}), 201)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ python-slugify==4.0.0
Werkzeug==1.0.1
WTForms==2.2.1
zipp==3.1.0
mockito
mockito==1.2.1
2 changes: 1 addition & 1 deletion tests/items_many/test_items_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def test_put_items_has_not_required_fields(self):
headers={"Content-Type": "application/json"},
data=payload_post)

payload = copy.deepcopy(self.mock_items['sem_obrigatorios'])
payload = copy.deepcopy(self.mock_items['sem_um_obrigatorio'])
id = response.json['content'][0]
payload['_id'] = id
payload = json.dumps({'content': [payload]})
Expand Down
2 changes: 1 addition & 1 deletion tests/items_many/test_items_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def test_items_body_no_required_fields(self):
response = self.client.post(
'/v2/items',
headers={"Content-Type": "application/json"},
data={'content': [self.mock_items['sem_obrigatorios']]})
data={'content': [self.mock_items['sem_um_obrigatorio']]})
self.assertEqual(response.status_code, 400)

def test_items_valid_body(self):
Expand Down
Loading

0 comments on commit 11b404a

Please sign in to comment.