Example #1
0
    def export_icon_to_png(self, icon, color='#000', size=100, alpha=255, font='/web/static/lib/fontawesome/fonts/fontawesome-webfont.ttf'):
        """ This method converts an unicode character to an image (using Font
            Awesome font by default) and is used only for mass mailing because
            custom fonts are not supported in mail.
            :param icon : decimal encoding of unicode character
            :param color : RGB code of the color
            :param size : Pixels in integer
            :param alpha : transparency of the image from 0 to 255
            :param font : font path

            :returns PNG image converted from given font
        """
        # Make sure we have at least size=1
        size = max(1, size)
        # Initialize font
        addons_path = http.addons_manifest['web']['addons_path']
        font_obj = ImageFont.truetype(addons_path + font, size)

        # if received character is not a number, keep old behaviour (icon is character)
        icon = pycompat.unichr(int(icon)) if icon.isdigit() else icon

        # Determine the dimensions of the icon
        image = Image.new("RGBA", (size, size), color=(0, 0, 0, 0))
        draw = ImageDraw.Draw(image)

        boxw, boxh = draw.textsize(icon, font=font_obj)
        draw.text((0, 0), icon, font=font_obj)
        left, top, right, bottom = image.getbbox()

        # Create an alpha mask
        imagemask = Image.new("L", (boxw, boxh), 0)
        drawmask = ImageDraw.Draw(imagemask)
        drawmask.text((-left, -top), icon, font=font_obj, fill=alpha)

        # Create a solid color image and apply the mask
        if color.startswith('rgba'):
            color = color.replace('rgba', 'rgb')
            color = ','.join(color.split(',')[:-1])+')'
        iconimage = Image.new("RGBA", (boxw, boxh), color)
        iconimage.putalpha(imagemask)

        # Create output image
        outimage = Image.new("RGBA", (boxw, size), (0, 0, 0, 0))
        outimage.paste(iconimage, (left, top))

        # output image
        output = io.BytesIO()
        outimage.save(output, format="PNG")
        response = werkzeug.wrappers.Response()
        response.mimetype = 'image/png'
        response.data = output.getvalue()
        response.headers['Cache-Control'] = 'public, max-age=604800'
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'GET, POST'
        response.headers['Connection'] = 'close'
        response.headers['Date'] = time.strftime("%a, %d-%b-%Y %T GMT", time.gmtime())
        response.headers['Expires'] = time.strftime("%a, %d-%b-%Y %T GMT", time.gmtime(time.time()+604800*60))

        return response
Example #2
0
File: main.py Project: 1806933/odoo
    def export_icon_to_png(self, icon, color='#000', size=100, alpha=255, font='/web/static/lib/fontawesome/fonts/fontawesome-webfont.ttf'):
        """ This method converts an unicode character to an image (using Font
            Awesome font by default) and is used only for mass mailing because
            custom fonts are not supported in mail.
            :param icon : decimal encoding of unicode character
            :param color : RGB code of the color
            :param size : Pixels in integer
            :param alpha : transparency of the image from 0 to 255
            :param font : font path

            :returns PNG image converted from given font
        """
        # Make sure we have at least size=1
        size = max(1, size)
        # Initialize font
        addons_path = http.addons_manifest['web']['addons_path']
        font_obj = ImageFont.truetype(addons_path + font, size)

        # if received character is not a number, keep old behaviour (icon is character)
        icon = pycompat.unichr(int(icon)) if icon.isdigit() else icon

        # Determine the dimensions of the icon
        image = Image.new("RGBA", (size, size), color=(0, 0, 0, 0))
        draw = ImageDraw.Draw(image)

        boxw, boxh = draw.textsize(icon, font=font_obj)
        draw.text((0, 0), icon, font=font_obj)
        left, top, right, bottom = image.getbbox()

        # Create an alpha mask
        imagemask = Image.new("L", (boxw, boxh), 0)
        drawmask = ImageDraw.Draw(imagemask)
        drawmask.text((-left, -top), icon, font=font_obj, fill=alpha)

        # Create a solid color image and apply the mask
        if color.startswith('rgba'):
            color = color.replace('rgba', 'rgb')
            color = ','.join(color.split(',')[:-1])+')'
        iconimage = Image.new("RGBA", (boxw, boxh), color)
        iconimage.putalpha(imagemask)

        # Create output image
        outimage = Image.new("RGBA", (boxw, size), (0, 0, 0, 0))
        outimage.paste(iconimage, (left, top))

        # output image
        output = io.BytesIO()
        outimage.save(output, format="PNG")
        response = werkzeug.wrappers.Response()
        response.mimetype = 'image/png'
        response.data = output.getvalue()
        response.headers['Cache-Control'] = 'public, max-age=604800'
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Methods'] = 'GET, POST'
        response.headers['Connection'] = 'close'
        response.headers['Date'] = time.strftime("%a, %d-%b-%Y %T GMT", time.gmtime())
        response.headers['Expires'] = time.strftime("%a, %d-%b-%Y %T GMT", time.gmtime(time.time()+604800*60))

        return response
Example #3
0
    def _get_attendance_duration(self):
        attendance_obj = self.env['resource.calendar.attendance']
        precision = self.env['res.users'].browse(self.env.uid).company_id.working_time_precision
        # 2012.10.16 LF FIX : Get timezone from context
        active_tz = pytz.timezone(self.env.context.get("tz","UTC") if self.env.context and self.env.context.get("tz","UTC") else "UTC")
        str_now = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S')
        for attendance in self:
            duration = 0.0
            attendance_start = datetime.strptime(attendance.check_in, DEFAULT_SERVER_DATETIME_FORMAT).replace(tzinfo=pytz.utc).astimezone(active_tz)
            next_attendance_date = datetime.strftime(attendance_start, DEFAULT_SERVER_DATETIME_FORMAT)
            if attendance.check_in:
                next_attendance_ids = self.search([
                    ('employee_id', '=', attendance.employee_id.id),
                    ('check_in', '>', attendance.check_in)], order='check_in')
                if next_attendance_ids:
                    next_attendance = next_attendance_ids[0]
                    if next_attendance.check_in and not next_attendance.check_out:
                        # 2012.10.16 LF FIX : Attendance in context timezone
                        raise UserError(_('Incongruent data: sign-in %s is followed by another sign-in') % attendance_start)
                    next_attendance_date = next_attendance.check_in
                if attendance.check_out:
                    # 2012.10.16 LF FIX : Attendance in context timezone
                    attendance_stop = datetime.strptime(attendance.check_out, DEFAULT_SERVER_DATETIME_FORMAT).replace(tzinfo=pytz.utc).astimezone(active_tz)
                    duration_delta = attendance_stop - attendance_start
                    # minutes, seconds = divmod(divmod(duration_delta.days * 86400 + duration_delta.seconds, 60)[0], 60)
                    # duration = float('%s.%s'%(str(int(minutes)), str(int(seconds)).zfill(2)))
                    duration = duration_delta.total_seconds() / 60.0 / 60.0
                    duration = round(duration / precision) * precision
            attendance.duration = duration
            attendance.end_datetime = next_attendance_date
            # If contract is not specified: working days = 24/7
            attendance.inside_calendar_duration = duration
            attendance.outside_calendar_duration = 0.0
            active_contract_ids = attendance.employee_id.get_active_contracts(date=str_now[:10])
            if active_contract_ids:
                contract = active_contract_ids[0]
                if contract.resource_calendar_id:
                    # TODO applicare prima arrotondamento o tolleranza?
                    if contract.resource_calendar_id.attendance_rounding:
                        float_attendance_rounding = float(contract.resource_calendar_id.attendance_rounding)
                        rounded_start_hour = self._ceil_rounding(float_attendance_rounding, attendance_start)
                        rounded_stop_hour = self._floor_rounding(float_attendance_rounding, attendance_stop)

                        if abs(1 - rounded_start_hour) < 0.01:  # if shift == 1 hour
                            attendance_start = datetime(attendance_start.year, attendance_start.month,
                                attendance_start.day, attendance_start.hour + 1)
                        else:
                            attendance_start = datetime(attendance_start.year, attendance_start.month,
                                attendance_start.day, attendance_start.hour, int(round(rounded_start_hour * 60.0)))

                        attendance_stop = datetime(attendance_stop.year, attendance_stop.month,
                            attendance_stop.day, attendance_stop.hour, int(round(rounded_stop_hour * 60.0)))

                        # again
                        duration_delta = attendance_stop - attendance_start
                        duration = duration_delta.total_seconds() / 60.0 / 60.0
                        duration = round(duration / precision) * precision
                        attendance.duration = duration

                    attendance.inside_calendar_duration = 0.0
                    attendance.outside_calendar_duration = 0.0
                    calendar_id = contract.resource_calendar_id.id
                    intervals_within = 0

                    # split attendance in intervals = precision
                    # 2012.10.16 LF FIX : no recursion in split attendance
                    splitted_attendances = self._split_norecurse_attendance(attendance_start, duration, precision)
                    counter = 0
                    for atomic_attendance in splitted_attendances:
                        counter += 1
                        centered_attendance = atomic_attendance[0] + timedelta(0, 0, 0, 0, 0, atomic_attendance[1] / 2.0)
                        centered_attendance_hour = centered_attendance.hour + centered_attendance.minute / 60.0 \
                            + centered_attendance.second / 60.0 / 60.0
                        # check if centered_attendance is within a working schedule
                        # 2012.10.16 LF FIX : weekday must be single character not int
                        weekday_char = str(pycompat.unichr(centered_attendance.weekday() + 48))
                        matched_schedule_ids = attendance_obj.search([
                            '&',
                            '|',
                            ('date_from', '=', False),
                            ('date_from', '<=', centered_attendance.date()),
                            '|',
                            ('dayofweek', '=', False),
                            ('dayofweek', '=', weekday_char),
                            ('calendar_id', '=', calendar_id),
                            ('hour_to', '>=', centered_attendance_hour),
                            ('hour_from', '<=', centered_attendance_hour),
                            ])
                        if len(matched_schedule_ids) > 1:
                            raise UserError(_('Wrongly configured working schedule with id %s') % str(calendar_id))
                        if matched_schedule_ids:
                            intervals_within += 1
                            # sign in tolerance
                            if intervals_within == 1:
                                calendar_attendance = matched_schedule_ids[0]
                                attendance_start_hour = attendance_start.hour + attendance_start.minute / 60.0 \
                                    + attendance_start.second / 60.0 / 60.0
                                if attendance_start_hour >= calendar_attendance.hour_from and \
                                    (attendance_start_hour - (calendar_attendance.hour_from +
                                    calendar_attendance.tolerance_to)) < 0.01:  # handling float roundings (<=)
                                    additional_intervals = round(
                                        (attendance_start_hour - calendar_attendance.hour_from) / precision)
                                    intervals_within += additional_intervals
                                    attendance.duration = self.time_sum(
                                        attendance.duration, additional_intervals * precision)
                            # sign out tolerance
                            if len(splitted_attendances) == counter:
                                attendance_stop_hour = attendance_stop.hour + attendance_stop.minute / 60.0 \
                                    + attendance_stop.second / 60.0 / 60.0
                                calendar_attendance = matched_schedule_ids[0]
                                if attendance_stop_hour <= calendar_attendance.hour_to and \
                                    (attendance_stop_hour - (calendar_attendance.hour_to -
                                    calendar_attendance.tolerance_from)) > -0.01:  # handling float roundings (>=)
                                    additional_intervals = round(
                                        (calendar_attendance.hour_to - attendance_stop_hour) / precision)
                                    intervals_within += additional_intervals
                                    attendance.duration = self.time_sum(
                                        attendance.duration, additional_intervals * precision)
                    attendance.inside_calendar_duration = round((intervals_within * precision), 2)
                    # make difference using time in order to avoid rounding errors
                    # inside_calendar_duration can't be > duration
                    attendance.outside_calendar_duration = self.time_difference(
                        attendance.inside_calendar_duration, attendance.duration)
                    if contract.resource_calendar_id.overtime_rounding:
                        if attendance.outside_calendar_duration:
                            overtime = attendance.outside_calendar_duration
                            if contract.resource_calendar_id.overtime_rounding_tolerance:
                                overtime = self.time_sum(overtime,
                                    contract.resource_calendar_id.overtime_rounding_tolerance)
                            float_overtime_rounding = float(contract.resource_calendar_id.overtime_rounding)
                            attendance.outside_calendar_duration = math.floor(
                                overtime * float_overtime_rounding) / float_overtime_rounding