diff --git a/smash/web/api_views/worker.py b/smash/web/api_views/worker.py
index 39eb016eead7bbde9c4478276c82f27e39fd50cf..0a06231d775e41a1040b647549f89eb80615c614 100644
--- a/smash/web/api_views/worker.py
+++ b/smash/web/api_views/worker.py
@@ -1,12 +1,15 @@
 import datetime
-
-from django.http import JsonResponse
+import logging
+import json
+from django.http import JsonResponse, HttpResponse
 from django.utils import timezone
 
+from django.shortcuts import get_object_or_404
 from web.models.constants import GLOBAL_STUDY_ID
 from web.api_views.daily_planning import get_workers_for_daily_planning, get_availabilities
 from ..models import Worker
 
+logger = logging.getLogger(__name__)
 
 def specializations(request):
     workers = Worker.objects.filter(specialization__isnull=False).values_list('specialization').distinct()
@@ -21,14 +24,18 @@ def units(request):
         "units": [x[0] for x in workers]
     })
 
-
 def workers_for_daily_planning(request):
+    start_date = request.GET.get('start_date')
     workers = get_workers_for_daily_planning(request)
     workers_list_for_json = []
+    if start_date is not None:
+        today = timezone.now()
+        start_date=datetime.datetime.strptime(start_date, '%Y-%m-%d').replace(tzinfo=today.tzinfo)
     for worker in workers:
         role = unicode(worker.roles.filter(study_id=GLOBAL_STUDY_ID)[0].role)
         worker_dict_for_json = {
             'id': worker.id,
+            'availability': worker.availability_percentage(start_date=start_date),
             'title': u"{} ({})".format(unicode(worker), role[:1].upper()),
             'role': role
         }
diff --git a/smash/web/models/worker.py b/smash/web/models/worker.py
index 58ecebabfc861ae1dbcec8e8b14e34bd71353d31..85037ed18446e0149e3e8ef8d417eb666cec6ab2 100644
--- a/smash/web/models/worker.py
+++ b/smash/web/models/worker.py
@@ -2,6 +2,8 @@
 import datetime
 import logging
 
+from web.utils import get_today_midnight_date
+
 from django.contrib.auth.models import User, AnonymousUser
 from django.db import models
 
@@ -9,6 +11,14 @@ from web.models.constants import GLOBAL_STUDY_ID, COUNTRY_OTHER_ID, AVAILABILITY
 from web.models.worker_study_role import STUDY_ROLE_CHOICES, HEALTH_PARTNER_ROLE_CHOICES, \
     VOUCHER_PARTNER_ROLE_CHOICES, WORKER_STAFF, WORKER_HEALTH_PARTNER, WORKER_VOUCHER_PARTNER, ROLE_CHOICES
 
+from web.utils import get_weekdays_in_period
+from web.officeAvailability import OfficeAvailability
+from django.db.models import Q
+from web.models.holiday import Holiday
+from web.models.availability import Availability
+from web.models.appointment import Appointment
+from web.models.appointment_type_link import AppointmentTypeLink
+
 logger = logging.getLogger(__name__)
 
 
@@ -159,6 +169,48 @@ class Worker(models.Model):
         else:
             return False
 
+    def is_available(self, start_date=None, end_date=None):
+        self.availability_percentage(start_date=start_date, end_date=end_date) > 50.0
+
+    def availability_percentage(self, start_date=None, end_date=None):
+        '''
+            start_date: defaults to None and then is set to today's midnight date 
+            end_date: defaults to None and then is set to today's midnight date + 24 hours
+        '''
+        today_midnight = get_today_midnight_date()
+
+        if start_date is None:
+            start_date = today_midnight
+        if end_date is None:
+            start_date = start_date.replace(hour=0, minute=0, second=0)
+            end_date = start_date + datetime.timedelta(days=1)
+
+        office_availability = OfficeAvailability('{} {}'.format(self.first_name, self.last_name), start=start_date, end=end_date)
+
+        #Appointments
+        subject_appointments = AppointmentTypeLink.objects.filter(worker=self.id, date_when__gte=start_date, date_when__lte=end_date)
+        general_appointments = Appointment.objects.filter(worker_assigned=self.id, datetime_when__gte=start_date, datetime_when__lte=end_date)
+
+        #Holidays and extra availabilities. 
+        holidays_and_extra_availabilities = self.holiday_set.filter(datetime_start__gte=start_date, datetime_end__lt=end_date).order_by('-datetime_start')
+
+        #Availability 
+        weekdays = get_weekdays_in_period(start_date, end_date)
+        weekdayQ = Q() #create a filter for each weekday in the selected period
+        for weekday in weekdays:
+            weekdayQ = weekdayQ | Q(day_number=weekday)
+        availabilities = self.availability_set.filter(person=self.id).filter(weekdayQ).order_by('day_number', 'available_from')
+
+        things = []
+        things.extend(availabilities)
+        things.extend(holidays_and_extra_availabilities)
+        things.extend(subject_appointments)
+        things.extend(general_appointments)
+        for thing in things:
+            office_availability.consider_this(thing, only_working_hours=True)
+
+        return office_availability.get_availability_percentage(only_working_hours=True)
+
     @property
     def role(self):
         roles = self.roles.filter(study=GLOBAL_STUDY_ID)
diff --git a/smash/web/officeAvailability.py b/smash/web/officeAvailability.py
new file mode 100644
index 0000000000000000000000000000000000000000..c4cf72f4c2a4d0ab27e86ba92c32458eb1f4be73
--- /dev/null
+++ b/smash/web/officeAvailability.py
@@ -0,0 +1,208 @@
+# coding=utf-8
+import datetime
+from datetime import timedelta
+import logging
+import pandas as pd
+
+from web.utils import timeit, get_today_midnight_date
+from web.models.holiday import Holiday
+from web.models.availability import Availability
+from web.models.appointment import Appointment
+from web.models.appointment_type_link import AppointmentTypeLink
+from web.models.constants import AVAILABILITY_EXTRA, AVAILABILITY_HOLIDAY
+
+logger = logging.getLogger(__name__)
+
+#only for plot method
+import matplotlib
+matplotlib.use('Agg')
+import matplotlib.pyplot as plt
+
+class OfficeAvailability(object):
+	'''
+		start: datetime-like indicating when the range starts. If none, then today midnight
+		end: datetime-like indicating when the range ends. If none, then tomorrow midnight
+		office_start: when the office hours begin
+		office_end: when the office hours finish 
+		minimum_slot: frequency of the pandas series. T stands of minutes. Docs: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.date_range.html
+	'''
+	def __init__(self, name, start=None, end=None, office_start='8:00', office_end='19:00', minimum_slot='1T'):
+		today_midnight = get_today_midnight_date()
+		tomorrow_midnight = today_midnight + datetime.timedelta(days=1)
+
+		if start is None:
+			self.start = today_midnight
+		else:
+			self.start = start
+
+		if end is None:
+			self.end = tomorrow_midnight
+		else:
+			self.end = end
+
+		self.name = name
+		self.office_start = office_start
+		self.office_end   = office_end
+		self.minimum_slot = minimum_slot
+		self.range = pd.date_range(start=self.start, end=self.end, freq=self.minimum_slot)
+		logger.debug('Min index: {}. Max index: {}'.format(self.start, self.end))
+		self.availability = pd.Series(index=self.range, data=0) # initialize range at 0
+	
+	def _get_duration(self):
+		return self.availability.index[-1] - self.availability.index[0]
+
+	def add_availability(self, range, only_working_hours=False):
+		if only_working_hours:
+			range = range.to_series().between_time(self.office_start, self.office_end)
+		self.availability[range] = 1
+
+	def remove_availability(self, range, only_working_hours=False):
+		if only_working_hours:
+			range = range.to_series().between_time(self.office_start, self.office_end)
+		self.availability[range] = 0
+
+	def consider_this(self, appointment_availability_or_holiday, only_working_hours=False):
+		'''
+			Availability repeat every week.
+			Availability always refers to a moment in which the worker should be working. Never the opposite.
+			
+			Holiday has higher preference because it refers to extraordinary events like extra availability or lack of availability.
+			Holiday modifies the status of Availability for specific periods of time.
+
+			Only_working_hours: If true changed are limited to the provided working hours.
+
+			Known Issues: If the range to be added extends beyond the limits of the given time series range, the call to self.availability[portion.index] = set_to will fail.
+			It fails because there are keys missing within the time series of the object.
+
+			Two solutions are possible:
+			- First, limit the time periods of the ranges to be considered to the object time space. (current solution)
+			- Second, extend the object time space.
+
+			Notwithstanding, this issue shouldn't exist because in preivous steps we should receive the availabilities queried to the limits of this objects time space.
+			First proposal should be the solution to consider.
+		'''
+		if isinstance(appointment_availability_or_holiday, Availability):
+			start   = appointment_availability_or_holiday.available_from
+			end     = appointment_availability_or_holiday.available_till
+			weekday = appointment_availability_or_holiday.day_number
+			logger.debug('Considering Availability from {} to {} for weekday {}'.format(start, end, weekday))
+			portion = self.availability[self.availability.index.weekday == (weekday-1)].between_time(start,end) #selects the weekdays and then the specific hours
+			set_to  = 1 
+		elif isinstance(appointment_availability_or_holiday, Holiday):
+			start   = appointment_availability_or_holiday.datetime_start
+			end     = appointment_availability_or_holiday.datetime_end
+			logger.debug('Considering {} from {} to {}'.format('Extra Availability' if appointment_availability_or_holiday.kind == AVAILABILITY_EXTRA else 'Holiday', start, end))
+			portion = self.availability[pd.date_range(start=start, end=end, freq=self.minimum_slot)] #select the specific range
+			set_to	= 1 if appointment_availability_or_holiday.kind == AVAILABILITY_EXTRA else 0
+		elif isinstance(appointment_availability_or_holiday, Appointment):
+			start   = appointment_availability_or_holiday.datetime_when
+			end     = start + datetime.timedelta(minutes=appointment_availability_or_holiday.length)
+			logger.debug('Considering General Appointment from {} to {}'.format(start, end))
+			portion = self.availability[pd.date_range(start=start, end=end, freq=self.minimum_slot)] #select the specific range
+			set_to  = 0
+		elif isinstance(appointment_availability_or_holiday, AppointmentTypeLink):
+			start   = appointment_availability_or_holiday.date_when
+			end     = start + datetime.timedelta(minutes=appointment_availability_or_holiday.appointment_type.default_duration)
+			logger.debug('Considering Subject Appointment from {} to {}'.format(start, end))
+			portion = self.availability[pd.date_range(start=start, end=end, freq=self.minimum_slot)] #select the specific range
+			set_to  = 0
+		else:
+			logger.error('Expected Holiday or Availability objects.')
+			raise TypeError
+
+		if only_working_hours:
+			portion = portion.between_time(self.office_start, self.office_end)
+
+		#limit portion to be changed to the bounds of the object time space (solution 1 of the aforementioned problem)
+		portion = portion[(self.availability.index.min() <= portion.index) & (portion.index <= self.availability.index.max())]
+
+		self.availability[portion.index] = set_to
+
+	def get_availability_percentage(self, only_working_hours=False):
+		'''
+		For multiple values this is the solution: return self.availability.value_counts().div(len(s))[1] * 100 
+		But since it's 0 or 1, this works as well and is faster: return self.availability.mean() * 100
+
+		To test it:
+		import pandas as pd
+		range = pd.date_range(start='2018-10-1', end='2018-10-2 01:00', freq='5T', closed=None)
+		s = pd.Series(index=range, data=0)
+		range2 = pd.date_range(start='2018-10-1 1:00', end='2018-10-1 2:30', freq='5T')
+		s[range2] = 1
+		print(s.value_counts().div(len(s))[1]*100)   # prints 6.312292358803987
+		print(s.mean()*100)							 # prints 6.312292358803987
+		%timeit s.value_counts().div(len(s))[1]*100  # 504 µs ± 19.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
+		%timeit s.mean()*100                         # 56.3 µs ± 1.66 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
+		'''
+		if only_working_hours:
+			availability = self.availability.between_time(self.office_start, self.office_end)
+		else:
+			availability = self.availability
+
+		return availability.mean() * 100 #better to isolate the operation in case we change it later
+
+	def is_availabile(self, only_working_hours=False):
+		'''
+		Returns True if on the selected period is available at least 50% of the time
+		Otherwise returns False
+		'''
+		return self.get_availability_percentage(only_working_hours=only_working_hours) > 50.0
+
+	@timeit
+	def plot_availability(self):
+		fig = plt.figure() #create new figure. This should ensure thread safe method
+		ax=fig.gca() #get current axes
+		matplotlib.rcParams['hatch.linewidth'] = 1
+		logger.warn('business_hours: {} {}'.format(self.office_start, self.office_end))
+		business_hours = self.business_hours = pd.Series(index=self.range, data=0)
+		mask = business_hours.between_time(self.office_start, self.office_end).index
+		business_hours[mask] = 1
+		ax = business_hours.plot(kind='area', alpha = 0.33, color='#1190D8', label='Business Hours', legend=True, ax=ax)
+
+		#calculate good xticks
+		hours = self._get_duration().total_seconds()/3600
+		n_ticks = int(hours/24)
+		if n_ticks == 0:
+			minutes = self._get_duration().total_seconds()/60
+			n_ticks = int(minutes/60)
+			if n_ticks == 0:
+				n_ticks = 1
+			xticks=self.availability.asfreq('{}T'.format(n_ticks)).index
+		else:
+			xticks=self.availability.asfreq('{}H'.format(n_ticks)).index
+
+		title = 'Availability for {} from {} to {}'.format(self.name, self.start.strftime('%Y/%m/%d %H:%M'), self.end.strftime('%Y/%m/%d %H:%M'))
+
+		ax = self.availability.plot(figsize=(16, 8), grid = True, 
+			title=title, legend=True, label='Availability', color='#00af52',
+			xticks=xticks, ax=ax, yticks=[0,1])
+		
+		ax.fill_between(self.availability.index, self.availability.tolist(), facecolor="none", hatch='//', edgecolor="#00af52", alpha=1, linewidth=0.5)
+		ax.set_axisbelow(True)
+		ax.yaxis.grid(color='gray', linewidth=0.5, alpha=0)
+		ax.xaxis.grid(color='gray', linewidth=0.5, alpha=1)
+		ax.set_yticklabels(['False', 'True'])
+		ax.set_ylabel('Is Available ?')
+		ax.set_xlabel('Date & Time')
+
+		fig.tight_layout()
+		fig.savefig('{}_{}_{}.pdf'.format(self.name, self.start.strftime('%Y%m%d%H%M'), self.end.strftime('%Y%m%d%H%M')))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/smash/web/static/js/daily_planning.js b/smash/web/static/js/daily_planning.js
index 1f8265a095241a09db9545ac11048d80f4809320..3806eae42d06a0a1e2a35a9971939cc8fc27191a 100644
--- a/smash/web/static/js/daily_planning.js
+++ b/smash/web/static/js/daily_planning.js
@@ -368,7 +368,21 @@ $(document).ready(function () {
         droppable: true,
         resourceAreaWidth: '15%',
         resourceLabelText: 'Workers',
-        resources: resources_url,
+        refetchResourcesOnNavigate: true,
+        resourceOrder: '-availability',
+        resources: function(callback){
+                        setTimeout(function(){
+                            var view = $('#calendar').fullCalendar('getView');
+                            $.ajax({
+                                url: resources_url,
+                                type: 'GET',
+                                cache: false,
+                                data: {
+                                    start_date: view.start.format('YYYY-MM-DD'),
+                                    }
+                                }).then(function(resources){callback(resources)});                  
+                        }, 0);
+        },
         events: [],
         eventRender: function (event, element) {
             if (event.rendering !== 'background') {