'Queries the DB for user jobs in error. Filters out monitor jobs.'

@web.expose
def per_month_in_error(self, trans, **kwd):

    message = ''
    PageSpec = namedtuple('PageSpec', ['entries', 'offset', 'page', 'pages_found'])
    params = util.Params(kwd)
    monitor_email = params.get('monitor_email', 'monitor@bx.psu.edu')
    specs = sorter('date', kwd)
    sort_id = specs.sort_id
    order = specs.order
    arrow = specs.arrow
    _order = specs.exc_order
    offset = 0
    limit = 10
    if ('entries' in kwd):
        entries = int(kwd.get('entries'))
    else:
        entries = 10
    limit = (entries * 4)
    if ('offset' in kwd):
        offset = int(kwd.get('offset'))
    else:
        offset = 0
    if ('page' in kwd):
        page = int(kwd.get('page'))
    else:
        page = 1
    monitor_user_id = get_monitor_id(trans, monitor_email)
    jobs_in_error_by_month = sa.select((self.select_month(model.Job.table.c.create_time).label('date'), sa.func.count(model.Job.table.c.id).label('total_jobs')), whereclause=sa.and_((model.Job.table.c.state == 'error'), (model.Job.table.c.user_id != monitor_user_id)), from_obj=[model.Job.table], group_by=self.group_by_month(model.Job.table.c.create_time), order_by=[_order], offset=offset, limit=limit)
    all_jobs = sa.select((self.select_day(model.Job.table.c.create_time).label('date'), model.Job.table.c.id.label('id')), whereclause=sa.and_((model.Job.table.c.state == 'error'), (model.Job.table.c.user_id != monitor_user_id)))
    trends = self._calculate_trends_for_jobs(all_jobs)
    jobs = self._calculate_job_table(jobs_in_error_by_month)
    pages_found = ceil((len(jobs) / float(entries)))
    page_specs = PageSpec(entries, offset, page, pages_found)
    return trans.fill_template('/webapps/reports/jobs_per_month_in_error.mako', order=order, arrow=arrow, sort_id=sort_id, trends=trends, jobs=jobs, message=message, is_user_jobs_only=monitor_user_id, page_specs=page_specs, offset=offset, limit=limit)
