fix a few things in backoffice chain/credebtor views and templates, and update bootstrap_devsite script to create chains, credebtors, expenses and revenues
This commit is contained in:
parent
02f0d77c21
commit
833fc85e46
|
@ -7,7 +7,7 @@ Details for Chain {{ chain.name }} | {{ block.super }}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Details for Chain {{ chain.name }}</h2>
|
<h2>Details for Chain {{ chain.name }}</h2>
|
||||||
<a href="{% url "backoffice:chain_list" camp_slug=camp.slug %}">Back to Chain list</a>
|
<a class="btn btn-default" href="{% url "backoffice:chain_list" camp_slug=camp.slug %}"><i class="fas fa-undo"></i> Back to Chain list</a>
|
||||||
|
|
||||||
<h3>{{ chain.credebtors.count }} Credebtors for Chain {{ chain.name }}</h3>
|
<h3>{{ chain.credebtors.count }} Credebtors for Chain {{ chain.name }}</h3>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
|
@ -26,7 +26,7 @@ Details for Chain {{ chain.name }} | {{ block.super }}
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for credebtor in chain.credebtors.all %}
|
{% for credebtor in chain.credebtors.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ credebtor.name }}</td>
|
<td><a class="btn btn-primary" href="{% url 'backoffice:credebtor_detail' camp_slug=camp.slug chain_slug=chain.slug credebtor_slug=credebtor.slug %}">{{ credebtor.name }}</a></td>
|
||||||
<td><address>{{ credebtor.address }}</address></td>
|
<td><address>{{ credebtor.address }}</address></td>
|
||||||
<td>{{ credebtor.notes|default:"N/A" }}</td>
|
<td>{{ credebtor.notes|default:"N/A" }}</td>
|
||||||
<td class="text-center"><span class="badge">{{ credebtor.expenses.count }}</span></td>
|
<td class="text-center"><span class="badge">{{ credebtor.expenses.count }}</span></td>
|
||||||
|
@ -39,10 +39,10 @@ Details for Chain {{ chain.name }} | {{ block.super }}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h3>{{ chain.expenses.count }} Expenses for Chain {{ chain.name }}</h3>
|
<h3>{{ chain.expenses_count }} Expenses for Chain {{ chain.name }}</h3>
|
||||||
{% include 'includes/expense_list_panel.html' with expense_list=chain.expenses.all %}
|
{% include 'includes/expense_list_panel.html' with expense_list=chain.expenses.all %}
|
||||||
|
|
||||||
<h3>{{ chain.revenues.count }} Revenues for Chain {{ chain.name }}</h3>
|
<h3>{{ chain.revenues_count }} Revenues for Chain {{ chain.name }}</h3>
|
||||||
{% include 'includes/revenue_list_panel.html' with revenue_list=chain.revenues.all %}
|
{% include 'includes/revenue_list_panel.html' with revenue_list=chain.revenues.all %}
|
||||||
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
@ -8,7 +8,7 @@ Select Chain | {{ block.super }}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Chains</h2>
|
<h2>Chains</h2>
|
||||||
<p><a href="{% url "backoffice:index" camp_slug=camp.slug %}">Back to Backoffice Index</a></p>
|
<p><a class="btn btn-default" href="{% url "backoffice:index" camp_slug=camp.slug %}"><i class="fas fa-undo"></i> Back to Backoffice Index</a></p>
|
||||||
|
|
||||||
{% if chain_list %}
|
{% if chain_list %}
|
||||||
<table class="table table-hover datatable">
|
<table class="table table-hover datatable">
|
||||||
|
@ -30,9 +30,9 @@ Select Chain | {{ block.super }}
|
||||||
<td>{{ chain.name }}</td>
|
<td>{{ chain.name }}</td>
|
||||||
<td>{{ chain.notes|default:"N/A" }}</td>
|
<td>{{ chain.notes|default:"N/A" }}</td>
|
||||||
<td class="text-center"><span class="badge">{{ chain.credebtors.count }}</span></td>
|
<td class="text-center"><span class="badge">{{ chain.credebtors.count }}</span></td>
|
||||||
<td class="text-center"><span class="badge">{{ chain.expenses.count }}</span></td>
|
<td class="text-center"><span class="badge">{{ chain.expenses_count }}</span></td>
|
||||||
<td class="text-center">{{ chain.expenses_total|default:"0" }} DKK</td>
|
<td class="text-center">{{ chain.expenses_total|default:"0" }} DKK</td>
|
||||||
<td class="text-center"><span class="badge">{{ chain.revenues.count }}</span></td>
|
<td class="text-center"><span class="badge">{{ chain.revenues_count }}</span></td>
|
||||||
<td class="text-center">{{ chain.revenues_total|default:"0" }} DKK</td>
|
<td class="text-center">{{ chain.revenues_total|default:"0" }} DKK</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn-primary" href="{% url 'backoffice:chain_detail' camp_slug=camp.slug chain_slug=chain.slug %}"><i class="fas fa-search"></i> Details</a>
|
<a class="btn btn-primary" href="{% url 'backoffice:chain_detail' camp_slug=camp.slug chain_slug=chain.slug %}"><i class="fas fa-search"></i> Details</a>
|
||||||
|
|
|
@ -7,7 +7,7 @@ Details for Credebtor {{ credebtor.name }} (Chain {{ credebtor.chain.name }}) |
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>Details for Credebtor {{ credebtor.name }} (Chain {{ credebtor.chain.name }})</h2>
|
<h2>Details for Credebtor {{ credebtor.name }} (Chain {{ credebtor.chain.name }})</h2>
|
||||||
<a href="{% url "backoffice:chain_detail" camp_slug=camp.slug chain_slug=credebtor.chain.slug %}">Back to Credebtor list</a>
|
<a class="btn btn-default" href="{% url "backoffice:chain_detail" camp_slug=camp.slug chain_slug=credebtor.chain.slug %}"><i class="fas fa-undo"></i> Back to Credebtor list</a>
|
||||||
|
|
||||||
<h3>{{ credebtor.expenses.count }} Expenses for Credebtor {{ credebtor.name }}</h3>
|
<h3>{{ credebtor.expenses.count }} Expenses for Credebtor {{ credebtor.name }}</h3>
|
||||||
{% include 'includes/expense_list_panel.html' with expense_list=credebtor.expenses.all %}
|
{% include 'includes/expense_list_panel.html' with expense_list=credebtor.expenses.all %}
|
||||||
|
|
|
@ -16,8 +16,8 @@ class ChainAdmin(admin.ModelAdmin):
|
||||||
@admin.register(Credebtor)
|
@admin.register(Credebtor)
|
||||||
class CredebtorAdmin(admin.ModelAdmin):
|
class CredebtorAdmin(admin.ModelAdmin):
|
||||||
list_filter = ["chain", "name"]
|
list_filter = ["chain", "name"]
|
||||||
list_display = ["chain", "name", "notes"]
|
list_display = ["name", "chain", "address", "notes"]
|
||||||
search_fields = ["chain", "name", "notes"]
|
search_fields = ["chain", "name", "address", "notes"]
|
||||||
|
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
|
|
|
@ -20,12 +20,17 @@ from .email import (
|
||||||
class ChainManager(models.Manager):
|
class ChainManager(models.Manager):
|
||||||
"""
|
"""
|
||||||
ChainManager adds 'expenses_total' and 'revenues_total' to the Chain qs
|
ChainManager adds 'expenses_total' and 'revenues_total' to the Chain qs
|
||||||
|
Also adds 'expenses_count' and 'revenues_count' and prefetches all expenses
|
||||||
|
and revenues for the credebtors.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
|
qs = qs.prefetch_related("credebtors__expenses", "credebtors__revenues")
|
||||||
qs = qs.annotate(expenses_total=models.Sum("credebtors__expenses__amount"))
|
qs = qs.annotate(expenses_total=models.Sum("credebtors__expenses__amount"))
|
||||||
|
qs = qs.annotate(expenses_count=models.Count("credebtors__expenses", distinct=True))
|
||||||
qs = qs.annotate(revenues_total=models.Sum("credebtors__revenues__amount"))
|
qs = qs.annotate(revenues_total=models.Sum("credebtors__revenues__amount"))
|
||||||
|
qs = qs.annotate(revenues_count=models.Count("credebtors__revenues", distinct=True))
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,11 +86,13 @@ class Chain(CreatedUpdatedModel, UUIDModel):
|
||||||
|
|
||||||
class CredebtorManager(models.Manager):
|
class CredebtorManager(models.Manager):
|
||||||
"""
|
"""
|
||||||
CredebtorManager adds 'expenses_total' and 'revenues_total' to the Credebtor qs
|
CredebtorManager adds 'expenses_total' and 'revenues_total' to the Credebtor qs,
|
||||||
|
and prefetches expenses and revenues for the credebtor(s).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
|
qs = qs.prefetch_related("expenses", "revenues")
|
||||||
qs = qs.annotate(expenses_total=models.Sum("expenses__amount"))
|
qs = qs.annotate(expenses_total=models.Sum("expenses__amount"))
|
||||||
qs = qs.annotate(revenues_total=models.Sum("revenues__amount"))
|
qs = qs.annotate(revenues_total=models.Sum("revenues__amount"))
|
||||||
return qs
|
return qs
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% if expense_list %}
|
{% if expense_list %}
|
||||||
<table class="table table-hover">
|
<table class="table table-hover datatable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Invoice Date</th>
|
<th>Invoice Date</th>
|
||||||
|
|
|
@ -12,6 +12,7 @@ from django.contrib.auth.models import User
|
||||||
from django.contrib.gis.geos import Point
|
from django.contrib.gis.geos import Point
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.core.management import call_command
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.crypto import get_random_string
|
from django.utils.crypto import get_random_string
|
||||||
|
@ -52,13 +53,65 @@ from tickets.models import TicketType
|
||||||
from tokens.models import Token, TokenFind
|
from tokens.models import Token, TokenFind
|
||||||
from utils.slugs import unique_slugify
|
from utils.slugs import unique_slugify
|
||||||
from villages.models import Village
|
from villages.models import Village
|
||||||
|
from economy.models import Chain, Credebtor, Expense, Revenue
|
||||||
|
|
||||||
fake = Faker()
|
fake = Faker()
|
||||||
tz = pytz.timezone("Europe/Copenhagen")
|
tz = pytz.timezone("Europe/Copenhagen")
|
||||||
logger = logging.getLogger("bornhack.%s" % __name__)
|
logger = logging.getLogger("bornhack.%s" % __name__)
|
||||||
|
|
||||||
|
|
||||||
@factory.django.mute_signals(post_save)
|
class ChainFactory(factory.django.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Chain
|
||||||
|
|
||||||
|
name = factory.Faker("company")
|
||||||
|
slug = factory.LazyAttribute(lambda f: unique_slugify(f.name, Chain.objects.all().values_list("slug", flat=True)))
|
||||||
|
|
||||||
|
|
||||||
|
class CredebtorFactory(factory.django.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Credebtor
|
||||||
|
|
||||||
|
chain = factory.SubFactory(ChainFactory)
|
||||||
|
name = factory.Faker("company")
|
||||||
|
slug = factory.LazyAttribute(lambda f: unique_slugify(f.name, Credebtor.objects.all().values_list("slug", flat=True)))
|
||||||
|
address = factory.Faker("address", locale="dk_DK")
|
||||||
|
notes = factory.Faker("text")
|
||||||
|
|
||||||
|
|
||||||
|
class ExpenseFactory(factory.django.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Expense
|
||||||
|
|
||||||
|
camp = factory.Faker("random_element", elements=Camp.objects.all())
|
||||||
|
creditor = factory.Faker("random_element", elements=Credebtor.objects.all())
|
||||||
|
user = factory.Faker("random_element", elements=User.objects.all())
|
||||||
|
amount = factory.Faker("random_int", min=20, max=20000)
|
||||||
|
description = factory.Faker("text")
|
||||||
|
paid_by_bornhack = factory.Faker("random_element", elements=[True, True, False])
|
||||||
|
invoice = factory.django.ImageField(color=random.choice(['#ff0000', '#00ff00', '#0000ff']))
|
||||||
|
invoice_date = factory.Faker("date")
|
||||||
|
responsible_team = factory.Faker("random_element", elements=Team.objects.all())
|
||||||
|
approved = factory.Faker("random_element", elements=[True, True, False])
|
||||||
|
notes = factory.Faker("text")
|
||||||
|
|
||||||
|
|
||||||
|
class RevenueFactory(factory.django.DjangoModelFactory):
|
||||||
|
class Meta:
|
||||||
|
model = Revenue
|
||||||
|
|
||||||
|
camp = factory.Faker("random_element", elements=Camp.objects.all())
|
||||||
|
debtor = factory.Faker("random_element", elements=Credebtor.objects.all())
|
||||||
|
user = factory.Faker("random_element", elements=User.objects.all())
|
||||||
|
amount = factory.Faker("random_int", min=20, max=20000)
|
||||||
|
description = factory.Faker("text")
|
||||||
|
invoice = factory.django.ImageField(color=random.choice(['#ff0000', '#00ff00', '#0000ff']))
|
||||||
|
invoice_date = factory.Faker("date")
|
||||||
|
responsible_team = factory.Faker("random_element", elements=Team.objects.all())
|
||||||
|
approved = factory.Faker("random_element", elements=[True, True, False])
|
||||||
|
notes = factory.Faker("text")
|
||||||
|
|
||||||
|
|
||||||
class ProfileFactory(factory.django.DjangoModelFactory):
|
class ProfileFactory(factory.django.DjangoModelFactory):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Profile
|
model = Profile
|
||||||
|
@ -159,8 +212,9 @@ class Command(BaseCommand):
|
||||||
dict(year=2017, tagline="Make Tradition", colour="#750787", read_only=True),
|
dict(year=2017, tagline="Make Tradition", colour="#750787", read_only=True),
|
||||||
dict(year=2018, tagline="scale it", colour="#008026", read_only=True),
|
dict(year=2018, tagline="scale it", colour="#008026", read_only=True),
|
||||||
dict(year=2019, tagline="a new /home", colour="#ffed00", read_only=True),
|
dict(year=2019, tagline="a new /home", colour="#ffed00", read_only=True),
|
||||||
dict(year=2020, tagline="Going Viral", colour="#ff8c00", read_only=False),
|
dict(year=2020, tagline="Make Clean", colour="#ff8c00", read_only=False),
|
||||||
dict(year=2021, tagline="Undecided", colour="#e40303", read_only=False),
|
dict(year=2021, tagline="Undecided", colour="#e40303", read_only=False),
|
||||||
|
dict(year=2022, tagline="Undecided", colour="#004dff", read_only=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
camp_instances = []
|
camp_instances = []
|
||||||
|
@ -508,6 +562,21 @@ class Command(BaseCommand):
|
||||||
name="Recording", defaults={"icon": "fas fa-film"}
|
name="Recording", defaults={"icon": "fas fa-film"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def create_credebtors(self):
|
||||||
|
self.output("Creating Chains and Credebtors...")
|
||||||
|
try:
|
||||||
|
CredebtorFactory.create_batch(50)
|
||||||
|
except ValidationError:
|
||||||
|
self.outout("Name conflict, retrying...")
|
||||||
|
CredebtorFactory.create_batch(50)
|
||||||
|
for _ in range(20):
|
||||||
|
# add 20 more credebtors to random existing chains
|
||||||
|
try:
|
||||||
|
CredebtorFactory.create(chain=Chain.objects.order_by("?").first())
|
||||||
|
except ValidationError:
|
||||||
|
self.outout("Name conflict, skipping...")
|
||||||
|
continue
|
||||||
|
|
||||||
def create_product_categories(self):
|
def create_product_categories(self):
|
||||||
categories = {}
|
categories = {}
|
||||||
self.output("Creating productcategories...")
|
self.output("Creating productcategories...")
|
||||||
|
@ -686,7 +755,7 @@ class Command(BaseCommand):
|
||||||
orders = {}
|
orders = {}
|
||||||
self.output("Creating orders...")
|
self.output("Creating orders...")
|
||||||
orders[0] = Order.objects.create(
|
orders[0] = Order.objects.create(
|
||||||
user=users[1], payment_method="cash", open=None, paid=True
|
user=users[1], payment_method="in_person", open=None, paid=True
|
||||||
)
|
)
|
||||||
orders[0].orderproductrelation_set.create(
|
orders[0].orderproductrelation_set.create(
|
||||||
product=camp_products["ticket1"], quantity=1
|
product=camp_products["ticket1"], quantity=1
|
||||||
|
@ -697,7 +766,7 @@ class Command(BaseCommand):
|
||||||
orders[0].mark_as_paid(request=None)
|
orders[0].mark_as_paid(request=None)
|
||||||
|
|
||||||
orders[1] = Order.objects.create(
|
orders[1] = Order.objects.create(
|
||||||
user=users[2], payment_method="cash", open=None
|
user=users[2], payment_method="in_person", open=None
|
||||||
)
|
)
|
||||||
orders[1].orderproductrelation_set.create(
|
orders[1].orderproductrelation_set.create(
|
||||||
product=camp_products["ticket1"], quantity=1
|
product=camp_products["ticket1"], quantity=1
|
||||||
|
@ -708,7 +777,7 @@ class Command(BaseCommand):
|
||||||
orders[1].mark_as_paid(request=None)
|
orders[1].mark_as_paid(request=None)
|
||||||
|
|
||||||
orders[2] = Order.objects.create(
|
orders[2] = Order.objects.create(
|
||||||
user=users[3], payment_method="cash", open=None
|
user=users[3], payment_method="in_person", open=None
|
||||||
)
|
)
|
||||||
orders[2].orderproductrelation_set.create(
|
orders[2].orderproductrelation_set.create(
|
||||||
product=camp_products["ticket2"], quantity=1
|
product=camp_products["ticket2"], quantity=1
|
||||||
|
@ -722,7 +791,7 @@ class Command(BaseCommand):
|
||||||
orders[2].mark_as_paid(request=None)
|
orders[2].mark_as_paid(request=None)
|
||||||
|
|
||||||
orders[3] = Order.objects.create(
|
orders[3] = Order.objects.create(
|
||||||
user=users[4], payment_method="cash", open=None
|
user=users[4], payment_method="in_person", open=None
|
||||||
)
|
)
|
||||||
orders[3].orderproductrelation_set.create(
|
orders[3].orderproductrelation_set.create(
|
||||||
product=global_products["product0"], quantity=1
|
product=global_products["product0"], quantity=1
|
||||||
|
@ -1189,6 +1258,13 @@ class Command(BaseCommand):
|
||||||
mailing_list="content@example.com",
|
mailing_list="content@example.com",
|
||||||
permission_set="contentteam_permission",
|
permission_set="contentteam_permission",
|
||||||
)
|
)
|
||||||
|
teams["economy"] = Team.objects.create(
|
||||||
|
name="Economy",
|
||||||
|
description="The Economy Team handles the money and accounts.",
|
||||||
|
camp=camp,
|
||||||
|
mailing_list="economy@example.com",
|
||||||
|
permission_set="economyteam_permission",
|
||||||
|
)
|
||||||
|
|
||||||
return teams
|
return teams
|
||||||
|
|
||||||
|
@ -1600,6 +1676,14 @@ class Command(BaseCommand):
|
||||||
for i in range(0, 6):
|
for i in range(0, 6):
|
||||||
TokenFind.objects.create(token=tokens[i], user=users[1])
|
TokenFind.objects.create(token=tokens[i], user=users[1])
|
||||||
|
|
||||||
|
def create_camp_expenses(self, camp):
|
||||||
|
self.output(f"Creating expenses for {camp}...")
|
||||||
|
ExpenseFactory.create_batch(200, camp=camp)
|
||||||
|
|
||||||
|
def create_camp_revenues(self, camp):
|
||||||
|
self.output(f"Creating revenues for {camp}...")
|
||||||
|
RevenueFactory.create_batch(20, camp=camp)
|
||||||
|
|
||||||
def output(self, message):
|
def output(self, message):
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
"%s: %s" % (timezone.now().strftime("%Y-%m-%d %H:%M:%S"), message)
|
"%s: %s" % (timezone.now().strftime("%Y-%m-%d %H:%M:%S"), message)
|
||||||
|
@ -1610,6 +1694,13 @@ class Command(BaseCommand):
|
||||||
self.output(
|
self.output(
|
||||||
self.style.SUCCESS("----------[ Running bootstrap-devsite ]----------")
|
self.style.SUCCESS("----------[ Running bootstrap-devsite ]----------")
|
||||||
)
|
)
|
||||||
|
self.output(
|
||||||
|
self.style.SUCCESS(
|
||||||
|
"----------[ Deleting all data from database ]----------"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
call_command("flush", "--noinput")
|
||||||
|
|
||||||
self.output(self.style.SUCCESS("----------[ Global stuff ]----------"))
|
self.output(self.style.SUCCESS("----------[ Global stuff ]----------"))
|
||||||
|
|
||||||
camps = self.create_camps()
|
camps = self.create_camps()
|
||||||
|
@ -1628,6 +1719,8 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
quickfeedback_options = self.create_quickfeedback_options()
|
quickfeedback_options = self.create_quickfeedback_options()
|
||||||
|
|
||||||
|
self.create_credebtors()
|
||||||
|
|
||||||
for (camp, read_only) in camps:
|
for (camp, read_only) in camps:
|
||||||
year = camp.camp.lower.year
|
year = camp.camp.lower.year
|
||||||
|
|
||||||
|
@ -1635,7 +1728,7 @@ class Command(BaseCommand):
|
||||||
self.style.SUCCESS("----------[ Bornhack {} ]----------".format(year))
|
self.style.SUCCESS("----------[ Bornhack {} ]----------".format(year))
|
||||||
)
|
)
|
||||||
|
|
||||||
if year < 2021:
|
if year < 2022:
|
||||||
ticket_types = self.create_camp_ticket_types(camp)
|
ticket_types = self.create_camp_ticket_types(camp)
|
||||||
|
|
||||||
camp_products = self.create_camp_products(
|
camp_products = self.create_camp_products(
|
||||||
|
@ -1716,6 +1809,10 @@ class Command(BaseCommand):
|
||||||
tokens = self.create_camp_tokens(camp)
|
tokens = self.create_camp_tokens(camp)
|
||||||
|
|
||||||
self.create_camp_token_finds(camp, tokens, users)
|
self.create_camp_token_finds(camp, tokens, users)
|
||||||
|
|
||||||
|
self.create_camp_expenses(camp)
|
||||||
|
|
||||||
|
self.create_camp_revenues(camp)
|
||||||
else:
|
else:
|
||||||
self.output("Not creating anything for this year yet")
|
self.output("Not creating anything for this year yet")
|
||||||
|
|
Loading…
Reference in a new issue