• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iplweb / bpp / 954eab8e-e29d-4864-88d5-f814d498649d

25 Aug 2025 07:53PM UTC coverage: 42.328% (-1.0%) from 43.284%
954eab8e-e29d-4864-88d5-f814d498649d

push

circleci

mpasternak
Merge branch 'release/v202508.1210'

1 of 1 new or added line in 1 file covered. (100.0%)

1298 existing lines in 55 files now uncovered.

16981 of 40118 relevant lines covered (42.33%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.7
src/pbn_api/tasks.py
1
from django.core.management import call_command
2✔
2

3
from long_running.util import wait_for_object
2✔
4
from pbn_api.models.queue import SendStatus
2✔
5

6
from django_bpp.celery_tasks import app
2✔
7

8

9
@app.task
2✔
10
def task_sprobuj_wyslac_do_pbn(pk):
2✔
11
    from pbn_api.models import PBN_Export_Queue
×
12

UNCOV
13
    p = wait_for_object(PBN_Export_Queue, pk)
×
14
    res = p.send_to_pbn()
×
15

16
    match res:
×
UNCOV
17
        case SendStatus.RETRY_LATER:
×
18
            task_sprobuj_wyslac_do_pbn.apply_async(args=[pk], countdown=5 * 60)
×
19

20
        case SendStatus.RETRY_SOON:
×
21
            # np. 423 Locked
22
            task_sprobuj_wyslac_do_pbn.apply_async(args=[pk], countdown=60)
×
23

24
        case SendStatus.RETRY_MUCH_LATER:
×
25
            # PraceSerwisoweException
26
            task_sprobuj_wyslac_do_pbn.apply_async(args=[pk], countdown=60 * 60 * 3)
×
27

UNCOV
28
        case (
×
29
            SendStatus.FINISHED_ERROR
30
            | SendStatus.FINISHED_OKAY
31
            | SendStatus.RETRY_AFTER_USER_AUTHORISED
32
        ):
33
            return
×
34

UNCOV
35
        case _:
×
UNCOV
36
            raise NotImplementedError(
×
37
                f"Return status for background send to PBN not supported {res=}"
38
            )
39

40

41
@app.task
2✔
42
def kolejka_wyczysc_wpisy_bez_rekordow():
2✔
43
    from pbn_api.models import PBN_Export_Queue
×
44

45
    for elem in PBN_Export_Queue.objects.all():
×
UNCOV
46
        if not elem.check_if_record_still_exists():
×
UNCOV
47
            elem.delete()
×
48

49

50
@app.task
2✔
51
def kolejka_ponow_wysylke_prac_po_zalogowaniu(pk):
2✔
UNCOV
52
    from pbn_api.models import PBN_Export_Queue
×
53

54
    # Użytkownik o ID pk zalogował się.
55
    # Odśwież do wysyłki prace które były jego po zalogowaniu
UNCOV
56
    for elem in PBN_Export_Queue.objects.filter(
×
57
        retry_after_user_authorised=True, zamowil_id=pk, wysylke_zakonczono=None
58
    ):
UNCOV
59
        task_sprobuj_wyslac_do_pbn.delay(elem.pk)
×
60

61
    # ... ale i odświez prace wszystkich użytkowników, którzy mają jego konto
62
    # jako konto do wysyłki:
UNCOV
63
    for elem in PBN_Export_Queue.objects.filter(
×
64
        retry_after_user_authorised=True,
65
        zamowil__przedstawiaj_w_pbn_jako_id=pk,
66
        wysylke_zakonczono=None,
67
    ):
UNCOV
68
        task_sprobuj_wyslac_do_pbn.delay(elem.pk)
×
69

70

71
@app.task
2✔
72
def download_institution_publications(user_id):
2✔
73
    """
74
    Download institution publications using PBN API management commands.
75
    Uses database-based locking to ensure only one instance runs at a time.
76

77
    Args:
78
        user_id: ID of the user initiating the download (must have valid PBN token)
79
    """
UNCOV
80
    from django.db import transaction
×
81

UNCOV
82
    from komparator_pbn.models import PbnDownloadTask
×
83

UNCOV
84
    from django.utils import timezone
×
85

UNCOV
86
    from bpp.models.profile import BppUser
×
87

88
    # Check if there's already a running task
UNCOV
89
    running_task = PbnDownloadTask.objects.filter(status="running").first()
×
UNCOV
90
    if running_task:
×
UNCOV
91
        raise ValueError(
×
92
            "Another download task is already running. Please wait for it to complete."
93
        )
94

UNCOV
95
    task_record = None
×
UNCOV
96
    try:
×
UNCOV
97
        user = BppUser.objects.get(pk=user_id)
×
UNCOV
98
        pbn_user = user.get_pbn_user()
×
99

UNCOV
100
        if not pbn_user.pbn_token:
×
UNCOV
101
            raise ValueError(
×
102
                f"User {user.username} is not authorized in PBN (no pbn_token)"
103
            )
104

UNCOV
105
        if not pbn_user.pbn_token_possibly_valid():
×
UNCOV
106
            raise ValueError(
×
107
                f"User {user.username} has an invalid or expired PBN token"
108
            )
109

110
        # Create task record with atomic transaction to prevent race conditions
UNCOV
111
        with transaction.atomic():
×
112
            # Double-check there's no running task within the transaction
UNCOV
113
            if PbnDownloadTask.objects.filter(status="running").exists():
×
UNCOV
114
                raise ValueError(
×
115
                    "Another download task is already running. Please wait for it to complete."
116
                )
117

UNCOV
118
            task_record = PbnDownloadTask.objects.create(
×
119
                user=user,
120
                status="running",
121
                started_at=timezone.now(),
122
                current_step="Inicjalizacja pobierania...",
123
                progress_percentage=0,
124
            )
125

126
        # Monkey-patch tqdm to capture progress and save to database
UNCOV
127
        from threading import Lock
×
128

UNCOV
129
        import tqdm
×
130

UNCOV
131
        original_tqdm_init = tqdm.tqdm.__init__
×
UNCOV
132
        original_tqdm_update = tqdm.tqdm.update
×
UNCOV
133
        original_tqdm_close = tqdm.tqdm.close
×
UNCOV
134
        progress_lock = Lock()
×
135

UNCOV
136
        def patched_tqdm_init(
×
137
            self, iterable=None, desc=None, total=None, *args, **kwargs
138
        ):
139
            # Store task record reference for progress updates
UNCOV
140
            self._task_record = task_record
×
UNCOV
141
            self._desc = desc or ""
×
142
            # Determine phase offset based on current step
UNCOV
143
            if task_record.current_step and "Faza 1" in task_record.current_step:
×
UNCOV
144
                self._phase_offset = 10  # First command: 10-45%
×
UNCOV
145
            elif task_record.current_step and "Faza 2" in task_record.current_step:
×
UNCOV
146
                self._phase_offset = 50  # Second command: 50-85%
×
147
            else:
UNCOV
148
                self._phase_offset = 10  # Default
×
149

150
            # Call original init
UNCOV
151
            original_tqdm_init(self, iterable, desc, total, *args, **kwargs)
×
152

UNCOV
153
        def patched_tqdm_update(self, n=1):
×
UNCOV
154
            result = original_tqdm_update(self, n)
×
155

156
            # Update database progress
UNCOV
157
            if hasattr(self, "_task_record") and self._task_record:
×
UNCOV
158
                with progress_lock:
×
UNCOV
159
                    try:
×
160
                        # Calculate progress percentage (10-45% for first command, 50-85% for second)
UNCOV
161
                        if self.total and self.total > 0:
×
UNCOV
162
                            command_progress = (
×
163
                                self.n / self.total
164
                            ) * 35  # Each command gets 35% of total progress
UNCOV
165
                            total_progress = self._phase_offset + command_progress
×
166

UNCOV
167
                            self._task_record.progress_percentage = min(
×
168
                                90, max(10, int(total_progress))
169
                            )
170

171
                            # Update current step with more detail
UNCOV
172
                            if self._desc:
×
UNCOV
173
                                if "publikacj" in self._desc.lower():
×
UNCOV
174
                                    self._task_record.publications_processed = self.n
×
UNCOV
175
                                    if self.total:
×
UNCOV
176
                                        self._task_record.total_publications = (
×
177
                                            self.total
178
                                        )
UNCOV
179
                                elif (
×
180
                                    "oświadczen" in self._desc.lower()
181
                                    or "statement" in self._desc.lower()
182
                                ):
UNCOV
183
                                    self._task_record.statements_processed = self.n
×
UNCOV
184
                                    if self.total:
×
UNCOV
185
                                        self._task_record.total_statements = self.total
×
186

187
                                # Update current step with progress details
UNCOV
188
                                progress_text = f"{self._desc} ({self.n}"
×
UNCOV
189
                                if self.total:
×
UNCOV
190
                                    progress_text += f"/{self.total}"
×
UNCOV
191
                                progress_text += ")"
×
UNCOV
192
                                self._task_record.current_step = progress_text
×
193

UNCOV
194
                            self._task_record.save()
×
UNCOV
195
                    except Exception:
×
UNCOV
196
                        pass  # Don't let database errors break the download
×
197

UNCOV
198
            return result
×
199

UNCOV
200
        def patched_tqdm_close(self):
×
UNCOV
201
            result = original_tqdm_close(self)
×
202

203
            # Final update when tqdm closes
UNCOV
204
            if hasattr(self, "_task_record") and self._task_record:
×
UNCOV
205
                with progress_lock:
×
UNCOV
206
                    try:
×
UNCOV
207
                        if self.total and self.n >= self.total:
×
208
                            # Command completed, update to end of phase
UNCOV
209
                            total_progress = self._phase_offset + 35
×
UNCOV
210
                            self._task_record.progress_percentage = min(
×
211
                                90, int(total_progress)
212
                            )
UNCOV
213
                            self._task_record.save()
×
UNCOV
214
                    except Exception:
×
UNCOV
215
                        pass
×
216

UNCOV
217
            return result
×
218

219
        # Apply monkey patches
UNCOV
220
        tqdm.tqdm.__init__ = patched_tqdm_init
×
UNCOV
221
        tqdm.tqdm.update = patched_tqdm_update
×
UNCOV
222
        tqdm.tqdm.close = patched_tqdm_close
×
223

UNCOV
224
        try:
×
225
            # Run the management commands with progress reporting
UNCOV
226
            task_record.current_step = "Pobieranie publikacji instytucji (Faza 1/2)"
×
UNCOV
227
            task_record.progress_percentage = 10
×
UNCOV
228
            task_record.save()
×
229

UNCOV
230
            call_command(
×
231
                "pbn_pobierz_publikacje_z_instytucji_v2", user_token=pbn_user.pbn_token
232
            )
233

UNCOV
234
            task_record.current_step = "Pobieranie oświadczeń i publikacji (Faza 2/2)"
×
UNCOV
235
            task_record.progress_percentage = 50
×
UNCOV
236
            task_record.save()
×
237

UNCOV
238
            call_command(
×
239
                "pbn_pobierz_oswiadczenia_i_publikacje_v1",
240
                user_token=pbn_user.pbn_token,
241
            )
242

UNCOV
243
            task_record.current_step = "Finalizowanie pobierania..."
×
UNCOV
244
            task_record.progress_percentage = 90
×
UNCOV
245
            task_record.save()
×
246

247
        finally:
248
            # Restore original tqdm methods
UNCOV
249
            tqdm.tqdm.__init__ = original_tqdm_init
×
UNCOV
250
            tqdm.tqdm.update = original_tqdm_update
×
UNCOV
251
            tqdm.tqdm.close = original_tqdm_close
×
252

253
        # Mark as completed
UNCOV
254
        task_record.status = "completed"
×
UNCOV
255
        task_record.current_step = "Pobieranie zakończone pomyślnie"
×
UNCOV
256
        task_record.progress_percentage = 100
×
UNCOV
257
        task_record.completed_at = timezone.now()
×
UNCOV
258
        task_record.save()
×
259

UNCOV
260
    except Exception as e:
×
261
        # Record the error
UNCOV
262
        if task_record:
×
UNCOV
263
            task_record.status = "failed"
×
UNCOV
264
            task_record.error_message = str(e)
×
UNCOV
265
            task_record.completed_at = timezone.now()
×
UNCOV
266
            task_record.save()
×
UNCOV
267
        raise
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc