add initial POS stuff
This commit is contained in:
parent
6d97d4b603
commit
001ba2d955
|
@ -1,3 +1,7 @@
|
|||
from camps.mixins import CampViewMixin
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.shortcuts import get_object_or_404
|
||||
from economy.models import Pos
|
||||
from utils.mixins import RaisePermissionRequiredMixin
|
||||
|
||||
|
||||
|
@ -37,3 +41,27 @@ class ContentTeamPermissionMixin(RaisePermissionRequiredMixin):
|
|||
"camps.backoffice_permission",
|
||||
"camps.contentteam_permission",
|
||||
)
|
||||
|
||||
|
||||
class PosViewMixin(CampViewMixin):
|
||||
"""A mixin to set self.pos based on pos_slug in url kwargs."""
|
||||
|
||||
def setup(self, *args, **kwargs):
|
||||
super().setup(*args, **kwargs)
|
||||
self.pos = get_object_or_404(
|
||||
Pos, team__camp=self.camp, slug=self.kwargs["pos_slug"]
|
||||
)
|
||||
|
||||
def get_permission_required(self):
|
||||
"""
|
||||
This view requires two permissions, camps.backoffice_permission and the permission_set for the team in question.
|
||||
"""
|
||||
if not self.pos.team.permission_set:
|
||||
raise PermissionDenied("No permissions set defined for this team")
|
||||
perms = ["camps.backoffice_permission"]
|
||||
return perms
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
context = super().get_context_data(*args, **kwargs)
|
||||
context["pos"] = self.pos
|
||||
return context
|
||||
|
|
28
src/backoffice/templates/includes/pos_list_table.html
Normal file
28
src/backoffice/templates/includes/pos_list_table.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
<table class="table table-striped{% if not nodatatable %} datatable{% endif %}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Team</th>
|
||||
<th>Slug</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pos in pos_list %}
|
||||
<tr>
|
||||
<td><a href="{% url 'backoffice:pos_detail' camp_slug=camp.slug pos_slug=pos.slug %}">{{ pos.name }}</a></td>
|
||||
<td>{{ pos.team }}</td>
|
||||
<td>{{ pos.slug }}</td>
|
||||
<td>
|
||||
<div class="btn-group-vertical">
|
||||
<a href="{% url 'backoffice:pos_detail' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-primary"><i class="fas fa-search"></i> Details</a>
|
||||
{% if perms.camps.orgateam_permission %}
|
||||
<a href="{% url 'backoffice:pos_update' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-primary"><i class="fas fa-edit"></i> Update</a>
|
||||
<a href="{% url 'backoffice:pos_delete' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-danger"><i class="fas fa-times"></i> Delete</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
34
src/backoffice/templates/includes/posreport_list_table.html
Normal file
34
src/backoffice/templates/includes/posreport_list_table.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<table class="table table-striped{% if not nodatatable %} datatable{% endif %}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Pos</th>
|
||||
<th>Bank Responsible</th>
|
||||
<th>Pos Responsible</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for pr in posreport_list %}
|
||||
<tr>
|
||||
<td><a href="{% url 'backoffice:posreport_detail' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=pr.uuid %}">{{ pr.date }}</a></td>
|
||||
<td>{{ pr.pos.name }}</td>
|
||||
<td>{{ pr.bank_responsible }}</td>
|
||||
<td>{{ pr.pos_responsible }}</td>
|
||||
<td>
|
||||
<div class="btn-group-vertical">
|
||||
<a href="{% url 'backoffice:posreport_detail' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=pr.uuid %}" class="btn btn-primary"><i class="fas fa-search"></i> Details</a>
|
||||
{% if request.user == pr.pos.bank_responsible %}
|
||||
<a href="{% url 'backoffice:posreport_bank_count_start' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=pr.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Bank Count Start</a>
|
||||
<a href="{% url 'backoffice:posreport_bank_count_end' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=pr.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Bank Count End</a>
|
||||
{% endif %}
|
||||
{% if request.user == pr.pos.pos_responsible %}
|
||||
<a href="{% url 'backoffice:posreport_pos_count_start' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=pr.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Pos Count Start</a>
|
||||
<a href="{% url 'backoffice:posreport_pos_count_end' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=pr.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Pos Count End</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
|
@ -166,6 +166,12 @@
|
|||
<h4 class="list-group-item-heading">Proxied Content</h4>
|
||||
<p class="list-group-item-text">Use this view to see proxied content</p>
|
||||
</a>
|
||||
|
||||
<h3>Point of Sale</h3>
|
||||
<a href="{% url 'backoffice:pos_list' camp_slug=camp.slug %}" class="list-group-item">
|
||||
<h4 class="list-group-item-heading">Point of Sale</h4>
|
||||
<p class="list-group-item-text">Use this view to see a list of Pos objects, and to see and submit PosReports</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
18
src/backoffice/templates/pos_delete.html
Normal file
18
src/backoffice/templates/pos_delete.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Delete Pos {{ pos.name }}?</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="lead">This Pos has <b>{{ pos.pos_reports.count }}</b> PosReports which will also be deleted.</p>
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<button type="submit" name="Delete" class="btn btn-danger"><i class="fas fa-times"></i> Yes, Delete it</button>
|
||||
<a href="{% url 'backoffice:pos_detail' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-default"><i class="fas fa-undo"></i> Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
42
src/backoffice/templates/pos_detail.html
Normal file
42
src/backoffice/templates/pos_detail.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}
|
||||
{{ pos.name }} | Pos | BackOffice | {{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{{ pos.name }} | Pos | BackOffice</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<a href="{% url 'backoffice:pos_update' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-primary"><i class="fas fa-edit"></i> Update Pos</a>
|
||||
<a href="{% url 'backoffice:pos_delete' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-danger"><i class="fas fa-times"></i> Delete Pos</a>
|
||||
<a href="{% url 'backoffice:pos_list' camp_slug=camp.slug %}" class="btn btn-default"><i class="fas fa-undo"></i> Pos List</a>
|
||||
</p>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Pos Name</th>
|
||||
<td>{{ pos.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Team</th>
|
||||
<td>{{ pos.team }}</p>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Pos Reports</h3>
|
||||
{% if pos.pos_reports.exists %}
|
||||
{% include "includes/posreport_list_table.html" with posreport_list=pos.pos_reports.all %}
|
||||
{% else %}
|
||||
None found
|
||||
{% endif %}
|
||||
<br>
|
||||
{% if perms.camps.orgateam_permission %}
|
||||
<a href="{% url 'backoffice:posreport_create' camp_slug=camp.slug pos_slug=pos.slug %}" class="btn btn-success"><i class="fas fa-plus"></i> Create PosReport</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
21
src/backoffice/templates/pos_form.html
Normal file
21
src/backoffice/templates/pos_form.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% if request.resolver_match.url_name == "pos_update" %}Update{% else %}Create new{% endif %} Pos</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Save</button>
|
||||
<a href="{% url 'backoffice:pos_list' camp_slug=camp.slug %}" class="btn btn-default"><i class="fas fa-undo"></i> Cancel</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
29
src/backoffice/templates/pos_list.html
Normal file
29
src/backoffice/templates/pos_list.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load bornhack %}
|
||||
|
||||
{% block title %}
|
||||
Pos List | Backoffice | {{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title">Pos List - BackOffice</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>A <i>Pos</i> is a place where we sell stuff for DKK and/or HAX.</p>
|
||||
{% if not pos_list %}
|
||||
<p class="lead">No Pos found.</p>
|
||||
{% else %}
|
||||
<p>
|
||||
<a class="btn btn-default" href="{% url 'backoffice:index' camp_slug=camp.slug %}"><i class="fas fa-undo"></i> Backoffice</a>
|
||||
{% include "includes/pos_list_table.html" %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
{% if perms.camps.orgateam_permission %}
|
||||
<a class="btn btn-success" href="{% url 'backoffice:pos_create' camp_slug=camp.slug %}"><i class="fas fa-plus"></i> Create Pos</a>
|
||||
{% endif %}
|
||||
<a class="btn btn-default" href="{% url 'backoffice:index' camp_slug=camp.slug %}"><i class="fas fa-undo"></i> Backoffice</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
115
src/backoffice/templates/posreport_detail.html
Normal file
115
src/backoffice/templates/posreport_detail.html
Normal file
|
@ -0,0 +1,115 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}
|
||||
PosReport {{ posreport.date }} {{ posreport.pos.name }} | Pos | BackOffice | {{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">PosReport {{ posreport.date }} {{ posreport.pos.name }} | Pos | BackOffice</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
{% if "camps.orgateam_permission" in perms %}
|
||||
<a href="{% url 'backoffice:posreport_update' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=posreport.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Update</a>
|
||||
{% endif %}
|
||||
{% if request.user == posreport.bank_responsible %}
|
||||
<a href="{% url 'backoffice:posreport_bank_count_start' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=posreport.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Bank Count Start</a>
|
||||
<a href="{% url 'backoffice:posreport_bank_count_end' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=posreport.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Bank Count End</a>
|
||||
{% endif %}
|
||||
{% if request.user == posreport.pos_responsible %}
|
||||
<a href="{% url 'backoffice:posreport_pos_count_start' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=posreport.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Pos Count Start</a>
|
||||
<a href="{% url 'backoffice:posreport_pos_count_end' camp_slug=camp.slug pos_slug=pos.slug posreport_uuid=posreport.uuid %}" class="btn btn-primary"><i class="fas fa-edit"></i> Pos Count End</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>PosReport UUID</th>
|
||||
<td>{{ posreport.uuid }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PosReport Date</th>
|
||||
<td>{{ posreport.date }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Pos Name</th>
|
||||
<td>{{ posreport.pos.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Team</th>
|
||||
<td>{{ posreport.pos.team }}</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Bank Responsible</th>
|
||||
<td>{{ posreport.bank_responsible }}</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Pos Responsible</th>
|
||||
<td>{{ posreport.pos_responsible }}</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Counts</th>
|
||||
<td>
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>What</th>
|
||||
<th>Bank Start</th>
|
||||
<th>Bank End</th>
|
||||
<th>Pos Start</th>
|
||||
<th>Pos End</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>DKK</td>
|
||||
<td>{{ posreport.bank_count_dkk_start }}</td>
|
||||
<td>{{ posreport.bank_count_dkk_end }}</td>
|
||||
<td>{{ posreport.pos_count_dkk_start }}</td>
|
||||
<td>{{ posreport.pos_count_dkk_end }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5 HAX</td>
|
||||
<td>{{ posreport.bank_count_hax5_start }}</td>
|
||||
<td>{{ posreport.bank_count_hax5_end }}</td>
|
||||
<td>{{ posreport.pos_count_hax5_start }}</td>
|
||||
<td>{{ posreport.pos_count_hax5_end }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>10 HAX</td>
|
||||
<td>{{ posreport.bank_count_hax10_start }}</td>
|
||||
<td>{{ posreport.bank_count_hax10_end }}</td>
|
||||
<td>{{ posreport.pos_count_hax10_start }}</td>
|
||||
<td>{{ posreport.pos_count_hax10_end }}</td>
|
||||
</tr>
|
||||
<td>20 HAX</td>
|
||||
<td>{{ posreport.bank_count_hax20_start }}</td>
|
||||
<td>{{ posreport.bank_count_hax20_end }}</td>
|
||||
<td>{{ posreport.pos_count_hax20_start }}</td>
|
||||
<td>{{ posreport.pos_count_hax20_end }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>50 HAX</td>
|
||||
<td>{{ posreport.bank_count_hax50_start }}</td>
|
||||
<td>{{ posreport.bank_count_hax50_end }}</td>
|
||||
<td>{{ posreport.pos_count_hax50_start }}</td>
|
||||
<td>{{ posreport.pos_count_hax50_end }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>100 HAX</td>
|
||||
<td>{{ posreport.bank_count_hax100_start }}</td>
|
||||
<td>{{ posreport.bank_count_hax100_end }}</td>
|
||||
<td>{{ posreport.pos_count_hax100_start }}</td>
|
||||
<td>{{ posreport.pos_count_hax100_end }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
21
src/backoffice/templates/posreport_form.html
Normal file
21
src/backoffice/templates/posreport_form.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% if request.resolver_match.url_name == "posreport_create" %}Create{% else %}Update{% endif %} PosReport</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-success"><i class="fas fa-check"></i> Save</button>
|
||||
<a href="{% url 'backoffice:pos_list' camp_slug=camp.slug %}" class="btn btn-default"><i class="fas fa-undo"></i> Cancel</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
25
src/backoffice/templates/posreport_list.html
Normal file
25
src/backoffice/templates/posreport_list.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load bornhack %}
|
||||
|
||||
{% block title %}
|
||||
PosReport List for {{ pos.name }} | Backoffice | {{ block.super }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title">PosReport List for {{ pos.name }} - BackOffice</h3></div>
|
||||
<div class="panel-body">
|
||||
<p>A <i>PosReport</i> contains the start and end counts of HAX+DKK from a point-of-sale and the exported JSON file from the Pos.</p>
|
||||
{% if not pos_list %}
|
||||
<p class="lead">No Pos found.</p>
|
||||
{% else %}
|
||||
<p>
|
||||
{% include "includes/posreport_list_table.html" %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p>
|
||||
<a class="btn btn-default" href="{% url 'backoffice:index' camp_slug=camp.slug %}"><i class="fas fa-undo"></i> Backoffice</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
|
@ -60,6 +60,18 @@ from .views import (
|
|||
MerchandiseToOrderView,
|
||||
OutgoingEmailMassUpdateView,
|
||||
PendingProposalsView,
|
||||
PosCreateView,
|
||||
PosDeleteView,
|
||||
PosDetailView,
|
||||
PosListView,
|
||||
PosReportBankCountEndView,
|
||||
PosReportBankCountStartView,
|
||||
PosReportCreateView,
|
||||
PosReportDetailView,
|
||||
PosReportPosCountEndView,
|
||||
PosReportPosCountStartView,
|
||||
PosReportUpdateView,
|
||||
PosUpdateView,
|
||||
ProductHandoutView,
|
||||
ReimbursementCreateUserSelectView,
|
||||
ReimbursementCreateView,
|
||||
|
@ -632,4 +644,77 @@ urlpatterns = [
|
|||
OutgoingEmailMassUpdateView.as_view(),
|
||||
name="outgoing_email_release",
|
||||
),
|
||||
# point-of-sale
|
||||
path(
|
||||
"pos/",
|
||||
include(
|
||||
[
|
||||
path("", PosListView.as_view(), name="pos_list",),
|
||||
path("create/", PosCreateView.as_view(), name="pos_create",),
|
||||
path(
|
||||
"<slug:pos_slug>/",
|
||||
include(
|
||||
[
|
||||
path("", PosDetailView.as_view(), name="pos_detail",),
|
||||
path(
|
||||
"update/", PosUpdateView.as_view(), name="pos_update",
|
||||
),
|
||||
path(
|
||||
"delete/", PosDeleteView.as_view(), name="pos_delete",
|
||||
),
|
||||
path(
|
||||
"reports/",
|
||||
include(
|
||||
[
|
||||
path(
|
||||
"create/",
|
||||
PosReportCreateView.as_view(),
|
||||
name="posreport_create",
|
||||
),
|
||||
path(
|
||||
"<uuid:posreport_uuid>/",
|
||||
include(
|
||||
[
|
||||
path(
|
||||
"",
|
||||
PosReportDetailView.as_view(),
|
||||
name="posreport_detail",
|
||||
),
|
||||
path(
|
||||
"update/",
|
||||
PosReportUpdateView.as_view(),
|
||||
name="posreport_update",
|
||||
),
|
||||
path(
|
||||
"bankcount/start/",
|
||||
PosReportBankCountStartView.as_view(),
|
||||
name="posreport_bank_count_start",
|
||||
),
|
||||
path(
|
||||
"bankcount/end/",
|
||||
PosReportBankCountEndView.as_view(),
|
||||
name="posreport_bank_count_end",
|
||||
),
|
||||
path(
|
||||
"poscount/start/",
|
||||
PosReportPosCountStartView.as_view(),
|
||||
name="posreport_pos_count_start",
|
||||
),
|
||||
path(
|
||||
"poscount/end/",
|
||||
PosReportPosCountEndView.as_view(),
|
||||
name="posreport_pos_count_end",
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -20,7 +20,15 @@ from django.utils import timezone
|
|||
from django.utils.safestring import mark_safe
|
||||
from django.views.generic import DetailView, ListView, TemplateView
|
||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||
from economy.models import Chain, Credebtor, Expense, Reimbursement, Revenue
|
||||
from economy.models import (
|
||||
Chain,
|
||||
Credebtor,
|
||||
Expense,
|
||||
Pos,
|
||||
PosReport,
|
||||
Reimbursement,
|
||||
Revenue,
|
||||
)
|
||||
from facilities.models import (
|
||||
Facility,
|
||||
FacilityFeedback,
|
||||
|
@ -59,6 +67,7 @@ from .mixins import (
|
|||
EconomyTeamPermissionMixin,
|
||||
InfoTeamPermissionMixin,
|
||||
OrgaTeamPermissionMixin,
|
||||
PosViewMixin,
|
||||
RaisePermissionRequiredMixin,
|
||||
)
|
||||
|
||||
|
@ -1955,3 +1964,219 @@ class OutgoingEmailMassUpdateView(CampViewMixin, OrgaTeamPermissionMixin, FormVi
|
|||
def get_success_url(self, *args, **kwargs):
|
||||
"""Return to the backoffice index."""
|
||||
return reverse("backoffice:index", kwargs={"camp_slug": self.camp.slug})
|
||||
|
||||
|
||||
################################
|
||||
# Pos and PosReport views
|
||||
|
||||
|
||||
class PosListView(CampViewMixin, RaisePermissionRequiredMixin, ListView):
|
||||
"""Show a list of Pos this user has access to (through team memberships)."""
|
||||
|
||||
permission_required = "camps.backoffice_permission"
|
||||
model = Pos
|
||||
template_name = "pos_list.html"
|
||||
|
||||
|
||||
class PosDetailView(PosViewMixin, RaisePermissionRequiredMixin, DetailView):
|
||||
"""Show details for a Pos."""
|
||||
|
||||
model = Pos
|
||||
template_name = "pos_detail.html"
|
||||
slug_url_kwarg = "pos_slug"
|
||||
|
||||
|
||||
class PosCreateView(CampViewMixin, OrgaTeamPermissionMixin, CreateView):
|
||||
"""Create a new Pos (orga only)."""
|
||||
|
||||
model = Pos
|
||||
template_name = "pos_form.html"
|
||||
fields = ["name", "team"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"].fields["team"].queryset = Team.objects.filter(camp=self.camp)
|
||||
return context
|
||||
|
||||
|
||||
class PosUpdateView(CampViewMixin, OrgaTeamPermissionMixin, UpdateView):
|
||||
"""Update a Pos."""
|
||||
|
||||
model = Pos
|
||||
template_name = "pos_form.html"
|
||||
slug_url_kwarg = "pos_slug"
|
||||
fields = ["name", "team"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"].fields["team"].queryset = Team.objects.filter(camp=self.camp)
|
||||
return context
|
||||
|
||||
|
||||
class PosDeleteView(CampViewMixin, OrgaTeamPermissionMixin, DeleteView):
|
||||
model = Pos
|
||||
template_name = "pos_delete.html"
|
||||
slug_url_kwarg = "pos_slug"
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
self.get_object().pos_reports.all().delete()
|
||||
return super().delete(*args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
messages.success(
|
||||
self.request, "The Pos and all related PosReports has been deleted"
|
||||
)
|
||||
return reverse("backoffice:pos_list", kwargs={"camp_slug": self.camp.slug})
|
||||
|
||||
|
||||
class PosReportCreateView(PosViewMixin, RaisePermissionRequiredMixin, CreateView):
|
||||
"""Use this view to create new PosReports."""
|
||||
|
||||
model = PosReport
|
||||
fields = ["date", "bank_responsible", "pos_responsible"]
|
||||
template_name = "posreport_form.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"].fields["bank_responsible"].queryset = Team.objects.get(
|
||||
camp=self.camp, name="Orga",
|
||||
).approved_members.all()
|
||||
context["form"].fields[
|
||||
"pos_responsible"
|
||||
].queryset = self.pos.team.responsible_members.all()
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
"""
|
||||
Set Pos before saving
|
||||
"""
|
||||
pr = form.save(commit=False)
|
||||
pr.pos = self.pos
|
||||
pr.save()
|
||||
messages.success(self.request, f"New PosReport created successfully!")
|
||||
return redirect(
|
||||
reverse(
|
||||
"backoffice:posreport_detail",
|
||||
kwargs={
|
||||
"camp_slug": self.camp.slug,
|
||||
"pos_slug": self.pos.slug,
|
||||
"posreport_uuid": pr.uuid,
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class PosReportUpdateView(PosViewMixin, RaisePermissionRequiredMixin, UpdateView):
|
||||
"""Use this view to update PosReports."""
|
||||
|
||||
model = PosReport
|
||||
fields = ["date", "bank_responsible", "pos_responsible"]
|
||||
template_name = "posreport_form.html"
|
||||
pk_url_kwarg = "posreport_uuid"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"].fields["bank_responsible"].queryset = Team.objects.get(
|
||||
camp=self.camp, name="Orga",
|
||||
).approved_members.all()
|
||||
context["form"].fields[
|
||||
"pos_responsible"
|
||||
].queryset = self.pos.team.responsible_members.all()
|
||||
return context
|
||||
|
||||
|
||||
class PosReportDetailView(PosViewMixin, RaisePermissionRequiredMixin, DetailView):
|
||||
"""Show details for a PosReport."""
|
||||
|
||||
model = PosReport
|
||||
template_name = "posreport_detail.html"
|
||||
pk_url_kwarg = "posreport_uuid"
|
||||
|
||||
|
||||
class PosReportBankCountStartView(
|
||||
PosViewMixin, RaisePermissionRequiredMixin, UpdateView
|
||||
):
|
||||
"""The bank responsible for a PosReport uses this view to add day-start HAX and DKK counts to a PosReport."""
|
||||
|
||||
model = PosReport
|
||||
template_name = "posreport_form.html"
|
||||
fields = [
|
||||
"bank_count_dkk_start",
|
||||
"bank_count_hax5_start",
|
||||
"bank_count_hax10_start",
|
||||
"bank_count_hax20_start",
|
||||
"bank_count_hax50_start",
|
||||
"bank_count_hax100_start",
|
||||
]
|
||||
pk_url_kwarg = "posreport_uuid"
|
||||
|
||||
def setup(self, *args, **kwargs):
|
||||
super().setup(*args, **kwargs)
|
||||
if self.request.user != self.get_object().bank_responsible:
|
||||
raise PermissionDenied("Only the bank responsible can do this")
|
||||
|
||||
|
||||
class PosReportBankCountEndView(PosViewMixin, RaisePermissionRequiredMixin, UpdateView):
|
||||
"""The bank responsible for a PosReport uses this view to add day-end HAX and DKK counts to a PosReport."""
|
||||
|
||||
model = PosReport
|
||||
template_name = "posreport_form.html"
|
||||
fields = [
|
||||
"bank_count_dkk_end",
|
||||
"bank_count_hax5_end",
|
||||
"bank_count_hax10_end",
|
||||
"bank_count_hax20_end",
|
||||
"bank_count_hax50_end",
|
||||
"bank_count_hax100_end",
|
||||
]
|
||||
pk_url_kwarg = "posreport_uuid"
|
||||
|
||||
def setup(self, *args, **kwargs):
|
||||
super().setup(*args, **kwargs)
|
||||
if self.request.user != self.get_object().bank_responsible:
|
||||
raise PermissionDenied("Only the bank responsible can do this")
|
||||
|
||||
|
||||
class PosReportPosCountStartView(
|
||||
PosViewMixin, RaisePermissionRequiredMixin, UpdateView
|
||||
):
|
||||
"""The Pos responsible for a PosReport uses this view to add day-start HAX and DKK counts to a PosReport."""
|
||||
|
||||
model = PosReport
|
||||
template_name = "posreport_form.html"
|
||||
fields = [
|
||||
"pos_count_dkk_start",
|
||||
"pos_count_hax5_start",
|
||||
"pos_count_hax10_start",
|
||||
"pos_count_hax20_start",
|
||||
"pos_count_hax50_start",
|
||||
"pos_count_hax100_start",
|
||||
]
|
||||
pk_url_kwarg = "posreport_uuid"
|
||||
|
||||
def setup(self, *args, **kwargs):
|
||||
super().setup(*args, **kwargs)
|
||||
if self.request.user != self.get_object().pos_responsible:
|
||||
raise PermissionDenied("Only the Pos responsible can do this")
|
||||
|
||||
|
||||
class PosReportPosCountEndView(PosViewMixin, RaisePermissionRequiredMixin, UpdateView):
|
||||
"""The Pos responsible for a PosReport uses this view to add day-end HAX and DKK counts to a PosReport."""
|
||||
|
||||
model = PosReport
|
||||
template_name = "posreport_form.html"
|
||||
fields = [
|
||||
"pos_count_dkk_end",
|
||||
"pos_count_hax5_end",
|
||||
"pos_count_hax10_end",
|
||||
"pos_count_hax20_end",
|
||||
"pos_count_hax50_end",
|
||||
"pos_count_hax100_end",
|
||||
"pos_json",
|
||||
]
|
||||
pk_url_kwarg = "posreport_uuid"
|
||||
|
||||
def setup(self, *args, **kwargs):
|
||||
super().setup(*args, **kwargs)
|
||||
if self.request.user != self.get_object().pos_responsible:
|
||||
raise PermissionDenied("Only the pos responsible can do this")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Chain, Credebtor, Expense, Reimbursement, Revenue
|
||||
from .models import Chain, Credebtor, Expense, Pos, PosReport, Reimbursement, Revenue
|
||||
|
||||
###############################
|
||||
# chains and credebtors
|
||||
|
@ -113,3 +113,18 @@ class ReimbursementAdmin(admin.ModelAdmin):
|
|||
list_filter = ["camp", "user", "reimbursement_user", "paid"]
|
||||
list_display = ["camp", "user", "reimbursement_user", "paid", "notes", "get_amount"]
|
||||
search_fields = ["user__username", "reimbursement_user__username", "notes"]
|
||||
|
||||
|
||||
################################
|
||||
# pos
|
||||
|
||||
|
||||
@admin.register(Pos)
|
||||
class PosAdmin(admin.ModelAdmin):
|
||||
list_display = ["name", "team"]
|
||||
list_filter = ["team"]
|
||||
|
||||
|
||||
@admin.register(PosReport)
|
||||
class PosReportAdmin(admin.ModelAdmin):
|
||||
list_display = ["uuid", "pos"]
|
||||
|
|
284
src/economy/migrations/0011_pos_posreport.py
Normal file
284
src/economy/migrations/0011_pos_posreport.py
Normal file
|
@ -0,0 +1,284 @@
|
|||
# Generated by Django 3.1 on 2020-08-10 23:41
|
||||
|
||||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("teams", "0052_team_permission_set"),
|
||||
("economy", "0010_auto_20190330_1045"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Pos",
|
||||
fields=[
|
||||
(
|
||||
"uuid",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("updated", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"name",
|
||||
models.CharField(
|
||||
help_text="The point-of-sale name", max_length=255
|
||||
),
|
||||
),
|
||||
(
|
||||
"slug",
|
||||
models.SlugField(
|
||||
blank=True,
|
||||
help_text="Url slug for this POS. Leave blank to generate based on POS name.",
|
||||
max_length=255,
|
||||
),
|
||||
),
|
||||
(
|
||||
"team",
|
||||
models.ForeignKey(
|
||||
help_text="The Team managning this POS",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="teams.team",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"ordering": ["name"],},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="PosReport",
|
||||
fields=[
|
||||
(
|
||||
"uuid",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("updated", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"date",
|
||||
models.DateField(
|
||||
help_text="The date this report covers (pick the starting date if opening hours cross midnight)."
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_json",
|
||||
models.JSONField(
|
||||
blank=True,
|
||||
help_text="The JSON exported from the external POS system",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_dkk_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax5_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax10_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax20_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax50_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax100_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_dkk_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed out from the bank to the POS at the start of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax5_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax10_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax20_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax50_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax100_start",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_dkk_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax5_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax10_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax20_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax50_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_count_hax100_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_dkk_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed back from the POS to the bank at the end of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax5_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax10_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax20_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax50_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_count_hax100_end",
|
||||
models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"bank_responsible",
|
||||
models.ForeignKey(
|
||||
help_text="The banker responsible for this PosReport",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="pos_reports_banker",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos",
|
||||
models.ForeignKey(
|
||||
help_text="The Pos this PosReport belongs to.",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="pos_reports",
|
||||
to="economy.pos",
|
||||
),
|
||||
),
|
||||
(
|
||||
"pos_responsible",
|
||||
models.ForeignKey(
|
||||
help_text="The POS person responsible for this PosReport",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="pos_reports_poser",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={"abstract": False,},
|
||||
),
|
||||
]
|
|
@ -3,6 +3,7 @@ import os
|
|||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from utils.models import CampRelatedModel, CreatedUpdatedModel, UUIDModel
|
||||
from utils.slugs import unique_slugify
|
||||
|
||||
|
@ -465,3 +466,224 @@ class Reimbursement(CampRelatedModel, UUIDModel):
|
|||
for expense in self.expenses.filter(paid_by_bornhack=False):
|
||||
amount += expense.amount
|
||||
return amount
|
||||
|
||||
|
||||
class Pos(CampRelatedModel, UUIDModel):
|
||||
"""A Pos is a point-of-sale like the bar or infodesk."""
|
||||
|
||||
class Meta:
|
||||
ordering = ["name"]
|
||||
|
||||
name = models.CharField(max_length=255, help_text="The point-of-sale name")
|
||||
|
||||
slug = models.SlugField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text="Url slug for this POS. Leave blank to generate based on POS name.",
|
||||
)
|
||||
|
||||
team = models.ForeignKey(
|
||||
"teams.Team", on_delete=models.PROTECT, help_text="The Team managning this POS",
|
||||
)
|
||||
|
||||
def save(self, **kwargs):
|
||||
"""Generate slug if needed."""
|
||||
if not self.slug:
|
||||
self.slug = unique_slugify(
|
||||
self.name,
|
||||
slugs_in_use=self.__class__.objects.filter(
|
||||
team__camp=self.team.camp
|
||||
).values_list("slug", flat=True),
|
||||
)
|
||||
super().save(**kwargs)
|
||||
|
||||
@property
|
||||
def camp(self):
|
||||
return self.team.camp
|
||||
|
||||
camp_filter = "team__camp"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
"backoffice:pos_detail",
|
||||
kwargs={"camp_slug": self.team.camp.slug, "pos_slug": self.slug},
|
||||
)
|
||||
|
||||
|
||||
class PosReport(CampRelatedModel, UUIDModel):
|
||||
"""A PosReport contains the HAX/DKK counts and the csv report from the POS system."""
|
||||
|
||||
pos = models.ForeignKey(
|
||||
"economy.Pos",
|
||||
on_delete=models.PROTECT,
|
||||
related_name="pos_reports",
|
||||
help_text="The Pos this PosReport belongs to.",
|
||||
)
|
||||
|
||||
bank_responsible = models.ForeignKey(
|
||||
"auth.User",
|
||||
on_delete=models.PROTECT,
|
||||
related_name="pos_reports_banker",
|
||||
help_text="The banker responsible for this PosReport",
|
||||
)
|
||||
|
||||
pos_responsible = models.ForeignKey(
|
||||
"auth.User",
|
||||
on_delete=models.PROTECT,
|
||||
related_name="pos_reports_poser",
|
||||
help_text="The POS person responsible for this PosReport",
|
||||
)
|
||||
|
||||
date = models.DateField(
|
||||
help_text="The date this report covers (pick the starting date if opening hours cross midnight).",
|
||||
)
|
||||
|
||||
pos_json = models.JSONField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="The JSON exported from the external POS system",
|
||||
)
|
||||
|
||||
# bank count start of day
|
||||
|
||||
bank_count_dkk_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax5_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax10_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax20_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax50_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax100_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins handed out from the bank to the POS at the start of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
# POS count start of day
|
||||
|
||||
pos_count_dkk_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed out from the bank to the POS at the start of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax5_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax10_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax20_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax50_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax100_start = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins received by the POS from the bank at the start of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
# bank count end of day
|
||||
|
||||
bank_count_dkk_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax5_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax10_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax20_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax50_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
bank_count_hax100_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins handed back from the POS to the bank at the end of the business day (counted by the bank responsible)",
|
||||
)
|
||||
|
||||
# pos count end of day
|
||||
|
||||
pos_count_dkk_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of DKK handed back from the POS to the bank at the end of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax5_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 5 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax10_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 10 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax20_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 20 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax50_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 50 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
pos_count_hax100_end = models.PositiveIntegerField(
|
||||
default=0,
|
||||
help_text="The number of 100 HAX coins received by the bank from the POS at the end of the business day (counted by the POS responsible)",
|
||||
)
|
||||
|
||||
@property
|
||||
def camp(self):
|
||||
return self.pos.team.camp
|
||||
|
||||
camp_filter = "pos__team__camp"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
"backoffice:posreport_detail",
|
||||
kwargs={
|
||||
"camp_slug": self.camp.slug,
|
||||
"pos_slug": self.pos.slug,
|
||||
"posreport_uuid": self.uuid,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Django==3.0.8
|
||||
Django==3.1
|
||||
channels==2.4.0
|
||||
channels-redis==3.0.1
|
||||
|
||||
|
|
Loading…
Reference in a new issue