Half day leaves in payslip - python-3.5

I used Odoo 11 when the leaves request set with 0.5 days, it will be considered 1 day when I generate the payslip
I would like, when I set the request leaves with half days, It will be not round in payslips worked days
#api.model
def get_worked_day_lines(self, contracts, date_from, date_to):
"""
#param contract: Browse record of contracts
#return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to
"""
res = []
# fill only if the contract as a working schedule linked
for contract in contracts.filtered(lambda contract: contract.resource_calendar_id):
day_from = datetime.combine(fields.Date.from_string(date_from), datetime_time.min)
day_to = datetime.combine(fields.Date.from_string(date_to), datetime_time.max)
# compute leave days
leaves = {}
day_leave_intervals = contract.employee_id.iter_leaves(day_from, day_to, calendar=contract.resource_calendar_id)
for day_intervals in day_leave_intervals:
for interval in day_intervals:
holiday = interval[2]['leaves'].holiday_id
code = holiday.holiday_status_id.name
if holiday.holiday_status_id.impayed:
code = "Unpaid"
current_leave_struct = leaves.setdefault(holiday.holiday_status_id, {
'name': holiday.holiday_status_id.name,
'sequence': 5,
'code': code,
'number_of_days': 0.0,
'number_of_hours': 0.0,
'contract_id': contract.id,
})
leave_time = (interval[1] - interval[0]).seconds / 3600
current_leave_struct['number_of_hours'] += leave_time
work_hours = contract.employee_id.get_day_work_hours_count(interval[0].date(), calendar=contract.resource_calendar_id)
if work_hours:
current_leave_struct['number_of_days'] += leave_time / work_hours
# compute worked days
work_data = contract.employee_id.get_work_days_data(day_from, day_to, calendar=contract.resource_calendar_id)
attendances = {
'name': _("Normal Working Days paid at 100%"),
'sequence': 1,
'code': 'WORK100',
'number_of_days': work_data['days'],
'number_of_hours': work_data['hours'],
'contract_id': contract.id,
}
res.append(attendances)
res.extend(leaves.values())
return res

Related

How to assign a specific value from an other column in pandas in a given time frame?

I want to create a rolling forecast for the following 12 months, the results for the month and entry must become part of the dataframe as well (Later it will be written out into excel as part of a bigger dataframe).
The entries for the new dataframe needs to be calculated based on the criteria, that the forecasted month is between start_date and start_date + duration is also in the range of the forecasted 12 months. If these are met, the value from duration should be written here.
expected output
To do this I imagine that I have to use a numpy.where(), however I can not wrap my head around it.
I came across Use lambda with pandas to calculate a new column conditional on existing column, but after some trying I came to the conclusion, that this can not be the whole truth for my case.
import numpy as np
import pandas as pd
import datetime as dt
months = ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"]
cur_month = dt.date.today().month - 1
cur_year = dt.date.today().year
d = {'start_date': ['2020-12-23', '2021-02-08', '2021-06-11', '2022-01-07'], 'duration': [12, 6, 8, 3],
'effort': [0.3, 0.5, 1.2, 0.1]}
df = pd.DataFrame(data=d)
i = 0
while i < 12:
# this creates the header rows for the 12 month period
next_month = months[(cur_month + i) % len(months)]
# here goes the calculation/condition I am stuck with...
df[next_month] = np.where(...)
i += 1
So I came up with this and seems to work, I also added some logic for weighting for the cases a project starts some time during the month, so we get a more accurate effort number.
d = {"id": [1,2,3,4], "start_date": ['2020-12-23', '2021-02-08', '2021-06-11', '2022-01-07'], "duration": [12, 6, 8, 3],
"effort": [0.3, 0.5, 1.2, 0.1]}
df = pd.DataFrame(data=d)
df["EndDates"] = df["start_date"].dt.to_period("M") + df_["duration"]
i = 0
forecast = pd.Series(pd.period_range(today, freq="M", periods=12))
while i < 12:
next_month = months[(cur_month + i) % len(months)]
df[next_month] = ""
for index, row in df.iterrows():
df_tmp = df.loc[df['id'] == int(row['id'])]
if not df_tmp.empty and pd.notna(df_tmp["start_date"].item()):
if df_tmp["start_date"].item().to_period("M") <= forecast[i] <= df_tmp["EndDates"].item():
# For the current month let's calculate with the remaining value
if i == 0:
act_enddate = monthrange(today.year, today.month)[1]
weighter = 1 - (int(today.day) / int(act_enddate))
df.at[index, next_month] = round(df_tmp['effort'].values[0] * weighter,
ndigits=2)
# If it is the first entry for the oppty, how many FTEs will be needed for the first month
# of the assignment
elif df_tmp["start_date"].item().to_period("M") == forecast[i]:
first_day = df_tmp["start_date"].item().day
if first_day != 1:
months_enddate = monthrange(forecast[i].year, forecast[i].month)[1]
weighter = 1 - (int(first_day) / int(months_enddate))
df.at[index, next_month] = round(df_tmp['effort'].values[0] * weighter,
ndigits=2)
else:
df.at[index, next_month] = df_tmp['effort'].values[0]
# How many FTEs are needed for the last month of the assignment
elif df_tmp["EndDates"].item() == forecast[i]:
end_day = df_tmp["start_date"].item().day
if end_day != 1:
months_enddate = monthrange(forecast[i].year, forecast[i].month)[1]
weighter = int(end_day) / int(months_enddate)
df.at[index, next_month] = round(df_tmp['Umrechnung in FTEs'].values[0] * weighter,
ndigits=2)
else:
continue
else:
df.at[index, next_month] = df_tmp['effort'].values[0]

Assign the same value to object keys from lambda in Python (Django)

When trying to assign the same value to starting_bid and price from the Listing model in my Django project the below approach always yields different values. How can I assign the same value while still having the lambda return a random integer whenever the test runs?
tests.py
SEEDER = Seed.seeder() # from django_seed
AMOUNT = 15
MIN = 5
MAX = 84
PRICE = lambda x: random.randint(MIN, MAX)
SEEDER.add_entity(
Listing,
AMOUNT,
{
"starting_bid": PRICE,
"price": PRICE
})
SEEDER.execute()
Result:
{"starting_bid": 80, "price": 45}
Expected:
{"starting_bid": 80, "price": 80}
models.py
class Listing(models.Model):
CATEGORIES = (("LAP", "Laptop"), ("CON", "Console"), ("GAD", "Gadget"), ("GAM", "Game"), ("TEL", "TV"))
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
title = models.CharField(max_length=64)
description = models.CharField(max_length=256)
starting_bid = models.PositiveSmallIntegerField()
price = models.PositiveSmallIntegerField()
image_url = models.URLField(max_length=200)
category = models.CharField(max_length=8, choices=CATEGORIES)
active = models.BooleanField(default=True)
_price = []
def PRICE(round = 2):
global _price
if not _price:
_price = random.randint(MIN, MAX)
_price = [_price] * round
return _price.pop()

Set model field default value set based on previous object's value from model class

I set model managers to query the request_number of the last record in the database. The default value of the request number should be 210001 (if the first record of the year 2021), or the next sequential number of the current year (20002, 20003, 20004, etc).
How do I set the code to look at the previous record as part of setting the default value of the model field?
from django.db import models
import datetime
class ServiceRequestManager(models.Manager):
def last_record(self):
last_record_year = int(self.last().request_number[0:2])
return last_record_year
def last_record_request_number_plus_one(self):
last_request_number = int(self.last().request_number) + 1
return last_request_number
def test(self):
year_difference = int(datetime.date.today().strftime('%y')) - int(self.last().request_number[0:2])
return year_difference
def number():
year = str(datetime.date.today().strftime('%y')) # Pulls last two digits of the year
# previous_record_year = ServiceRequestManager.last_record
# new_request_number = ServiceRequestManager.last_record_request_number_plus_one
# current_record_year = int(datetime.date.today().strftime('%y'))
if int(year) > ServiceRequestManager.last_record(): # TypeError: last_record() missing 1 required positional argument: 'self'
return year
else:
i = 1
i_pad = "%04d" % i # creates 000x so default is 0001
return year+str(i_pad) # Creates the full request number e.g. 200001
# Need the next record to be 200002, 200003, 200004 etc until the first instance of 2021 which would be 210001, 210002, etc.
# Create your models here.
class ServiceRequest(models.Model):
CATEGORY_CHOICES = (
(None, ''),
('aircraft_repair', 'Aircraft Repair'),
('backshop', 'Backshop'),
('documentation', 'Documentation'),
('other', 'Other')
)
PRIORITY_CHOICES = (
(None, ''),
('1', '1-Critical (<24 hours)'),
('2', '2-Urgent (1-2 Days)'),
('3', '3-Standard (3 Days)'),
('4', '4-Low (5 Days)')
)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, blank=True)
updated = models.DateTimeField(auto_now=True)
request_number = models.CharField(max_length=6, default=number())
objects = ServiceRequestManager()
def __str__(self):
return self.request_number # show the request number in admin screen
class Meta:
ordering = ('-request_number',) # sort request number descending in admin screen
We can make a function that looks for the ServiceRequest that starts with the first two digits of the year, and then look for the last one of these records.
If no such record exists, we return f'{y2}0000' (so we "start" a new sequence), and if it does, we parse it to an int, then increment it, and obtain the last four digits to create a new one:
from django.utils.timezone import now
def number():
y2 = now().strftime('%y')
last_request = ServiceRequest.objects.filter(
request_number__startswith=y2
).order_by('-request_number').values_list('request_number', flat=True).first()
if last_request is None:
return f'{y2}0000'
else:
num = (int(last_request) + 1) % 10000
return f'{y2}{num:04d}'
In the model, we pass default=number, so a reference to the function, not the result of calling the function. Furthermore it might be useful to specify a database index, and make the field unique (to prevent generating two records with the same reference_number in the database):
class ServiceRequest(models.Model):
CATEGORY_CHOICES = (
(None, ''),
('aircraft_repair', 'Aircraft Repair'),
('backshop', 'Backshop'),
('documentation', 'Documentation'),
('other', 'Other')
)
PRIORITY_CHOICES = (
(None, ''),
('1', '1-Critical (<24 hours)'),
('2', '2-Urgent (1-2 Days)'),
('3', '3-Standard (3 Days)'),
('4', '4-Low (5 Days)')
)
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
request_number = models.CharField(
max_length=6,
db_index=True,
default=number,
unique=True
)
Perhaps four digits is however not enough. It might be more safe to use max_length=8 for example, to allow 1'000'000 request numbers per year. Especially since some request numbers are perhaps not valid (and will thus be closed).

Taking info from file and creating a dictionary

The goal of mine is to create a dictionary called 'sum_of_department' contains the department as the key and the total annual salary of all employees combined as a value. So far this is what I have but I'm a bit lost on how to add all the department names along with a sum of all of the employees salary in that dictionary. The current dictionary i tried displays only the amount of the salary and how many times its seen in the file. this is where i need the help.
import requests
# endpoint
endpoint = "https://data.cityofchicago.org/resource/xzkq-xp2w.json"
# optional parameters
parameters = {"$limit":20,}
# make request
response = requests.get(endpoint, params=parameters)
# Get the response data as a python object.
data = response.json()
count_by_department = {}
sum_by_department = {}
#loop through the data
for i in data:
if ('department' and 'salary_or_hourly' and 'annual_salary' in i):
department = i['department']
pay_type = i['salary_or_hourly']
anual_salary = i['annual_salary']
# print(i['annual_salary'])
else:
# handle case where there is no department property in that record
department = 'undefined'
pay_type = 'n/a'
anual_salary = 'n/a'
# print(department,"," ,pay_type)
# exclude the cases where the pay type is Hourly
if(pay_type != 'Salary' ):
pay_type = 0
# print(department,"," ,pay_type)
# update the sum_by_department and count_by_department dictionaries
if (department in count_by_department):
count_by_department[department] += 1
else:
count_by_department[department] = 1
if (anual_salary in sum_by_department):
sum_by_department[anual_salary] +=1
else:
sum_by_department[anual_salary] = 1
# print(count_by_department)
# print(sum_by_department)
You should add each person's annual_salary to the sum_by_department array while looping. Also, do not forget to convert your annual_salary variable to the float type, because adding them together as strings won't work.
Example script:
import requests
# endpoint
endpoint = "https://data.cityofchicago.org/resource/xzkq-xp2w.json"
# optional parameters
parameters = {"$limit":20,}
# make request
response = requests.get(endpoint, params=parameters)
# Get the response data as a python object.
data = response.json()
count_by_department = {}
sum_by_department = {}
#loop through the data
for i in data:
if ('department' and 'salary_or_hourly' and 'annual_salary' in i):
department = i['department']
pay_type = i['salary_or_hourly']
annual_salary = float(i['annual_salary'])
# print(i['annual_salary'])
else:
# handle case where there is no department property in that record
department = 'undefined'
pay_type = 'n/a'
annual_salary = 0
# print(department,"," ,pay_type)
# exclude the cases where the pay type is Hourly
if(pay_type != 'Salary' ):
pay_type = 0
# print(department,"," ,pay_type)
# update the sum_by_department and count_by_department dictionaries
if (department in count_by_department):
count_by_department[department] += 1
sum_by_department[department] += annual_salary
else:
count_by_department[department] = 1
sum_by_department[department] = annual_salary
#import pdb; pdb.set_trace();
print('count_by_department = ', count_by_department)
print('sum_by_department = ', sum_by_department)
Tip:
Uncomment the pdb line to debug interactively. The Python Debugger (pdb for short) halts the program while it's still running (i.e. in memory), so you can interact with it and inspect all variables.

Dark Sky API Iterate daily through one year in Python 3

I just try to get the weather data for a time range.
I want to get daily OR hourly data for a whole year.
I just tried the following code:
from forecastiopy import *
from datetime import date, datetime, timedelta
def daterange(start_date, end_date):
for n in range(int ((end_date - start_date).days)):
yield start_date + timedelta(n)
start_date = date(2015, 1, 1)
end_date = date(2015, 12, 31)
for single_date in daterange(start_date, end_date):
time = single_date.strftime("%Y-%m-%d")
print('DATE: ', time)
city = [40.730610, -73.935242]
fio = ForecastIO.ForecastIO(apikey,
units=ForecastIO.ForecastIO.UNITS_SI,
lang=ForecastIO.ForecastIO.LANG_ENGLISH,
latitude=city[0], longitude=city[1])
print('Latitude:', fio.latitude, 'Longitude:', fio.longitude)
print('Timezone', fio.timezone, 'Offset', fio.offset)
print(fio.get_url()) # You might want to see the request url
if fio.has_hourly() is True:
hourly = FIOHourly.FIOHourly(fio)
print('Hourly')
print('Summary:', hourly.summary)
print('Icon:', hourly.icon)
for hour in range(0, hourly.hours()):
print('Hour', hour+1)
for item in hourly.get_hour(hour).keys():
print(item + ' : ' + str(hourly.get_hour(hour)[item]))
# Or access attributes directly for a given minute.
print(hourly.hour_5_time)
else:
print('No Hourly data')
I get:
DATUM: 2015-01-01
DATUM: 2015-01-02
DATUM: 2015-01-03
...
DATUM: 2015-12-29
DATUM: 2015-12-30
Latitude: 40.73061 Longitude: -73.935242
Timezone America/New_York Offset -4
Hourly
Summary: Light rain starting this afternoon.
Icon: rain
Hour 1
visibility : 16.09
humidity : 0.52
...
Hour 49
visibility : 16.09
humidity : 0.57
apparentTemperature : 23.52
icon : partly-cloudy-day
precipProbability : 0
windGust : 2.7
uvIndex : 2
time : 1498395600
precipIntensity : 0
windSpeed : 2.07
pressure : 1014.84
summary : Mostly Cloudy
windBearing : 37
temperature : 23.34
ozone : 308.33
cloudCover : 0.65
dewPoint : 14.43
1498237200
How can I use for the time parameter each day of a specific year to get 365 daily reports or 365 * 24 hourly reports? I am not a specialist in python.
This blog provides some code to query between dates https://nipunbatra.github.io/blog/2013/download_weather.html
times = []
data = {}
for attr in attributes:
data[attr] = []
start = datetime.datetime(2015, 1, 1)
for offset in range(1, 60):
forecast = forecastio.load_forecast(api_key, lat, lng, time=start+datetime.timedelta(offset), units="us")
h = forecast.hourly()
d = h.data
for p in d:
times.append(p.time)
try:
for i in attributes:
data[i].append(p.d[i])
except:
print(KeyError)
df = pd.DataFrame(data, index=times)
It works for me on python 3.6...however, i am getting a error KeyError: 'temperature' when i query dates around march 2019 for my coordinates... so in this code I added try catach error in the for p in d loop
Hope this helps

Resources