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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
# @author: La Louve
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html
from openerp import api, fields, models, _
from openerp.exceptions import UserError
from datetime import datetime, timedelta
class ShiftShift(models.Model):
_inherit = "shift.shift"
standard_registration_ids = fields.One2many(
"shift.registration",
"shift_id",
string="Standard Attendances",
domain=[('shift_type', '=', 'standard')])
ftop_registration_ids = fields.One2many(
"shift.registration",
"shift_id",
string="FTOP Attendances",
domain=[('shift_type', '=', 'ftop')])
state = fields.Selection([
('draft', 'Unconfirmed'), ('cancel', 'Cancelled'),
('confirm', 'Confirmed'), ('entry', 'Entry'), ('done', 'Done')])
shift_name_read = fields.Char(related='name')
is_send_reminder = fields.Boolean("Send Reminder", default=False)
@api.multi
def button_done(self):
"""
@Overide the function to validate the registration before allowing
marking the shift done
"""
for shift in self:
if not shift.shift_type_id.is_ftop:
not_recorded_attendances = shift.registration_ids.filtered(
lambda x: x.state in ['draft', 'open'])
if not_recorded_attendances:
shift_ticket_partners = []
for att in not_recorded_attendances:
ticket_name = att.shift_ticket_id.name or ''
partner_name = att.partner_id.name or ''
shift_ticket_partners.append(
"- [%s] %s" % (ticket_name, partner_name))
raise UserError(_(
"Warning! You have not recorded the attendance " +
"for: \n\n%s") % '\n'.join(shift_ticket_partners))
super(ShiftShift, self).button_done()
# - Create Point for FTOP shift on cloturing
# + Deduct 1 if current point > 1
# + Deduct 2 if current point < 1
point_counter_env = self.env['shift.counter.event']
for shift in self:
if shift.shift_type_id.is_ftop:
for registration in shift.registration_ids:
partner = registration.partner_id
# Registration's state is waiting means the member is on
# vacation or exempted at the current shift. So, we don't
# deduct member's points
if registration.state == 'waiting':
continue
# Unignored all ignored counter
for counter in partner.counter_event_ids:
if counter.ignored:
counter.ignored = False
current_point = partner.final_ftop_point
if current_point >= 1:
point = -1
else:
point = -1
# Create Point Counter
point_counter_env.sudo().with_context(
{'automatic': True}).create({
'name': _('Shift Cloture'),
'shift_id': shift.id,
'type': 'ftop',
'partner_id': partner.id,
'point_qty': point
})
@api.multi
def button_makeupok(self):
"""
@Function trigger to change the state from Confirm to Entry
"""
for shift in self:
shift.state = 'entry'
# Automatically mark attendance as "Attended" for
# makeup (ABCD Member)
for reg in shift.registration_ids:
if not reg.partner_id.in_ftop_team and \
not reg.tmpl_reg_line_id and \
reg.state != 'replacing':
reg.button_reg_close()
@api.multi
def write(self, vals):
res = super(ShiftShift, self).write(vals)
# change to unconfirmed registrations to confirmed if this shift state
# is `entry`
for shift in self:
if shift.state == 'entry':
for reg in shift.standard_registration_ids:
if reg.state == 'draft':
reg.confirm_registration()
for reg in shift.ftop_registration_ids:
if reg.state == 'draft':
reg.confirm_registration()
return res
@api.model
def send_mail_reminder_ftop_members(self):
shift_env = self.env['shift.shift']
# get shifts 7 days later
shifts = shift_env.search([
('is_send_reminder', '=', False),
('shift_type_id.is_ftop', '=', True),
('state', 'not in', ('cancel', 'done')),
('date_begin', '>=', fields.Date.context_today(self)),
('date_begin', '<=',
(datetime.now() + timedelta(days=12)).strftime('%Y-%m-%d'))
])
# Get attendent
attendances = shifts.mapped("ftop_registration_ids")
# Get attendences not former member
partners = attendances.mapped("partner_id").filtered(
lambda p: not p.is_former_member and p.active)
# get all attendences's leaves
leaves = partners.mapped('leave_ids')
# get leaves on shift
leave_on_shift_ids = []
for shift in shifts:
leave_on_shift_id = leaves.filtered(
lambda l: l.state == 'done' and
l.stop_date >= shift.date_begin and
l.start_date <= shift.date_end).ids
leave_on_shift_ids += leave_on_shift_id
leave_on_shifts = self.env['shift.leave'].browse(leave_on_shift_ids)
# get partner on leaves
partner_on_leaves = leave_on_shifts.mapped("partner_id")
# remove partner on leaves
partner_can_join = partners - partner_on_leaves
attendences_to_send = attendances.filtered(
lambda a: a.partner_id.id in partner_can_join.ids)
# get mail template and send
mail_template = self.env.ref(
'coop_membership.coop_ftop_members_reminder_email')
if mail_template:
for attendence_to_send in attendences_to_send:
mail_template.send_mail(attendence_to_send.id)
# update sent reminder
shifts.write({
'is_send_reminder': True
})
return True