出退勤記録をつける際に、例えば8:12に出社したら、出勤時刻は8:15として、15分刻みで実働時間や時給計算するというのはよくあります。
逆に退勤時は、15:12に退勤したら、15:00と記録したいですね。
特に丸めずにそのまま記録して、集計時に丸めてもよいのですが、djangoだと集計時にいろいろ面倒なので、最初から丸めて記録しておくと良いかと思います。
主にformの機能を使ってDBに記録するので、記録する際にviews.pyのform_validをいじります。
以下は出勤時の例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
from django.shortcuts import render from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.edit import CreateView from .forms import AttendanceAttendanceForm import datetime as datetime from django.contrib import messages #モデル読み込み(models.pyの内容は割愛) from .models import Attendance class AttendanceCreateView(LoginRequiredMixin, CreateView): template_name = './attendance/attendance_form.html' model = Attendance form_class = AttendanceAttendanceForm # もしCreateViewクラスでフォームに初期値を設定する場合はget_initionalを # オーバーライドする """ def get_initial(self): initial = super().get_initial() initial["model_name"] = "initial_value" return initial """ def form_valid(self, form): post = form.save(commit=False) # 時刻を丸める round_min = 15 # 15分刻み at = timezone.now() # 端数時間を計算 discard = datetime.timedelta(minutes=at.minute % round_min, seconds=at.second, microseconds=at.microsecond) # 端数を差し引き、15分加算 at = at - discard + datetime.timedelta(minutes=round_min) post.attendance_at = at post.save() messages.info(self.request, f'出勤しました。今日もよろしくお願いします。') return redirect('attendance:attendance') |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from django import forms from .models import Attendance # 出勤用 class AttendanceAttendanceForm(forms.ModelForm): class Meta: model = Attendance # 他に必要なパーツがある場合はここに fields = ( ) widgets = { } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
{% block content %} {{ form.certifications.errors }} <div class="container"> <div class="row"> <div class="col-12"> <form method="post" id="attendance_form"> {% form %} {% csrf_token %} </form> </div> </div> <div id="error"></div> <a id="attendance" class="btn-lg text-center save" href="#">出勤する</a> </div> <script type="text/javascript"> $(function(){ "use strict"; $('.save').on('click', function (e) { if(!confirm("出勤します。よろしいですか?")){ return false; }; $(this).addClass('disabled'); $('#attendance_form').submit(); }) }); </script> {% endblock %} |
退勤用のフォームを作る場合は、form_validで以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
: # 退勤 class AttendanceUpdateView(LoginRequiredMixin, UpdateView): template_name = 'attendance/absence_form.html' model = Attendance : def form_valid(self, form): post = form.save(commit=False) # 時刻を丸める round_min = 15 # 15分刻み at = timezone.now() # 端数時間を計算 discard = datetime.timedelta(minutes=at.minute % round_min, seconds=at.second, microseconds=at.microsecond) # 純粋に差し引く at -= discard post.absence_at = at post.save() messages.info(self.request, f'退勤しました。お疲れ様でした。') return redirect('attendance:absence') : |
なお実際には、出勤した直後に(15分もたたずに)すぐ退勤した場合、上記の例だと出勤時刻と退勤時刻が逆転してしまいますので、もし丸めた退勤時刻が出勤時刻より早くなってしまったら出勤時刻と同じにするなどのイレギュラー処理が必要となります。
参考サイト)