Add bank details and file uploads for reimbursement claims
This commit is contained in:
parent
8ef85addd0
commit
96e45c0c5c
@ -23,7 +23,7 @@
|
|||||||
{% block maincontent %}
|
{% block maincontent %}
|
||||||
<h1>{% if request.resolver_match.url_name == 'claim_new' %}New{% else %}Edit{% endif %} reimbursement claim</h1>
|
<h1>{% if request.resolver_match.url_name == 'claim_new' %}New{% else %}Edit{% endif %} reimbursement claim</h1>
|
||||||
|
|
||||||
<form class="ui form" method="POST">
|
<form class="ui form" method="POST" enctype="multipart/form-data">
|
||||||
<div class="ui disabled inline grid field">
|
<div class="ui disabled inline grid field">
|
||||||
<label class="three wide column">ID</label>
|
<label class="three wide column">ID</label>
|
||||||
<input class="eleven wide column" type="text" name="id" value="{{ 'RE-{}'.format(claim.id) if claim.id != None else '' }}">
|
<input class="eleven wide column" type="text" name="id" value="{{ 'RE-{}'.format(claim.id) if claim.id != None else '' }}">
|
||||||
@ -72,6 +72,31 @@
|
|||||||
<textarea class="eleven wide column" rows="2" name="comments">{{ claim.comments }}</textarea>
|
<textarea class="eleven wide column" rows="2" name="comments">{{ claim.comments }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
|
<div class="ui required inline grid field">
|
||||||
|
<label class="three wide column">Payee name</label>
|
||||||
|
<input class="eleven wide column" type="text" name="payee_name" value="{{ claim.payee_name }}">
|
||||||
|
</div>
|
||||||
|
<div class="ui required inline grid field">
|
||||||
|
<label class="three wide column">Payee BSB</label>
|
||||||
|
<input class="eleven wide column" type="text" name="payee_bsb" value="{{ claim.payee_bsb }}">
|
||||||
|
</div>
|
||||||
|
<div class="ui required inline grid field">
|
||||||
|
<label class="three wide column">Payee account number</label>
|
||||||
|
<input class="eleven wide column" type="text" name="payee_account" value="{{ claim.payee_account }}">
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<div class="ui required inline grid field">
|
||||||
|
<label class="three wide column">Receipts</label>
|
||||||
|
<div class="eleven wide column">
|
||||||
|
<ul>
|
||||||
|
{% for claim_receipt in claim.claimreceipt_set.all() %}
|
||||||
|
<li><a href="{{ MEDIA_URL }}{{ claim_receipt.uploaded_file.name }}">{{ claim_receipt.uploaded_file.name.split('/')[-1] }}</a> <button class="ui mini red basic icon button" type="submit" name="submit" value="DeleteFile{{ claim_receipt.id }}" style="margin-left: 1em;" onclick="return confirm('Are you sure you want to delete this file? If you have any unsaved changes, you should save the claim first.');"><i class="trash icon"></i></button></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<input type="file" name="upload_file" multiple>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
<div class="ui required inline grid field">
|
<div class="ui required inline grid field">
|
||||||
<label class="three wide column">Items</label>
|
<label class="three wide column">Items</label>
|
||||||
<div class="eleven wide column"></div>
|
<div class="eleven wide column"></div>
|
||||||
@ -80,6 +105,12 @@
|
|||||||
<input type="hidden" name="items" id="items_input">
|
<input type="hidden" name="items" id="items_input">
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<div class="ui error message"></div>
|
<div class="ui error message"></div>
|
||||||
|
<div>
|
||||||
|
<h2 class="ui header">Declaration</h2>
|
||||||
|
<p>By submitting this form for processing with my MUMUS account, I agree that MUMUS Inc. will accept this communication as containing my signature for the purposes of the Electronic Transactions Acts. I certify that the information on this form is true and accurate. I acknowledge that incorrect information may result in the forfeiture of this reimbursement.</p>
|
||||||
|
<p>Under the Pay As You Go legislation and guidelines produced by the Australian Taxation Office, I state that the supply to MUMUS Inc. described on this form is wholly of a private or domestic nature for me, I have no reasonable expectation of profit or gain from the activity undertaken, and I consider that I do not meet the definition of enterprise for tax purposes. Therefore, I do not need to quote an Australian Business Number and MUMUS Inc. is not required to withhold tax from my payment.</p>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
|
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
|
||||||
<input class="ui primary button" type="submit" name='submit' value="Save">
|
<input class="ui primary button" type="submit" name='submit' value="Save">
|
||||||
<input class="ui button" type="submit" name='submit' value="Save and continue editing">
|
<input class="ui button" type="submit" name='submit' value="Save and continue editing">
|
||||||
|
@ -77,6 +77,35 @@
|
|||||||
<td>Comments</td>
|
<td>Comments</td>
|
||||||
<td>{{ claim.comments }}</td>
|
<td>{{ claim.comments }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Payee</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui list">
|
||||||
|
<div class="item">
|
||||||
|
<i class="user circle icon"></i>
|
||||||
|
<div class="content">{{ claim.payee_name }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<i class="building icon"></i>
|
||||||
|
<div class="content">BSB: {{ claim.payee_bsb }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<i class="dollar sign icon"></i>
|
||||||
|
<div class="content">Account: {{ claim.payee_account }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Receipts</td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
{% for claim_receipt in claim.claimreceipt_set.all() %}
|
||||||
|
<li><a href="{{ MEDIA_URL }}{{ claim_receipt.uploaded_file.name }}">{{ claim_receipt.uploaded_file.name.split('/')[-1] }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Items</td>
|
<td>Items</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -105,6 +105,35 @@
|
|||||||
<td>Comments</td>
|
<td>Comments</td>
|
||||||
<td>{{ claim.comments }}</td>
|
<td>{{ claim.comments }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Payee</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui list">
|
||||||
|
<div class="item">
|
||||||
|
<i class="user circle icon"></i>
|
||||||
|
<div class="content">{{ claim.payee_name }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<i class="building icon"></i>
|
||||||
|
<div class="content">BSB: {{ claim.payee_bsb }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<i class="dollar sign icon"></i>
|
||||||
|
<div class="content">Account: {{ claim.payee_account }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Receipts</td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
{% for claim_receipt in claim.claimreceipt_set.all() %}
|
||||||
|
<li><a href="{{ MEDIA_URL }}{{ claim_receipt.uploaded_file.name }}">{{ claim_receipt.uploaded_file.name.split('/')[-1] }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Items</td>
|
<td>Items</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -195,6 +195,10 @@ class ReimbursementClaim(models.Model):
|
|||||||
|
|
||||||
items = JSONField(default=[])
|
items = JSONField(default=[])
|
||||||
|
|
||||||
|
payee_name = models.TextField()
|
||||||
|
payee_bsb = models.CharField(max_length=7)
|
||||||
|
payee_account = models.TextField(max_length=20)
|
||||||
|
|
||||||
def update_state(self, user, state):
|
def update_state(self, user, state):
|
||||||
self.state = state.value
|
self.state = state.value
|
||||||
self.save()
|
self.save()
|
||||||
@ -270,7 +274,7 @@ class ReimbursementClaim(models.Model):
|
|||||||
|
|
||||||
class ClaimReceipt(models.Model):
|
class ClaimReceipt(models.Model):
|
||||||
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
|
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
|
||||||
uploaded_file = models.FileField()
|
uploaded_file = models.FileField(upload_to='receipt_uploads/%Y/%m/%d/')
|
||||||
|
|
||||||
class ClaimComment(models.Model):
|
class ClaimComment(models.Model):
|
||||||
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
|
claim = models.ForeignKey(ReimbursementClaim, on_delete=models.CASCADE)
|
||||||
|
@ -112,7 +112,7 @@ def revision_from_form(budget, revision, form):
|
|||||||
|
|
||||||
return revision
|
return revision
|
||||||
|
|
||||||
def claim_from_form(claim, form):
|
def claim_from_form(claim, form, files):
|
||||||
claim.purpose = form['purpose']
|
claim.purpose = form['purpose']
|
||||||
claim.date = form['date'] if form['date'] else None
|
claim.date = form['date'] if form['date'] else None
|
||||||
claim.budget_id = form['budget_id']
|
claim.budget_id = form['budget_id']
|
||||||
@ -121,8 +121,19 @@ def claim_from_form(claim, form):
|
|||||||
claim.state = models.ClaimState.DRAFT.value
|
claim.state = models.ClaimState.DRAFT.value
|
||||||
claim.items = json.loads(form['items'])
|
claim.items = json.loads(form['items'])
|
||||||
|
|
||||||
|
claim.payee_name = form['payee_name']
|
||||||
|
claim.payee_bsb = form['payee_bsb']
|
||||||
|
claim.payee_account = form['payee_account']
|
||||||
|
|
||||||
claim.save()
|
claim.save()
|
||||||
|
|
||||||
|
if files:
|
||||||
|
for f in files.getlist('upload_file'):
|
||||||
|
claim_receipt = models.ClaimReceipt()
|
||||||
|
claim_receipt.claim = claim
|
||||||
|
claim_receipt.uploaded_file = f
|
||||||
|
claim_receipt.save()
|
||||||
|
|
||||||
return claim
|
return claim
|
||||||
|
|
||||||
# INDEX VIEW
|
# INDEX VIEW
|
||||||
@ -392,7 +403,7 @@ def claim_new(request):
|
|||||||
claim.author = request.user
|
claim.author = request.user
|
||||||
claim.time = timezone.now()
|
claim.time = timezone.now()
|
||||||
claim.state = models.BudgetState.DRAFT.value
|
claim.state = models.BudgetState.DRAFT.value
|
||||||
claim = claim_from_form(claim, request.POST)
|
claim = claim_from_form(claim, request.POST, request.FILES)
|
||||||
|
|
||||||
claim_history = models.ClaimHistory()
|
claim_history = models.ClaimHistory()
|
||||||
claim_history.claim = claim
|
claim_history.claim = claim
|
||||||
@ -456,12 +467,24 @@ def claim_print(request, claim):
|
|||||||
@claim_editable
|
@claim_editable
|
||||||
def claim_edit(request, claim):
|
def claim_edit(request, claim):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
if request.POST['submit'].startswith('DeleteFile'):
|
||||||
|
file_id = int(request.POST['submit'][10:])
|
||||||
|
|
||||||
|
claim_receipt = models.ClaimReceipt.objects.get(id=file_id)
|
||||||
|
if claim_receipt.claim != claim:
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
claim_receipt.delete()
|
||||||
|
claim_receipt.uploaded_file.delete(save=False)
|
||||||
|
|
||||||
|
return redirect(reverse('claim_edit', kwargs={'id': claim.id}))
|
||||||
|
|
||||||
if request.POST['submit'] == 'Delete':
|
if request.POST['submit'] == 'Delete':
|
||||||
claim.delete()
|
claim.delete()
|
||||||
return redirect(reverse('claim_list'))
|
return redirect(reverse('claim_list'))
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
claim = claim_from_form(claim, request.POST)
|
claim = claim_from_form(claim, request.POST, request.FILES)
|
||||||
|
|
||||||
claim_history = models.ClaimHistory()
|
claim_history = models.ClaimHistory()
|
||||||
claim_history.claim = claim
|
claim_history.claim = claim
|
||||||
|
Loading…
Reference in New Issue
Block a user