Coverage for src\pncp\instrumentos_convocatorios\tipos.py: 98%

253 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-07-22 22:11 -0300

1from datetime import datetime 

2from typing import Literal, Self 

3 

4from pncp.tipos import Lista, ModeloBasico 

5from pncp.utils import get_many, get_one 

6 

7type Id = str | int 

8 

9 

10class Status(ModeloBasico): 

11 id: Id 

12 nome: str 

13 

14 @classmethod 

15 def listar(cls) -> Lista[Self]: 

16 return Lista( 

17 [ 

18 cls(id="todos", nome="Todos"), 

19 cls(id="em_andamento", nome="Em Andamento"), 

20 cls(id="concluido", nome="Concluído"), 

21 cls(id="cancelado", nome="Cancelado"), 

22 ] 

23 ) 

24 

25 

26class InstrumentoConvocatorio(ModeloBasico): 

27 id: Id 

28 nome: str 

29 total: int 

30 

31 

32class ModalidadeDeContratacao(ModeloBasico): 

33 id: Id 

34 nome: str 

35 total: int 

36 

37 

38class Orgao(ModeloBasico): 

39 id: Id 

40 nome: str 

41 total: int 

42 cnpj: str 

43 

44 

45class Unidade(ModeloBasico): 

46 id: Id 

47 nome: str 

48 total: int 

49 codigo: str 

50 codigo_nome: str 

51 

52 

53class UnidadeDaFederacao(ModeloBasico): 

54 id: Id 

55 total: int 

56 

57 

58class Municipio(ModeloBasico): 

59 id: Id 

60 nome: str 

61 total: int 

62 

63 

64class Esfera(ModeloBasico): 

65 id: Id 

66 nome: str 

67 total: int 

68 

69 

70class Poder(ModeloBasico): 

71 id: Id 

72 nome: str 

73 total: int 

74 

75 

76class Ano(ModeloBasico): 

77 ano: Id 

78 total: int 

79 

80 

81class FonteOrcamentaria(ModeloBasico): 

82 id: Id 

83 nome: str 

84 total: int 

85 

86 

87class CamposDeBusca(ModeloBasico): 

88 tipos_documento: Literal["edital"] = "edital" 

89 

90 q: str = "" 

91 pagina: int = 1 

92 tam_pagina: int = 500 

93 status: Id = "todos" 

94 tipos: Lista[Id] = Lista() 

95 orgaos: Lista[Id] = Lista() 

96 unidades: Lista[Id] = Lista() 

97 esferas: Lista[Id] = Lista() 

98 poderes: Lista[Id] = Lista() 

99 ufs: Lista[Id] = Lista() 

100 municipios: Lista[Id] = Lista() 

101 modalidades: Lista[Id] = Lista() 

102 anos: Lista[Id] = Lista() 

103 fontes_orcamentarias: Lista[Id] = Lista() 

104 

105 

106class Resultado(ModeloBasico): 

107 id: Id 

108 index: str 

109 doc_type: str 

110 title: str 

111 description: str 

112 item_url: str 

113 document_type: str 

114 created_at: datetime 

115 numero: str | None 

116 ano: str 

117 numero_sequencial: str 

118 numero_sequencial_compra_ata: str | None 

119 numero_controle_pncp: str 

120 orgao_id: str 

121 orgao_cnpj: str 

122 orgao_nome: str 

123 orgao_subrogado_id: str | None 

124 orgao_subrogado_nome: str | None 

125 unidade_id: str 

126 unidade_codigo: str 

127 unidade_nome: str 

128 esfera_id: str 

129 esfera_nome: str 

130 poder_id: str 

131 poder_nome: str 

132 municipio_id: str 

133 municipio_nome: str 

134 uf: str 

135 modalidade_licitacao_id: str 

136 modalidade_licitacao_nome: str 

137 situacao_id: str 

138 situacao_nome: str 

139 data_publicacao_pncp: datetime 

140 data_atualizacao_pncp: datetime 

141 data_assinatura: datetime | None 

142 data_inicio_vigencia: datetime 

143 data_fim_vigencia: datetime 

144 cancelado: bool 

145 valor_global: float | None 

146 tem_resultado: bool 

147 tipo_id: str 

148 tipo_nome: str 

149 tipo_contrato_nome: str | None 

150 fonte_orcamentaria: str | None 

151 fonte_orcamentaria_id: str | None 

152 fonte_orcamentaria_nome: str | None 

153 

154 def detalhar(self) -> "Contratacao": 

155 url = f"https://pncp.gov.br/api/consulta/v1/orgaos/{self.orgao_cnpj}/compras/{self.ano}/{self.numero_sequencial}" 

156 data = get_one(url) 

157 return Contratacao(**data) 

158 

159 

160class IOrgaoEntidade(ModeloBasico): 

161 cnpj: str 

162 razao_social: str 

163 poder_id: str 

164 esfera_id: str 

165 

166 

167class IUnidadeOrgao(ModeloBasico): 

168 uf_nome: str 

169 codigo_ibge: str 

170 codigo_unidade: str 

171 nome_unidade: str 

172 uf_sigla: str 

173 municipio_nome: str 

174 

175 

176class IOrgaoSubRogado(ModeloBasico): 

177 cnpj: str 

178 razao_social: str 

179 poder_id: str 

180 esfera_id: str 

181 

182 

183class IUnidadeSubRogada(ModeloBasico): 

184 uf_nome: str 

185 codigo_ibge: str 

186 codigo_unidade: str 

187 nome_unidade: str 

188 uf_sigla: str 

189 municipio_nome: str 

190 

191 

192class IAmparoLegal(ModeloBasico): 

193 descricao: str 

194 nome: str 

195 codigo: int 

196 

197 

198class IFonteOrcamentaria(ModeloBasico): 

199 codigo: int 

200 nome: str 

201 descricao: str 

202 data_inclusao: datetime 

203 

204 

205class Contratacao(ModeloBasico): 

206 valor_total_estimado: float 

207 valor_total_homologado: float | None 

208 orcamento_sigiloso_codigo: int 

209 orcamento_sigiloso_descricao: str 

210 numero_controle_PNCP: str 

211 link_sistema_origem: str | None 

212 link_processo_eletronico: str | None 

213 ano_compra: int 

214 sequencial_compra: int 

215 numero_compra: str 

216 processo: str 

217 orgao_entidade: IOrgaoEntidade 

218 unidade_orgao: IUnidadeOrgao 

219 orgao_sub_rogado: IOrgaoSubRogado | None 

220 unidade_sub_rogada: IUnidadeSubRogada | None 

221 modalidade_id: int 

222 modalidade_nome: str 

223 justificativa_presencial: str | None 

224 modo_disputa_id: int 

225 modo_disputa_nome: str 

226 tipo_instrumento_convocatorio_codigo: int 

227 tipo_instrumento_convocatorio_nome: str 

228 amparo_legal: IAmparoLegal 

229 objeto_compra: str 

230 informacao_complementar: str 

231 srp: bool 

232 fontes_orcamentarias: list[IFonteOrcamentaria] # TODO: Converter para Lista 

233 data_publicacao_pncp: datetime 

234 data_abertura_proposta: datetime 

235 data_encerramento_proposta: datetime 

236 situacao_compra_id: int 

237 situacao_compra_nome: str 

238 existe_resultado: bool 

239 data_inclusao: datetime 

240 data_atualizacao: datetime 

241 data_atualizacao_global: datetime 

242 usuario_nome: str 

243 

244 def listar_itens(self) -> Lista["Item"]: 

245 url = f"https://pncp.gov.br/api/pncp/v1/orgaos/{self.orgao_entidade.cnpj}/compras/{self.ano_compra}/{self.sequencial_compra}/itens" 

246 params = { 

247 "pagina": 1, 

248 "tamanhoPagina": 500, 

249 } 

250 data = get_many(url, params=params) 

251 return Lista([Item(**item) for item in data]) 

252 

253 def listar_documentos(self) -> None: 

254 raise NotImplementedError("Método não implementado") 

255 

256 def obter_historico(self) -> None: 

257 raise NotImplementedError("Método não implementado") 

258 

259 

260class ICatalogo(ModeloBasico): 

261 id: int 

262 nome: str 

263 descricao: str 

264 data_inclusao: datetime 

265 data_atualizacao: datetime 

266 status_ativo: bool 

267 url: str 

268 

269 

270class ICategoriaItemCatalogo(ModeloBasico): 

271 id: int 

272 nome: str 

273 descricao: str 

274 data_inclusao: datetime 

275 data_atualizacao: datetime 

276 status_ativo: bool 

277 

278 

279class Item(ModeloBasico): 

280 numero_item: int 

281 descricao: str 

282 material_ou_servico: str 

283 material_ou_servico_nome: str 

284 valor_unitario_estimado: float 

285 valor_total: float 

286 quantidade: float 

287 unidade_medida: str 

288 orcamento_sigiloso: bool 

289 item_categoria_id: int 

290 item_categoria_nome: str 

291 patrimonio: str | None 

292 codigo_registro_imobiliario: str | None 

293 criterio_julgamento_id: int 

294 criterio_julgamento_nome: str 

295 situacao_compra_item: int 

296 situacao_compra_item_nome: str 

297 tipo_beneficio: int 

298 tipo_beneficio_nome: str 

299 incentivo_produtivo_basico: bool 

300 data_inclusao: datetime 

301 data_atualizacao: datetime 

302 tem_resultado: bool 

303 imagem: int 

304 aplicabilidade_margem_preferencia_normal: bool 

305 aplicabilidade_margem_preferencia_adicional: bool 

306 percentual_margem_preferencia_normal: float | None 

307 percentual_margem_preferencia_adicional: float | None 

308 ncm_nbs_codigo: str | None 

309 ncm_nbs_descricao: str | None 

310 catalogo: ICatalogo | None 

311 categoria_item_catalogo: ICategoriaItemCatalogo | None 

312 catalogo_codigo_item: str | None 

313 informacao_complementar: str | None 

314 

315 def listar_resultados(self) -> None: 

316 raise NotImplementedError("Método não implementado") 

317 

318 def listar_imagens(self) -> None: 

319 raise NotImplementedError("Método não implementado")