44from django .contrib import messages
55from django .contrib .auth .decorators import login_required
66from django .db .models import Q
7- from django .http import HttpResponse , HttpResponseRedirect
8- from django .shortcuts import get_object_or_404 , render
7+ from django .http import HttpResponse
8+ from django .shortcuts import get_object_or_404 , redirect , render
99from django .urls import reverse
1010
1111from thebook .bookkeeping .models import BankAccount , Transaction
@@ -72,7 +72,7 @@ def criar_fornecedor(request):
7272 request ,
7373 f"Fornecedora(o) '{ novo_fornecedor .nome } ' criada(o) com sucesso!" ,
7474 )
75- return HttpResponseRedirect ( reverse ( "fornecedores:listar" ) )
75+ return redirect ( "fornecedores:listar" )
7676 else :
7777 form = FornecedorForm ()
7878
@@ -102,7 +102,7 @@ def editar_fornecedor(request, fornecedor_id):
102102 request ,
103103 f"Fornecedora(o) '{ fornecedor_atualizado .nome } ' atualizada(o) com sucesso!" ,
104104 )
105- return HttpResponseRedirect ( reverse ( "fornecedores:listar" ) )
105+ return redirect ( "fornecedores:listar" )
106106 else :
107107 form = FornecedorForm (instance = fornecedor )
108108
@@ -131,7 +131,7 @@ def excluir_fornecedor(request, fornecedor_id):
131131 nome = fornecedor .nome
132132 fornecedor .delete ()
133133 messages .success (request , f"Fornecedora(o) '{ nome } ' removida(o) com sucesso!" )
134- return HttpResponseRedirect ( reverse ( "fornecedores:listar" ) )
134+ return redirect ( "fornecedores:listar" )
135135
136136 return render (
137137 request ,
@@ -173,9 +173,7 @@ def criar_entrega(request, fornecedor_id):
173173 return response
174174
175175 # Senão, redireciona normalmente
176- return HttpResponseRedirect (
177- reverse ("fornecedores:detalhar" , args = [fornecedor .id ])
178- )
176+ return redirect ("fornecedores:detalhar" , fornecedor .id )
179177 else :
180178 form = EntregaFornecedorForm ()
181179
@@ -219,9 +217,7 @@ def editar_entrega(request, fornecedor_id, entrega_id):
219217 return response
220218
221219 # Senão, redireciona normalmente
222- return HttpResponseRedirect (
223- reverse ("fornecedores:detalhar" , args = [fornecedor .id ])
224- )
220+ return redirect ("fornecedores:detalhar" , fornecedor .id )
225221 else :
226222 form = EntregaFornecedorForm (instance = entrega )
227223
@@ -249,9 +245,7 @@ def excluir_entrega(request, fornecedor_id, entrega_id):
249245 request ,
250246 f"Entrega '{ titulo } ' removida com sucesso!" ,
251247 )
252- return HttpResponseRedirect (
253- reverse ("fornecedores:detalhar" , args = [fornecedor .id ])
254- )
248+ return redirect ("fornecedores:detalhar" , fornecedor .id )
255249
256250 return render (
257251 request ,
@@ -271,23 +265,7 @@ def vincular_transacoes(request, fornecedor_id):
271265 """
272266 fornecedor = get_object_or_404 (Fornecedor , pk = fornecedor_id )
273267
274- # Processar o formulário de vinculação
275- if request .method == "POST" :
276- transaction_ids = request .POST .getlist ("transaction_ids" )
277- if transaction_ids :
278- transactions_to_update = Transaction .objects .filter (id__in = transaction_ids )
279- updated_count = transactions_to_update .update (fornecedor = fornecedor )
280- messages .success (
281- request , f"{ updated_count } transações vinculadas com sucesso!"
282- )
283- # Manter na mesma página com os mesmos filtros seria ideal
284- return HttpResponseRedirect (
285- f"{ reverse ('fornecedores:vincular-transacoes' , args = [fornecedor .id ])} ?{ request .GET .urlencode ()} "
286- )
287- else :
288- messages .warning (request , "Nenhuma transação selecionada." )
289-
290- # Filtros de Data
268+ # Filtros de Data (usado tanto no POST quanto no GET)
291269 today = datetime .date .today ()
292270 try :
293271 month = int (request .GET .get ("month" , today .month ))
@@ -299,6 +277,70 @@ def vincular_transacoes(request, fornecedor_id):
299277 except (ValueError , TypeError ):
300278 year = today .year
301279
280+ # Processar o formulário de vinculação/desvinculação
281+ if request .method == "POST" :
282+ selected_ids = set (request .POST .getlist ("transaction_ids" ))
283+
284+ # Buscar todas as transações do período atual que estão vinculadas a este fornecedor
285+ # e que estão visíveis na página atual (com os filtros aplicados)
286+ period_transactions = Transaction .objects .filter (
287+ date__year = year , date__month = month , fornecedor = fornecedor
288+ )
289+
290+ # Aplicar filtros adicionais se existirem
291+ search_query = request .GET .get ("q" , "" )
292+ bank_account_filter = request .GET .get ("bank_account" , "" )
293+
294+ if search_query :
295+ period_transactions = period_transactions .filter (
296+ Q (description__icontains = search_query )
297+ | Q (amount__icontains = search_query )
298+ )
299+ if bank_account_filter :
300+ period_transactions = period_transactions .filter (
301+ bank_account__slug = bank_account_filter
302+ )
303+
304+ # IDs das transações que devem estar vinculadas (marcadas)
305+ selected_ids_int = {int (id ) for id in selected_ids if id }
306+
307+ # IDs das transações que estão vinculadas mas foram desmarcadas
308+ currently_linked_ids = set (period_transactions .values_list ("id" , flat = True ))
309+ to_unlink_ids = currently_linked_ids - selected_ids_int
310+
311+ # Vincular as selecionadas
312+ linked_count = 0
313+ if selected_ids_int :
314+ transactions_to_link = Transaction .objects .filter (id__in = selected_ids_int )
315+ linked_count = transactions_to_link .update (fornecedor = fornecedor )
316+
317+ # Desvincular as que foram desmarcadas
318+ unlinked_count = 0
319+ if to_unlink_ids :
320+ transactions_to_unlink = Transaction .objects .filter (id__in = to_unlink_ids )
321+ unlinked_count = transactions_to_unlink .update (fornecedor = None )
322+
323+ # Mensagem de sucesso
324+ if linked_count > 0 or unlinked_count > 0 :
325+ msg_parts = []
326+ if linked_count > 0 :
327+ msg_parts .append (f"{ linked_count } transação(ões) vinculada(s)" )
328+ if unlinked_count > 0 :
329+ msg_parts .append (f"{ unlinked_count } transação(ões) desvinculada(s)" )
330+ messages .success (request , f"{ ' e ' .join (msg_parts )} com sucesso!" )
331+ else :
332+ messages .info (request , "Nenhuma alteração realizada." )
333+
334+ # Construir URL com parâmetros preservados
335+ url = reverse ("fornecedores:vincular-transacoes" , args = [fornecedor .id ])
336+ # Preservar todos os parâmetros GET
337+ query_params = request .GET .copy ()
338+ if query_params :
339+ url = f"{ url } ?{ query_params .urlencode ()} "
340+
341+ # Redirecionar mantendo os filtros (POST-redirect-GET pattern)
342+ return redirect (url )
343+
302344 # Navegação de períodos
303345 reference_date = datetime .date (year , month , 1 )
304346
0 commit comments