SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 87b9e9fe authored by George Katsikas's avatar George Katsikas :goat:
Browse files

create IndividualBudget model and migration

fix #351
parent 97a37b59
No related branches found
No related tags found
No related merge requests found
# Generated by Django 4.2.15 on 2024-11-29 12:17
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("finances", "0047_subsidycollective"),
("funders", "0016_individualbudget_and_more"),
]
operations = [
migrations.AlterField(
model_name="subsidy",
name="subsidy_type",
field=models.CharField(
choices=[
("sponsorshipagreement", "Sponsorship Agreement"),
("incidentalgrant", "Incidental Grant"),
("developmentgrant", "Development Grant"),
("collaborationagreement", "Collaboration Agreement"),
("coordinationsupportaction", "Coordination and Support Action"),
("donation", "Donation"),
("individualbudget", "Individual Budget"),
],
max_length=256,
),
),
migrations.AddField(
model_name="subsidy",
name="individual_budget",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="subsidies_funded",
to="funders.individualbudget",
),
),
]
......@@ -4,7 +4,9 @@ __license__ = "AGPL v3"
from django.contrib import admin
from .models import Funder, Grant
from finances.admin import SubsidyInline
from .models import Funder, Grant, IndividualBudget
@admin.register(Funder)
......@@ -21,8 +23,6 @@ class FunderAdmin(admin.ModelAdmin):
]
@admin.register(Grant)
class GrantAdmin(admin.ModelAdmin):
search_fields = [
......@@ -37,3 +37,18 @@ class GrantAdmin(admin.ModelAdmin):
]
@admin.register(IndividualBudget)
class IndividualBudgetAdmin(admin.ModelAdmin):
search_fields = [
"organization__name",
"organization__acronym",
"holder__first_name",
"holder__last_name",
]
autocomplete_fields = [
"organization",
"holder",
]
inlines = [
SubsidyInline,
]
# Generated by Django 4.2.15 on 2024-12-02 12:26
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("organizations", "0024_contactperson_info_source"),
("profiles", "0043_alter_profile_first_name_original_and_more"),
("funders", "0015_alter_grant_funder_alter_grant_recipient"),
]
operations = [
migrations.CreateModel(
name="IndividualBudget",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("description", models.TextField(blank=True)),
(
"budget_number",
models.CharField(blank=True, max_length=64, null=True),
),
("fundref_id", models.CharField(blank=True, max_length=64, null=True)),
(
"holder",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="profiles.profile",
),
),
(
"organization",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="organizations.organization",
),
),
],
options={
"ordering": ["organization", "holder"],
"default_related_name": "individual_budgets",
},
),
migrations.AddConstraint(
model_name="individualbudget",
constraint=models.UniqueConstraint(
fields=("organization", "budget_number"),
name="unique_organization_budget_number",
violation_error_message="This organization already has a budget with this number.",
),
),
migrations.AddConstraint(
model_name="individualbudget",
constraint=models.CheckConstraint(
check=models.Q(("holder", None), ("organization", None), _negated=True),
name="organization_or_holder_must_be_set",
violation_error_message="Either an organization or a holder must be set for the budget.",
),
),
]
......@@ -4,9 +4,13 @@ __license__ = "AGPL v3"
from django.db import models
from django.db.models import Q
from django.forms import ValidationError
from django.urls import reverse
from journals.models import Publication
from organizations.models import Organization
from profiles.models import Profile
from scipost.models import Contributor
from .managers import FunderQuerySet
......@@ -78,3 +82,51 @@ class Grant(models.Model):
if self.further_details:
grantstring += " [%s]" % self.further_details
return grantstring
class IndividualBudget(models.Model):
"""
Generic structure of a budget from an Organization given to a single individual.
The funding source of individual subsidies.
"""
required_css_class = "required-asterisk"
description = models.TextField(blank=True)
organization = models.ForeignKey["Organization"](
"organizations.Organization", on_delete=models.CASCADE, blank=True, null=True
)
holder = models.ForeignKey["Profile"](
"profiles.Profile", on_delete=models.CASCADE, blank=True, null=True
)
budget_number = models.CharField(max_length=64, blank=True, null=True)
fundref_id = models.CharField(max_length=64, blank=True, null=True)
class Meta:
default_related_name = "individual_budgets"
ordering = ["organization", "holder"]
constraints = [
models.UniqueConstraint(
fields=["organization", "budget_number"],
name="unique_organization_budget_number",
violation_error_message="This organization already has a budget with this number.",
),
models.CheckConstraint(
check=~models.Q(organization=None, holder=None),
name="organization_or_holder_must_be_set",
violation_error_message="Either an organization or a holder must be set for the budget.",
),
]
@property
def name(self):
if self.budget_number:
return f"Budget {self.budget_number}"
return "Unnamed budget"
def __str__(self):
str_repr = f"{self.name} from {self.organization}"
if self.holder:
str_repr += f" to {self.holder}"
return str_repr
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment