Commit 673ff0981498d303c3b0611d2bf7df5434585dd3
1 parent
1d5dbff3
Exists in
dev
Quota progression (with sequence, quota sp now attached to SP_Period)
Showing
6 changed files
with
129 additions
and
40 deletions
Show diff stats
src/core/pyros_django/majordome/agent/Agent.py
@@ -154,7 +154,7 @@ import config.old_config as config_old | @@ -154,7 +154,7 @@ import config.old_config as config_old | ||
154 | #from config import * | 154 | #from config import * |
155 | 155 | ||
156 | from majordome.models import AgentSurvey, AgentCmd, AgentLogs | 156 | from majordome.models import AgentSurvey, AgentCmd, AgentLogs |
157 | -from user_mgmt.models import Period | 157 | +from user_mgmt.models import Period, Institute, ScientificProgram, SP_Period |
158 | from scp_mgmt.models import Quota | 158 | from scp_mgmt.models import Quota |
159 | 159 | ||
160 | from vendor.guitastro.src.guitastro import Ephemeris | 160 | from vendor.guitastro.src.guitastro import Ephemeris |
@@ -3576,8 +3576,10 @@ class Agent: | @@ -3576,8 +3576,10 @@ class Agent: | ||
3576 | d_prev = 0 | 3576 | d_prev = 0 |
3577 | d_cur = 0 | 3577 | d_cur = 0 |
3578 | d_total = 0 | 3578 | d_total = 0 |
3579 | + dusk_elev1, dusk_elev2 = self.config.getDuskElev() | ||
3580 | + dawn_elev1, dawn_elev2 = self.config.getDawnElev() | ||
3579 | night_info = {} | 3581 | night_info = {} |
3580 | - self._duskelev = self.config.getDuskElev() | 3582 | + _ ,self._duskelev = self.config.getDuskElev() |
3581 | while jd < jd2: | 3583 | while jd < jd2: |
3582 | night = self._oc['config'].fn.date2night(jd) | 3584 | night = self._oc['config'].fn.date2night(jd) |
3583 | for target in targets: | 3585 | for target in targets: |
@@ -3586,13 +3588,15 @@ class Agent: | @@ -3586,13 +3588,15 @@ class Agent: | ||
3586 | ks = np.where(ephem['alt'] < self._duskelev) | 3588 | ks = np.where(ephem['alt'] < self._duskelev) |
3587 | d_prev = d_prev + d_cur | 3589 | d_prev = d_prev + d_cur |
3588 | d_cur = len(ks[0]) | 3590 | d_cur = len(ks[0]) |
3589 | - night_info[night] = [0, d_prev, d_cur, 0] | 3591 | + _, start_index = self.get_indexes_of_night(ephem, dusk_elev1, dusk_elev2) |
3592 | + night_info[night] = [0, d_prev, d_cur, 0, start_index] | ||
3593 | + | ||
3590 | jd += 1 | 3594 | jd += 1 |
3591 | d_total = d_prev + d_cur | 3595 | d_total = d_prev + d_cur |
3592 | for key, val in night_info.items(): | 3596 | for key, val in night_info.items(): |
3593 | night_id = key | 3597 | night_id = key |
3594 | val[0] = d_total | 3598 | val[0] = d_total |
3595 | - val[-1] = d_total - val[-2] | 3599 | + val[-2] = d_total - val[-3] |
3596 | # --- update db TODO | 3600 | # --- update db TODO |
3597 | try: | 3601 | try: |
3598 | if Quota.objects.get(night_id=night_id): | 3602 | if Quota.objects.get(night_id=night_id): |
@@ -3607,7 +3611,8 @@ class Agent: | @@ -3607,7 +3611,8 @@ class Agent: | ||
3607 | quota_attributes["d_total"] = val[0] | 3611 | quota_attributes["d_total"] = val[0] |
3608 | quota_attributes["d_previous"] = val[1] | 3612 | quota_attributes["d_previous"] = val[1] |
3609 | quota_attributes["d_current"] = val[2] | 3613 | quota_attributes["d_current"] = val[2] |
3610 | - quota_attributes["d_next"] = val[-1] | 3614 | + quota_attributes["d_next"] = val[3] |
3615 | + quota_attributes["index_start"] = val[4] | ||
3611 | quota.set_attributes_and_save(quota_attributes) | 3616 | quota.set_attributes_and_save(quota_attributes) |
3612 | operiod.quota = Quota.objects.get(night_id=list(night_info.keys())[0], id_period=operiod.id) | 3617 | operiod.quota = Quota.objects.get(night_id=list(night_info.keys())[0], id_period=operiod.id) |
3613 | operiod.save() | 3618 | operiod.save() |
@@ -3615,6 +3620,41 @@ class Agent: | @@ -3615,6 +3620,41 @@ class Agent: | ||
3615 | #pickle.dump(night_info, open(filename, "wb")) | 3620 | #pickle.dump(night_info, open(filename, "wb")) |
3616 | return night_info | 3621 | return night_info |
3617 | 3622 | ||
3623 | + def update_quota_institutes_and_sp_for_night(self, quota_night): | ||
3624 | + for institute in Institute.objects.all(): | ||
3625 | + institute_new_quota = quota_night.convert_to_quota(institute.quota_f) | ||
3626 | + institute.quota.set_attributes_and_save(institute_new_quota) | ||
3627 | + for sp_period in SP_Period.objects.filter(scientific_program__in=institute.scientific_programs.all(), period=Period.objects.get(id=quota_night.id_period)): | ||
3628 | + sp_new_quota = institute.quota.convert_to_quota(sp_period.quota_f) | ||
3629 | + | ||
3630 | + sp_period.quota.set_attributes_and_save(sp_new_quota) | ||
3631 | + | ||
3632 | + def get_indexes_of_night(self, ephemeris:dict, dusk_elev1:int, dusk_elev2:int)->Tuple: | ||
3633 | + es = ephemeris["alt"] | ||
3634 | + delta_w = dusk_elev2 - dusk_elev1 | ||
3635 | + delta_es = es[1:] - es[:-1] | ||
3636 | + delta_es = np.append(delta_es, delta_es[-1]) | ||
3637 | + ks = np.linspace(0, 86400, 86401) | ||
3638 | + k1 = -1 | ||
3639 | + k2 = -1 | ||
3640 | + k = 0 | ||
3641 | + if delta_w > 0: | ||
3642 | + for e, delta_e, k in zip(es, delta_es, ks): | ||
3643 | + if e > dusk_elev1 and k1 == -1 and delta_e > 0: | ||
3644 | + k1 = k | ||
3645 | + elif e > dusk_elev2 and k2 == -1 and delta_e > 0: | ||
3646 | + k2=k | ||
3647 | + break | ||
3648 | + else: | ||
3649 | + for e, delta_e, k in zip(es, delta_es, ks): | ||
3650 | + | ||
3651 | + if e < dusk_elev1 and k1 == -1 and delta_e < 0: | ||
3652 | + k1=k | ||
3653 | + elif e < dusk_elev2 and k2 == -1 and delta_e < 0: | ||
3654 | + k2=k | ||
3655 | + break | ||
3656 | + | ||
3657 | + return (k1, k2) | ||
3618 | """ | 3658 | """ |
3619 | ================================================================= | 3659 | ================================================================= |
3620 | MAIN | 3660 | MAIN |
src/core/pyros_django/scheduling/A_Scheduler.py
@@ -232,6 +232,7 @@ class A_Scheduler(Agent): | @@ -232,6 +232,7 @@ class A_Scheduler(Agent): | ||
232 | 232 | ||
233 | def update_db_quota_sequence(self, sequence_id, quota_attributes): | 233 | def update_db_quota_sequence(self, sequence_id, quota_attributes): |
234 | sequence = Sequence.objects.get(id=sequence_id) | 234 | sequence = Sequence.objects.get(id=sequence_id) |
235 | + | ||
235 | new_quota = Quota() | 236 | new_quota = Quota() |
236 | new_quota.set_attributes_and_save(quota_attributes) | 237 | new_quota.set_attributes_and_save(quota_attributes) |
237 | sequence.quota = new_quota | 238 | sequence.quota = new_quota |
@@ -291,7 +292,21 @@ class A_Scheduler(Agent): | @@ -291,7 +292,21 @@ class A_Scheduler(Agent): | ||
291 | # --- Unpack the matrix to effective schedule arrays | 292 | # --- Unpack the matrix to effective schedule arrays |
292 | schedule_eff_jd, schedule_eff_binary, schedule_eff_sequence_id, schedule_eff_scientific_programm_id, schedule_eff_order, schedule_eff_visibility = input_matrix | 293 | schedule_eff_jd, schedule_eff_binary, schedule_eff_sequence_id, schedule_eff_scientific_programm_id, schedule_eff_order, schedule_eff_visibility = input_matrix |
293 | # --- Get the index of the current instant in the night | 294 | # --- Get the index of the current instant in the night |
294 | - nownight, index = self._fn.date2night("now", self.BINS_NIGHT) | 295 | + date = guitastro.Date("now") + "12H" |
296 | + nownight, index = self._fn.date2night(date.iso(), self.BINS_NIGHT) | ||
297 | + index_stop = oquota.index_start + oquota.d_current | ||
298 | + #print(f"{index=} {index_stop=} {oquota.index_start=}") | ||
299 | + if index > index_stop: | ||
300 | + period_quota_passed = oquota.d_current | ||
301 | + elif index > oquota.index_start: | ||
302 | + period_quota_passed = index - oquota.index_start | ||
303 | + else: | ||
304 | + period_quota_passed = 0 | ||
305 | + oquota.d_passed = period_quota_passed | ||
306 | + period_quota_to_schedule = oquota.d_current - period_quota_passed | ||
307 | + oquota.d_schedule = period_quota_to_schedule | ||
308 | + oquota.save() | ||
309 | + self.update_quota_institutes_and_sp_for_night(oquota) | ||
295 | self.dprint(f"{nownight=} {index=}") | 310 | self.dprint(f"{nownight=} {index=}") |
296 | # --- Add all ever observed sequences from 0 to index | 311 | # --- Add all ever observed sequences from 0 to index |
297 | if nownight == night and (index >= 0 or index < self.BINS_NIGHT): | 312 | if nownight == night and (index >= 0 or index < self.BINS_NIGHT): |
@@ -309,6 +324,24 @@ class A_Scheduler(Agent): | @@ -309,6 +324,24 @@ class A_Scheduler(Agent): | ||
309 | print(f"Invalid entry in the database") | 324 | print(f"Invalid entry in the database") |
310 | #print(f"{schedule_jd=}") | 325 | #print(f"{schedule_jd=}") |
311 | 326 | ||
327 | + # Set global quota for SP and institutes for current night | ||
328 | + date = guitastro.Date("now") + "240H" | ||
329 | + nownight, index = self._fn.date2night(date.iso(), self.BINS_NIGHT) | ||
330 | + index_stop = oquota.index_start + oquota.d_current | ||
331 | + #print(f"{index=} {index_stop=} {oquota.index_start=}") | ||
332 | + if index > index_stop: | ||
333 | + period_quota_passed = oquota.d_current | ||
334 | + elif index > oquota.index_start: | ||
335 | + period_quota_passed = index - oquota.index_start | ||
336 | + else: | ||
337 | + period_quota_passed = 0 | ||
338 | + oquota.d_passed = period_quota_passed | ||
339 | + period_quota_to_schedule = oquota.d_current - period_quota_passed | ||
340 | + oquota.d_schedule = period_quota_to_schedule | ||
341 | + oquota.save() | ||
342 | + self.update_quota_institutes_and_sp_for_night(oquota) | ||
343 | + | ||
344 | + | ||
312 | # =================================================================== | 345 | # =================================================================== |
313 | # --- Loop over the sequences of the night to extract useful infos | 346 | # --- Loop over the sequences of the night to extract useful infos |
314 | # =================================================================== | 347 | # =================================================================== |
@@ -389,29 +422,18 @@ class A_Scheduler(Agent): | @@ -389,29 +422,18 @@ class A_Scheduler(Agent): | ||
389 | self.dprint(f"{scientific_program_ids=}") | 422 | self.dprint(f"{scientific_program_ids=}") |
390 | for scientific_program_id in scientific_program_ids: | 423 | for scientific_program_id in scientific_program_ids: |
391 | scientific_program_info = {} | 424 | scientific_program_info = {} |
392 | - try: | ||
393 | - osp = ScientificProgram.objects.get(id=scientific_program_id) | ||
394 | - # --- ospperiod is the SP object | ||
395 | - ospperiod = SP_Period.objects.get(period = period_id, scientific_program = osp) | ||
396 | - scientific_program_info['priority'] = ospperiod.priority | ||
397 | - scientific_program_info['over_quota_duration'] = ospperiod.over_quota_duration | ||
398 | - scientific_program_info['over_quota_duration_allocated'] = ospperiod.over_quota_duration_allocated | ||
399 | - scientific_program_info['over_quota_duration_remaining'] = ospperiod.over_quota_duration_remaining | ||
400 | - scientific_program_info['quota_allocated'] = ospperiod.quota_allocated | ||
401 | - scientific_program_info['quota_minimal'] = ospperiod.quota_minimal | ||
402 | - scientific_program_info['quota_nominal'] = ospperiod.quota_nominal | ||
403 | - scientific_program_info['quota_remaining'] = ospperiod.quota_remaining | ||
404 | - scientific_program_info['token_allocated'] = ospperiod.token_allocated | ||
405 | - scientific_program_info['token_remaining'] = ospperiod.token_allocated | ||
406 | - except: | ||
407 | - # --- simulation | ||
408 | - scientific_program_info['priority'] = 0 | ||
409 | - if scientific_program_info['priority'] == 0: | ||
410 | - # --- simulation | ||
411 | - priority = 50 + scientific_program_id*5 | ||
412 | - scientific_program_info['priority'] = priority | ||
413 | - scientific_program_info['quota_allocated'] = 12000 | ||
414 | - scientific_program_info['quota_remaining'] = 12000 | 425 | + ospperiod = SP_Period.objects.get(scientific_program=ScientificProgram.objects.get(id=scientific_program_id), period=info["operiod"]) |
426 | + # --- ospperiod is the SP object | ||
427 | + scientific_program_info['priority'] =ospperiod.priority | ||
428 | + quota_ospperiod = ospperiod.quota | ||
429 | + # example to get d_current of sp_period | ||
430 | + # quota_ospperiod.d_current | ||
431 | + scientific_program_info['token_allocated'] = ospperiod.token_allocated | ||
432 | + scientific_program_info['token_remaining'] = ospperiod.token_allocated | ||
433 | + scientific_program_info['quota_allocated'] = quota_ospperiod.d_current | ||
434 | + scientific_program_info['quota_remaining'] = quota_ospperiod.d_schedule | ||
435 | + scientific_program_info['d_currentq'] = 0 | ||
436 | + | ||
415 | scientific_program_infos[str(scientific_program_id)] = scientific_program_info | 437 | scientific_program_infos[str(scientific_program_id)] = scientific_program_info |
416 | self.dprint(f"{scientific_program_id=} priority={scientific_program_info['priority']} quota={scientific_program_info['quota_remaining']}") | 438 | self.dprint(f"{scientific_program_id=} priority={scientific_program_info['priority']} quota={scientific_program_info['quota_remaining']}") |
417 | 439 | ||
@@ -530,7 +552,28 @@ class A_Scheduler(Agent): | @@ -530,7 +552,28 @@ class A_Scheduler(Agent): | ||
530 | # --- Update the scientific program dict | 552 | # --- Update the scientific program dict |
531 | quota_remaining -= duration | 553 | quota_remaining -= duration |
532 | scientific_program_infos[str(scientific_program_id)]['quota_remaining'] = quota_remaining | 554 | scientific_program_infos[str(scientific_program_id)]['quota_remaining'] = quota_remaining |
533 | - | 555 | + |
556 | + # --- Update the DB | ||
557 | + osequence = Sequence.objects.get(id=sequence_id) | ||
558 | + sequence_quota = osequence.quota | ||
559 | + sequence_quota.d_schedule = 0 | ||
560 | + sequence_quota.d_currentq = duration | ||
561 | + sequence_quota.d_scheduleq = duration | ||
562 | + osequence.quota.save() | ||
563 | + # quota_ospperiod.d_currentq += duration | ||
564 | + # quota_ospperiod.save() | ||
565 | + scientific_program_infos[str(scientific_program_id)]['d_currentq'] += duration | ||
566 | + | ||
567 | + for scientific_program_id in scientific_program_ids: | ||
568 | + ospperiod = SP_Period.objects.get(scientific_program=ScientificProgram.objects.get(id=scientific_program_id), period=info["operiod"]) | ||
569 | + quota_ospperiod = ospperiod.quota | ||
570 | + quota_ospperiod.d_currentq = scientific_program_infos[str(scientific_program_id)]['d_currentq'] | ||
571 | + quota_ospperiod.d_scheduleq = scientific_program_infos[str(scientific_program_id)]['d_currentq'] | ||
572 | + ospperiod.quota.save() | ||
573 | + # for sp in SP_Period.objects.filter(period=Period.objects.get(id=period_id)): | ||
574 | + # institute_quota = sp.scientific_program.institute.quota | ||
575 | + # institute_quota.d_currentq += sp.quota.d_currentq | ||
576 | + # sp.scientific_program.institute.save() | ||
534 | 577 | ||
535 | # =================================================================== | 578 | # =================================================================== |
536 | # --- Insert sequences in the schedule. Respecting priority but over quota | 579 | # --- Insert sequences in the schedule. Respecting priority but over quota |
@@ -632,7 +675,7 @@ class A_Scheduler(Agent): | @@ -632,7 +675,7 @@ class A_Scheduler(Agent): | ||
632 | #start_expo_pref = "BESTELEV" #"IMMEDIATE" | 675 | #start_expo_pref = "BESTELEV" #"IMMEDIATE" |
633 | start_expo_pref = 0 # for bestelev 1, for immediate 0 | 676 | start_expo_pref = 0 # for bestelev 1, for immediate 0 |
634 | start_date,_ = self._fn.night2date(info["night"]) | 677 | start_date,_ = self._fn.night2date(info["night"]) |
635 | - start_date = start_date + 0.25 + (0.5*k) | 678 | + start_date = start_date + 0.25 + (0.05*k) |
636 | start_date_to_datetime = guitastro.Date(start_date).iso() | 679 | start_date_to_datetime = guitastro.Date(start_date).iso() |
637 | #start_date = datetime.datetime(2023, 6, 28, 10, 21, 40) | 680 | #start_date = datetime.datetime(2023, 6, 28, 10, 21, 40) |
638 | #end_date = datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc) | 681 | #end_date = datetime.datetime(2023, 6, 28, 10, 21, 40, 999640, tzinfo=datetime.timezone.utc) |
src/core/pyros_django/scp_mgmt/A_SCP_Manager.py
@@ -287,12 +287,12 @@ class A_SCP_Manager(Agent): | @@ -287,12 +287,12 @@ class A_SCP_Manager(Agent): | ||
287 | institute = sp.institute | 287 | institute = sp.institute |
288 | institute_quota = institute.quota | 288 | institute_quota = institute.quota |
289 | new_quota = Quota() | 289 | new_quota = Quota() |
290 | - quota_attributes = institute_quota.convert_to_quota(sp.quota_f) | 290 | + quota_attributes = institute_quota.convert_to_quota(sp_period.quota_f) |
291 | quota_attributes["night_id"] = 1 | 291 | quota_attributes["night_id"] = 1 |
292 | quota_attributes["id_period"] = id_period | 292 | quota_attributes["id_period"] = id_period |
293 | new_quota.set_attributes_and_save(quota_attributes) | 293 | new_quota.set_attributes_and_save(quota_attributes) |
294 | - sp.quota = new_quota | ||
295 | - sp.save() | 294 | + sp_period.quota = new_quota |
295 | + sp_period.save() | ||
296 | 296 | ||
297 | except Exception as e: | 297 | except Exception as e: |
298 | print(e) | 298 | print(e) |
src/core/pyros_django/scp_mgmt/models.py
@@ -4,6 +4,9 @@ from django.db import models | @@ -4,6 +4,9 @@ from django.db import models | ||
4 | class Quota(models.Model): | 4 | class Quota(models.Model): |
5 | id_period = models.BigIntegerField(blank=True, null=True) | 5 | id_period = models.BigIntegerField(blank=True, null=True) |
6 | night_id = models.CharField(max_length=8, null=True, blank=True, db_index=True) | 6 | night_id = models.CharField(max_length=8, null=True, blank=True, db_index=True) |
7 | + | ||
8 | + # in seconds | ||
9 | + index_start = models.BigIntegerField(default=0, blank=True, null=True) | ||
7 | d_total = models.BigIntegerField(default=0, blank=True, null=True) | 10 | d_total = models.BigIntegerField(default=0, blank=True, null=True) |
8 | d_totalq = models.BigIntegerField(default=0, blank=True, null=True) | 11 | d_totalq = models.BigIntegerField(default=0, blank=True, null=True) |
9 | d_totalx = models.BigIntegerField(default=0, blank=True, null=True) | 12 | d_totalx = models.BigIntegerField(default=0, blank=True, null=True) |
@@ -57,6 +60,9 @@ class Quota(models.Model): | @@ -57,6 +60,9 @@ class Quota(models.Model): | ||
57 | self.id_period = quota_attributes["id_period"] | 60 | self.id_period = quota_attributes["id_period"] |
58 | if quota_attributes.get("night_id") != None: | 61 | if quota_attributes.get("night_id") != None: |
59 | self.night_id = quota_attributes["night_id"] | 62 | self.night_id = quota_attributes["night_id"] |
63 | + | ||
64 | + if quota_attributes.get("index_start") != None: | ||
65 | + self.index_start = quota_attributes.get("index_start") | ||
60 | 66 | ||
61 | if quota_attributes.get("d_totalq") != None: | 67 | if quota_attributes.get("d_totalq") != None: |
62 | self.d_totalq = quota_attributes["d_totalq"] | 68 | self.d_totalq = quota_attributes["d_totalq"] |
src/core/pyros_django/seq_submit/views.py
@@ -305,7 +305,7 @@ def sequence_validate(request, seq_id): | @@ -305,7 +305,7 @@ def sequence_validate(request, seq_id): | ||
305 | eph = guitastro.Ephemeris() | 305 | eph = guitastro.Ephemeris() |
306 | eph.set_home(home) | 306 | eph.set_home(home) |
307 | # duskelev a parametrer dans obsconfig (yml) | 307 | # duskelev a parametrer dans obsconfig (yml) |
308 | - duskelev = -7 | 308 | + _, duskelev = config.getDuskElev() |
309 | message = "" | 309 | message = "" |
310 | try: | 310 | try: |
311 | # TODO remplacer les none par les fichiers pickle de ephem_sun & ephem_moon | 311 | # TODO remplacer les none par les fichiers pickle de ephem_sun & ephem_moon |
src/core/pyros_django/user_mgmt/models.py
@@ -70,7 +70,6 @@ class UserLevel(models.Model): | @@ -70,7 +70,6 @@ class UserLevel(models.Model): | ||
70 | class Country(models.Model): | 70 | class Country(models.Model): |
71 | name = models.CharField(max_length=45, blank=True, null=True) | 71 | name = models.CharField(max_length=45, blank=True, null=True) |
72 | desc = models.TextField(blank=True, null=True) | 72 | desc = models.TextField(blank=True, null=True) |
73 | - quota = models.FloatField(blank=True, null=True) | ||
74 | 73 | ||
75 | class Meta: | 74 | class Meta: |
76 | managed = True | 75 | managed = True |
@@ -86,7 +85,7 @@ class Institute(models.Model): | @@ -86,7 +85,7 @@ class Institute(models.Model): | ||
86 | # fraction quota | 85 | # fraction quota |
87 | quota_f = models.FloatField( | 86 | quota_f = models.FloatField( |
88 | validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True) | 87 | validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True) |
89 | - | 88 | + country = models.ForeignKey(Country, on_delete=models.SET_NULL,related_name="institute_countrys", blank=True, null=True) |
90 | quota = models.ForeignKey(Quota, on_delete=models.SET_NULL,related_name="institute_quotas", blank=True, null=True) | 89 | quota = models.ForeignKey(Quota, on_delete=models.SET_NULL,related_name="institute_quotas", blank=True, null=True) |
91 | #representative_user = models.ForeignKey("PyrosUser", on_delete=models.DO_NOTHING,related_name="institutes",default=1) | 90 | #representative_user = models.ForeignKey("PyrosUser", on_delete=models.DO_NOTHING,related_name="institutes",default=1) |
92 | 91 | ||
@@ -475,9 +474,7 @@ class ScientificProgram(models.Model): | @@ -475,9 +474,7 @@ class ScientificProgram(models.Model): | ||
475 | science_theme = models.ForeignKey(ScienceTheme, on_delete=models.DO_NOTHING, related_name="scientific_program_theme", default=1) | 474 | science_theme = models.ForeignKey(ScienceTheme, on_delete=models.DO_NOTHING, related_name="scientific_program_theme", default=1) |
476 | is_auto_validated = models.BooleanField(default=False) | 475 | is_auto_validated = models.BooleanField(default=False) |
477 | objects = ScientificProgramManager() | 476 | objects = ScientificProgramManager() |
478 | - quota = models.ForeignKey(Quota, on_delete=models.SET_NULL, related_name="scientific_program_quotas", blank=True, null=True) | ||
479 | - quota_f = models.FloatField( | ||
480 | - validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True) | 477 | + |
481 | 478 | ||
482 | class Meta: | 479 | class Meta: |
483 | managed = True | 480 | managed = True |
@@ -541,6 +538,9 @@ class SP_Period(models.Model): | @@ -541,6 +538,9 @@ class SP_Period(models.Model): | ||
541 | token = models.PositiveIntegerField(default=0) | 538 | token = models.PositiveIntegerField(default=0) |
542 | token_allocated = models.PositiveIntegerField(default=0, blank=True) | 539 | token_allocated = models.PositiveIntegerField(default=0, blank=True) |
543 | token_remaining = models.PositiveIntegerField(default=0, blank=True) | 540 | token_remaining = models.PositiveIntegerField(default=0, blank=True) |
541 | + quota = models.ForeignKey(Quota, on_delete=models.SET_NULL, related_name="sp_period_quotas", blank=True, null=True) | ||
542 | + quota_f = models.FloatField( | ||
543 | + validators=[MinValueValidator(0), MaxValueValidator(1)], blank=True, null=True) | ||
544 | # Unit PI donne un nombre de priorité (100 = alert) | 544 | # Unit PI donne un nombre de priorité (100 = alert) |
545 | priority = models.IntegerField( | 545 | priority = models.IntegerField( |
546 | validators=[MinValueValidator(0), MaxValueValidator(100)], blank=True, null=True) | 546 | validators=[MinValueValidator(0), MaxValueValidator(100)], blank=True, null=True) |