from rest_framework import serializers
from src.dados_comuns.fluxo_status import FichaTecnicaDoProdutoWorkflow
from src.pre_recebimento.ficha_tecnica.models import (
AnaliseFichaTecnica,
FichaTecnicaDoProduto,
)
[docs]
def valida_campos_flv_ficha_tecnica(attrs):
attrs_obrigatorios_flv = {"organico", "especie_variedade"}
if not attrs_obrigatorios_flv.issubset(attrs.keys()):
raise serializers.ValidationError(
"Fichas Técnicas de Produtos FLV exigem que sejam fornecidos valores para os campos"
+ " organico e especie_variedade"
)
[docs]
def valida_campos_pereciveis_ficha_tecnica(attrs):
attrs_obrigatorios_pereciveis = {
"organico",
"prazo_validade_descongelamento",
"temperatura_congelamento",
"temperatura_veiculo",
"condicoes_de_transporte",
"variacao_percentual",
}
if not attrs_obrigatorios_pereciveis.issubset(attrs.keys()):
raise serializers.ValidationError(
"Fichas Técnicas de Produtos PERECÍVEIS exigem que sejam fornecidos valores para os campos"
+ " organico, prazo_validade_descongelamento, temperatura_congelamento"
+ ", temperatura_veiculo, condicoes_de_transporte e variacao_percentual."
)
[docs]
def valida_campos_nao_pereciveis_ficha_tecnica(attrs):
attrs_obrigatorios_nao_pereciveis = {
"organico",
"produto_eh_liquido",
}
if not attrs_obrigatorios_nao_pereciveis.issubset(attrs.keys()):
raise serializers.ValidationError(
"Fichas Técnicas de Produtos NÃO PERECÍVEIS exigem que sejam fornecidos valores para os campos"
+ " organico, e produto_eh_liquido"
)
[docs]
def valida_campos_dependentes_ficha_tecnica(attrs):
if attrs.get("organico") is True and not attrs.get("mecanismo_controle"):
raise serializers.ValidationError(
"É obrigatório fornecer um valor para o atributo mecanismo_controle quando o produto for orgânico."
)
valida_ingredientes_alergenicos_ficha_tecnica(attrs)
if attrs.get("lactose") is True and not attrs.get("lactose_detalhe"):
raise serializers.ValidationError(
"É obrigatório fornecer um valor para o atributo lactose_detalhe quando o produto possuir lactose."
)
if attrs.get("produto_eh_liquido") is True and (
not attrs.get("volume_embalagem_primaria")
or not attrs.get("unidade_medida_volume_primaria")
):
raise serializers.ValidationError(
"É obrigatório fornecer um valor para os atributos volume_embalagem_primaria e unidade_medida_volume_primaria quando o produto for líquido."
)
[docs]
def valida_ingredientes_alergenicos_ficha_tecnica(attrs):
if attrs.get("alergenicos") is True and not attrs.get("ingredientes_alergenicos"):
raise serializers.ValidationError(
"É obrigatório fornecer um valor para o atributo ingredientes_alergenicos quando o produto for alergênico."
)
[docs]
class ServiceValidacaoCorrecaoFichaTecnica:
CAMPOS_OBRIGATORIOS_COMUNS = {
"fabricante_envasador_conferido": {
"obrigatorios": [
"fabricante",
],
"opcionais": [
"envasador_distribuidor",
],
},
"detalhes_produto_conferido": {
"obrigatorios": [
"prazo_validade",
"organico",
"componentes_produto",
"alergenicos",
"gluten",
"lactose",
],
"dependentes": [
"mecanismo_controle",
"ingredientes_alergenicos",
"lactose_detalhe",
],
"opcionais": [
"numero_registro",
],
},
"informacoes_nutricionais_conferido": {
"obrigatorios": [
"porcao",
"unidade_medida_porcao",
"valor_unidade_caseira",
"unidade_medida_caseira",
"informacoes_nutricionais",
]
},
"armazenamento_conferido": {
"obrigatorios": [
"embalagem_primaria",
"embalagem_secundaria",
]
},
"responsavel_tecnico_conferido": {
"obrigatorios": [
"nome_responsavel_tecnico",
"habilitacao",
"numero_registro_orgao",
"arquivo",
]
},
"modo_preparo_conferido": {
"obrigatorios": [
"modo_de_preparo",
]
},
}
CAMPOS_PERECIVEIS = {
**CAMPOS_OBRIGATORIOS_COMUNS,
"conservacao_conferido": {
"obrigatorios": [
"prazo_validade_descongelamento",
"condicoes_de_conservacao",
]
},
"temperatura_e_transporte_conferido": {
"obrigatorios": [
"temperatura_congelamento",
"temperatura_veiculo",
"condicoes_de_transporte",
]
},
"embalagem_e_rotulagem_conferido": {
"obrigatorios": [
"embalagens_de_acordo_com_anexo",
"material_embalagem_primaria",
"peso_liquido_embalagem_primaria",
"unidade_medida_primaria",
"peso_liquido_embalagem_secundaria",
"unidade_medida_secundaria",
"peso_embalagem_primaria_vazia",
"unidade_medida_primaria_vazia",
"peso_embalagem_secundaria_vazia",
"unidade_medida_secundaria_vazia",
"sistema_vedacao_embalagem_secundaria",
"variacao_percentual",
"rotulo_legivel",
]
},
}
CAMPOS_NAO_PERECIVEIS = {
**CAMPOS_OBRIGATORIOS_COMUNS,
"conservacao_conferido": {"obrigatorios": ["condicoes_de_conservacao"]},
"embalagem_e_rotulagem_conferido": {
"obrigatorios": [
"embalagens_de_acordo_com_anexo",
"material_embalagem_primaria",
"peso_liquido_embalagem_primaria",
"unidade_medida_primaria",
"peso_liquido_embalagem_secundaria",
"unidade_medida_secundaria",
"peso_embalagem_primaria_vazia",
"unidade_medida_primaria_vazia",
"peso_embalagem_secundaria_vazia",
"unidade_medida_secundaria_vazia",
"sistema_vedacao_embalagem_secundaria",
"produto_eh_liquido",
"rotulo_legivel",
],
"dependentes": [
"volume_embalagem_primaria",
"unidade_medida_volume_primaria",
],
},
}
CAMPOS_FLV = {
"fabricante_envasador_conferido": {
"obrigatorios": [
"fabricante",
],
"opcionais": [
"envasador_distribuidor",
],
},
"detalhes_produto_conferido": {
"obrigatorios": [
"organico",
"especie_variedade",
],
"dependentes": [
"mecanismo_controle",
],
"opcionais": [
"numero_registro",
],
},
"responsavel_tecnico_conferido": {
"obrigatorios": [
"nome_responsavel_tecnico",
"habilitacao",
"numero_registro_orgao",
"arquivo",
]
},
"outras_informacoes_conferido": {"obrigatorios": []},
}
def __init__(self, ficha_tecnica, attrs) -> None:
self._ficha_tecnica = ficha_tecnica
self._attrs = attrs
self._campos_collapses = self._obter_campos_collapses_por_categoria()
self._collapses_com_correcao = self._obter_collapses_com_correcao()
[docs]
def valida_status_enviada_para_correcao(self):
status_atual = self._ficha_tecnica.status
if status_atual != FichaTecnicaDoProdutoWorkflow.ENVIADA_PARA_CORRECAO:
raise serializers.ValidationError(
{
"status": f"Não é possível corrigir uma Ficha no status {status_atual}"
}
)
[docs]
def valida_campos_obrigatorios_por_collapse(self):
for collapse in self._collapses_com_correcao:
campos_obrigatorios_collapse = self._campos_collapses[collapse].get(
"obrigatorios", []
)
for campo in campos_obrigatorios_collapse:
if campo not in self._attrs:
raise serializers.ValidationError(
{campo: "Este campo é obrigatório."}
)
[docs]
def valida_campos_nao_permitidos_por_collapse(self):
campos_nao_permitidos = {}
campos_validos = set()
for collapse in self._collapses_com_correcao:
self._buscar_campos_nao_permitidos_e_validos_por_collapse(
collapse, campos_nao_permitidos, campos_validos
)
self._remover_campos_validos_dos_nao_permitidos(
campos_nao_permitidos, campos_validos
)
if campos_nao_permitidos:
raise serializers.ValidationError(campos_nao_permitidos)
def _buscar_campos_nao_permitidos_e_validos_por_collapse(
self, collapse, campos_nao_permitidos, campos_validos
):
campos_obrigatorios_collapse = self._campos_collapses[collapse].get(
"obrigatorios", []
)
campos_dependentes_collapse = self._campos_collapses[collapse].get(
"dependentes", []
)
campos_opcionais_collapse = self._campos_collapses[collapse].get(
"opcionais", []
)
campos_collapse = (
campos_obrigatorios_collapse
+ campos_dependentes_collapse
+ campos_opcionais_collapse
)
for attr in self._attrs:
if attr not in campos_collapse:
campos_nao_permitidos[attr] = (
"Este campo não é permitido nesta correção."
)
else:
campos_validos.add(attr)
def _remover_campos_validos_dos_nao_permitidos(
self, campos_nao_permitidos, campos_validos
):
for campo in campos_nao_permitidos.copy():
if campo in campos_validos:
campos_nao_permitidos.pop(campo)
def _obter_campos_collapses_por_categoria(self):
if self._ficha_tecnica.categoria == FichaTecnicaDoProduto.CATEGORIA_FLV:
return self.CAMPOS_FLV
return (
self.CAMPOS_PERECIVEIS
if self._ficha_tecnica.categoria
== FichaTecnicaDoProduto.CATEGORIA_PERECIVEIS
else self.CAMPOS_NAO_PERECIVEIS
)
def _obter_collapses_com_correcao(self):
analise = (
AnaliseFichaTecnica.objects.filter(ficha_tecnica=self._ficha_tecnica)
.order_by("-criado_em")
.first()
)
return [
campo.name
for campo in analise._meta.fields
if (
campo.name in self._campos_collapses.keys()
and getattr(analise, campo.name) is False
)
]