Search code examples
pythonodoononetype

TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType


I am new user in Python, I have a problem with the None type, I looked different question, but the problem persists.

My code is looking for Friday and Saturday between two dates, so far it works, but when I sum both I have this error:

"TypeError: unsupported operand type (s) for +: 'NoneType' and 'NoneType'

After I return the result in the function.

Here's my code :

    # -*- coding: utf-8 -*-

import datetime
import calendar
calendar.setfirstweekday(calendar.SUNDAY)

from odoo import models, fields, api

class HrMission(models.Model):
    _name = "hr.employee.mission"
    _description = "hr mission"
    _inherit = "hr.employee.mission"

    days_compensation =fields.Float(compute='get_compensation', compstring='Jours de récupération', help="Jours de récupération si la mission contient les jours de repos",
                             required=True, readonly=True,)

    @api.multi
    @api.depends('mission_start_date', 'mission_end_date')
    def get_compensation(self):
        for rec in self:
            if rec.mission_start_date and rec.mission_end_date:
                time1 = datetime.datetime.strptime(rec.mission_start_date, "%Y-%m-%d")
                time2 = datetime.datetime.strptime(rec.mission_end_date, "%Y-%m-%d")
                week = {}
                leave_value = {}
        # Compute Number Of Friday And Saturday
                for i in range((time2 - time1).days):
                    day = calendar.day_name[(time1 + datetime.timedelta(days=i+1)).weekday()]
                    week[day] = week[day] + 1 if day in week else 1                    
                fri = week.get('Friday')  # Result Number 4 Of Friday If "Start Date", "End date" --> "01/01/2017", "31/01/2017"
                sat = week.get('Saturday') # Same thing that friday
                friandsat = mon + sat # Error ---> "TypeError: unsupported operand type(s) for +: 'NoneType' and 'NoneType'"
                rec.days_compensation = friandsat

Solution

    • One thing to be careful of, is whether the start and end dates are both to be included in the date range. For example, if both dates are datetime.datetime(2019, 3, 1), then should the answer be 1?
    ...
    def get_compensation(self):
        def date_range_inclusive(rec):
            # if either date is undefined, then so is date range
            if not rec.mission_end_date or not rec.mission_start_date:
                return iter([])
    
            # Add 1 for inclusivity of both start and end dates
            num_days = abs((rec.mission_end_date - rec.mission_start_date).days) + 1
            return (rec.mission_start_date + timedelta(days=n) for n in range(num_days))
    
        for rec in self:
            # date range, including both start and end dates
            dates = date_range_inclusive(rec)
            # desired days to count
            day_selection = (calendar.FRIDAY, calendar.SATURDAY)
    
            rec.days_compensation = sum([dt.weekday() in day_selection for dt in dates])
    

    The above code will assume that the date range is inclusive. Remove + 1 to make it not inclusive. It will set the days_compensation field to 0 if no Fridays or Saturdays are included.

    • Note that there is no need to convert back and forth between data types since both the calendar days enumeration and weekday function in datetime evaluate to integers that can be compared.

    • Another thing to mind, is, according to https://www.odoo.com/documentation/8.0/reference/orm.html

    computed fields are not stored by default, they are computed and returned when requested. Setting store=True will store them in the database and automatically enable searching

    Therefore, you might want:

    days_compensation = fields.Float(compute='get_compensation', compstring='Jours de récupération', help="Jours de récupération si la mission contient les jours de repos", required=True, readonly=True,
    store=True)
    

    Note the only update was store=True