Nabil Taleb
Nabil Taleb

Reputation: 137

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

Upvotes: 1

Views: 8555

Answers (4)

salah
salah

Reputation: 21

I think you can return Fridays and Saturdays between two dates by using datetime format. That is all. And a condition to check if the day name is the required one or not.

This format prints the day name: "%A"

Upvotes: 0

Tirtha R
Tirtha R

Reputation: 1318

This is for someone arriving here from search engines. I faced this error while importing data. This happened because I had the product id field mapped to Product instead of Product/External ID. So if you got this error while importing data, check whether the id fields are mapped properly.

Upvotes: 0

ELinda
ELinda

Reputation: 2821

  • 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

Upvotes: 1

CryptoFool
CryptoFool

Reputation: 23089

I've played with your code. It seems to kinda work. It figures out what days of the week exist in a range of dates. The problem you're seeing occurs when there aren't both a Friday and a Saturday in your range of dates (note that you have a variable named 'mon' that is set by looking for the key 'Friday').

So it seems that your problem is just that you have to allow for the case where you don't have both these days of the week in the range of dates your provide as input. In that case, either or both of week.get('Friday') and week.get('Saturday') are not going to exist in your week map, and so mon and/or sat are going to be None, and you're going to have a problem.

To get your code to run, I added this below it:

class Rec:
    def __init__(self, start, end):
        self.mission_start_date = start
        self.mission_end_date = end

self = [
    Rec("2019-3-31", "2019-4-1")
]

get_compensation(self)

This lets me cause your code to process a pair of dates. If the range of dates I give here includes both a Friday and a Saturday, your code runs fine. Otherwise it barfs with exactly the error you're talking about.

If you change the lines:

mon = week.get('Friday')
sat = week.get('Saturday')

to:

mon = week.get('Friday') if 'Friday' in week else 0
sat = week.get('Saturday') if 'Saturday' in week else 0

then your code does not crash for any date ranges I tested it with. I don't know if it's computing the results you want, because you aren't holding onto or returning any of the results of your computations.

Upvotes: 0

Related Questions