def test_connector_with_multi_tenants(self):
     set_tenant_map({get_unittest_tenant_name(): 'NC', 'b': 'AB'})
     dummy_session = DummySession()
     dummy_session.set_tenants([get_unittest_tenant_name(), 'dummyTenant'])
     self.__config.testing_securitypolicy(dummy_session)
     conn = EdCoreDBConnection(state_code='NC')
     self.assertIsInstance(conn, EdCoreDBConnection)
     dim_student = conn.get_table('dim_student')
     self.assertEqual(dim_student.name, 'dim_student')
示例#2
0
 def __init__(self, tenant=None, state_code=None, is_public=False):
     '''
     :params str tenant:  Name of tenant
     :params str state_code name of state_code
     :params bool is_public.  True if we want to access de-identified datastore
     '''
     if is_public:
         self.db_conn = PublicDBConnection(tenant=tenant, state_code=state_code)
     else:
         self.db_conn = EdCoreDBConnection(tenant=tenant, state_code=state_code)
def _prepare_data(param, extract_type):
    '''
    Prepare record for available pre-query extract
    '''
    asmt_guid_with_grades = []
    dim_asmt = None
    fact_table = None
    FACT_TABLE = {
        AssessmentType.INTERIM_ASSESSMENT_BLOCKS:
        Constants.FACT_BLOCK_ASMT_OUTCOME,
        AssessmentType.SUMMATIVE: Constants.FACT_ASMT_OUTCOME_VW,
        AssessmentType.INTERIM_COMPREHENSIVE: Constants.FACT_ASMT_OUTCOME_VW
    }

    prequery_func = PREQUERY_FUNCTIONS[param['asmtType']]
    available_records = prequery_func(param, extract_type)
    for record_by_asmt_type in available_records:
        record = (record_by_asmt_type[Constants.ASMT_GUID],
                  record_by_asmt_type[Constants.ASMT_GRADE])
        if (Constants.EFFECTIVE_DATE in record_by_asmt_type):
            # IAB records
            record_iab = (record_by_asmt_type[Constants.EFFECTIVE_DATE],
                          record_by_asmt_type[Constants.ASMT_CLAIM_1_NAME])
        else:
            record_iab = ()
        asmt_guid_with_grades.append(record + record_iab)

    if asmt_guid_with_grades:
        with EdCoreDBConnection(
                state_code=param.get(Constants.STATECODE)) as connector:
            dim_asmt = connector.get_table(Constants.DIM_ASMT)
            fact_table = connector.get_table(FACT_TABLE[param['asmtType']])
    # Returns list of asmt guid with grades, and table objects
    return asmt_guid_with_grades, dim_asmt, fact_table
示例#4
0
def get_extract_assessment_item_and_raw_count_query(params, extract_type):
    """
    private method to generate SQLAlchemy object or sql code for extraction of
    students for item level/raw data

    :param params: for query parameters asmt_year, asmt_type, asmt_subject,
    asmt_grade
    :param extract_type: Type of extraction: Item Level, Raw Data Level,
    Student Assessment
    """
    state_code = params.get(Constants.STATECODE)

    with EdCoreDBConnection(state_code=state_code) as connector:
        fact_asmt_outcome_vw = connector.get_table(
            Constants.FACT_ASMT_OUTCOME_VW)
        query = select_with_context(
            [func.count().label(Constants.COUNT)],
            from_obj=[fact_asmt_outcome_vw],
            permission=get_required_permission(extract_type),
            state_code=state_code)

        query = _assessment_item_and_raw_where_clause_builder(
            query, fact_asmt_outcome_vw, params)

    return query
示例#5
0
def get_academic_year_query(academic_year, state_code):
    with EdCoreDBConnection(state_code=state_code) as connection:
        student_reg = connection.get_table(Constants.STUDENT_REG)
        academic_year_query = select_with_context([student_reg.c.state_code,
                                                   student_reg.c.state_name,
                                                   student_reg.c.district_id,
                                                   student_reg.c.district_name,
                                                   student_reg.c.school_id,
                                                   student_reg.c.school_name,
                                                   student_reg.c.sex,
                                                   student_reg.c.enrl_grade,
                                                   student_reg.c.dmg_eth_hsp,
                                                   student_reg.c.dmg_eth_ami,
                                                   student_reg.c.dmg_eth_asn,
                                                   student_reg.c.dmg_eth_blk,
                                                   student_reg.c.dmg_eth_pcf,
                                                   student_reg.c.dmg_eth_wht,
                                                   student_reg.c.dmg_prg_iep,
                                                   student_reg.c.dmg_prg_lep,
                                                   student_reg.c.dmg_prg_504,
                                                   student_reg.c.dmg_sts_ecd,
                                                   student_reg.c.dmg_sts_mig,
                                                   student_reg.c.dmg_multi_race,
                                                   student_reg.c.academic_year],
                                                  from_obj=[student_reg], permission=RolesConstants.SRC_EXTRACTS,
                                                  state_code=state_code)\
            .where(student_reg.c.academic_year == academic_year)

    return academic_year_query
示例#6
0
def select_with_context(columns=None,
                        whereclause=None,
                        from_obj=[],
                        permission=RolesConstants.PII,
                        **kwargs):
    '''
    Returns a SELECT clause statement with context security attached in the WHERE clause

    Note: state_code must be passed in as kwargs for database routing for multi tenant users
    '''
    # Retrieve state code for db connection routing
    state_code = kwargs.get(Constants.STATE_CODE)
    kwargs.pop(Constants.STATE_CODE, None)
    with EdCoreDBConnection(state_code=state_code) as connector:
        # Get user role and guid
        user = __get_user_info()

        # Build query
        query = Select(columns,
                       whereclause=whereclause,
                       from_obj=from_obj,
                       **kwargs)

        if permission not in user.get_roles():
            raise HTTPForbidden()
        context = __get_context_instance(permission, connector)
        # Get context security expression to attach to where clause
        query = context.add_context(get_tenant_by_state_code(state_code), user,
                                    query)

    return query
def get_student_reg_academic_years(state_code, tenant=None):
    with EdCoreDBConnection(tenant=tenant,
                            state_code=state_code) as connection:
        student_reg = connection.get_table(Constants.STUDENT_REG)
        query = select([distinct(student_reg.c.academic_year).label(Constants.ACADEMIC_YEAR)])\
            .where(student_reg.c.state_code == state_code).order_by(student_reg.c.academic_year.desc())
        results = connection.get_result(query)
    return list(result[Constants.ACADEMIC_YEAR] for result in results)
示例#8
0
class ReportingDbConnection():
    '''
    Used for routing between public and private dbs
    '''
    def __init__(self, tenant=None, state_code=None, is_public=False):
        '''
        :params str tenant:  Name of tenant
        :params str state_code name of state_code
        :params bool is_public.  True if we want to access de-identified datastore
        '''
        if is_public:
            self.db_conn = PublicDBConnection(tenant=tenant, state_code=state_code)
        else:
            self.db_conn = EdCoreDBConnection(tenant=tenant, state_code=state_code)

    def __enter__(self):
        return self.db_conn

    def __exit__(self, exc_type, value, tb):
        self.db_conn.close_connection()
def _get_asmt_records_iab(param, extract_type):
    '''
    query all asmt_guid and asmt_grade by given extract request params
    '''
    asmt_type = param.get(Constants.ASMTTYPE)
    asmt_subject = param.get(Constants.ASMTSUBJECT)
    state_code = param.get(Constants.STATECODE)
    district_id = param.get(Constants.DISTRICTGUID)
    school_id = param.get(Constants.SCHOOLGUID)
    asmt_grade = param.get(Constants.ASMTGRADE)
    asmt_year = param.get(Constants.ASMTYEAR)
    student_id = param.get(Constants.STUDENTGUID)
    # TODO: remove dim_asmt
    with EdCoreDBConnection(state_code=state_code) as connector:
        dim_asmt = connector.get_table(Constants.DIM_ASMT)
        fact_block_asmt_outcome = connector.get_table(
            Constants.FACT_BLOCK_ASMT_OUTCOME)
        dim_student = connector.get_table(Constants.DIM_STUDENT)
        query = select_with_context([dim_asmt.c.asmt_guid.label(Constants.ASMT_GUID),
                                     dim_asmt.c.effective_date.label(Constants.EFFECTIVE_DATE),
                                     dim_asmt.c.asmt_claim_1_name.label(Constants.ASMT_CLAIM_1_NAME),
                                     fact_block_asmt_outcome.c.asmt_grade.label(Constants.ASMT_GRADE)],
                                    from_obj=[dim_asmt
                                              .join(fact_block_asmt_outcome, and_(dim_asmt.c.asmt_rec_id == fact_block_asmt_outcome.c.asmt_rec_id))], permission=get_required_permission(extract_type), state_code=state_code)\
            .where(and_(fact_block_asmt_outcome.c.state_code == state_code))\
            .where(and_(fact_block_asmt_outcome.c.asmt_type == asmt_type))\
            .where(and_(fact_block_asmt_outcome.c.asmt_subject == asmt_subject))\
            .where(and_(fact_block_asmt_outcome.c.rec_status == Constants.CURRENT))\
            .group_by(dim_asmt.c.asmt_guid, dim_asmt.c.effective_date, dim_asmt.c.asmt_claim_1_name, fact_block_asmt_outcome.c.asmt_grade)

        if district_id is not None:
            query = query.where(
                and_(fact_block_asmt_outcome.c.district_id == district_id))
        if school_id is not None:
            query = query.where(
                and_(fact_block_asmt_outcome.c.school_id == school_id))
        if asmt_grade is not None:
            query = query.where(
                and_(fact_block_asmt_outcome.c.asmt_grade == asmt_grade))
        if asmt_year is not None:
            query = query.where(
                and_(fact_block_asmt_outcome.c.asmt_year == asmt_year))
        if student_id:
            query = query.where(
                and_(fact_block_asmt_outcome.c.student_id.in_(student_id)))

        query = apply_filter_to_query(query, fact_block_asmt_outcome,
                                      dim_student, param)
        results = connector.get_result(query)
    return results
示例#10
0
def check_context(permission, state_code, student_ids):
    '''
    Given a list of student guids, return true if user has access to see their data, false otherwise

    :param student_ids: guids of students that we want to check whether the user has context to
    :type student_ids: list
    '''
    if not student_ids:
        return False

    with EdCoreDBConnection(state_code=state_code) as connector:
        # Get user role and guid
        user = __get_user_info()
        context = __get_context_instance(permission, connector)
        return context.check_context(get_tenant_by_state_code(state_code),
                                     user, student_ids)
def generate_csv(tenant, output_file, task_info, extract_args):
    """
    Write data extract to CSV file.

    @param tenant: Requestor's tenant ID
    @param output_file: File pathname of extract file
    @param task_info: Task information for recording stats    @param extract_args: Arguments specific to generate_csv
    """

    query = extract_args[TaskConstants.TASK_QUERIES][QueryType.QUERY]
    with EdCoreDBConnection(tenant=tenant) as connection:
        results = connection.get_streaming_result(query)  # this result is a generator
        header, data = _generate_csv_data(results)
        with open(output_file, 'w') as f:
            write_csv(f, data, header=header)
        insert_extract_stats(task_info, {Constants.STATUS: ExtractStatus.EXTRACTED})
def estimate_extract_total_file_size(params, avg_file_size, extract_type):
    """
    returns an estimate of the number of extract files based on query params and extract type

    @param params: Extract query params
    """
    return_number = -1
    state_code = params.get(Constants.STATECODE)
    with EdCoreDBConnection(state_code=state_code) as connector:
        query = get_extract_assessment_item_and_raw_count_query(
            params, extract_type)
        results = connector.get_result(query)
        return_number = results[0][Constants.COUNT]
    if return_number > 0:
        if avg_file_size > 0:
            return return_number * avg_file_size
    return 0
示例#13
0
def get_assessment_query(academic_year, state_code):
    with EdCoreDBConnection(state_code=state_code) as connection:
        student_reg = connection.get_table(Constants.STUDENT_REG)
        asmt_outcome = connection.get_table(Constants.FACT_ASMT_OUTCOME_VW)

        assmt_query = select_with_context([asmt_outcome.c.student_id,
                                           asmt_outcome.c.asmt_subject,
                                           asmt_outcome.c.asmt_type,
                                           asmt_outcome.c.asmt_year],
                                          from_obj=[asmt_outcome],
                                          permission=RolesConstants.SRC_EXTRACTS,
                                          state_code=state_code)\
            .distinct(asmt_outcome.c.student_id, asmt_outcome.c.asmt_subject, asmt_outcome.c.asmt_type)\
            .where(and_(asmt_outcome.c.rec_status == Constants.CURRENT, asmt_outcome.c.asmt_year == academic_year))\
            .alias(name=Constants.FACT_ASMT_OUTCOME_VW)

        academic_year_query = select_with_context([student_reg.c.state_code,
                                                   student_reg.c.state_name,
                                                   student_reg.c.district_id,
                                                   student_reg.c.district_name,
                                                   student_reg.c.school_id,
                                                   student_reg.c.school_name,
                                                   student_reg.c.sex,
                                                   student_reg.c.enrl_grade,
                                                   student_reg.c.dmg_eth_hsp,
                                                   student_reg.c.dmg_eth_ami,
                                                   student_reg.c.dmg_eth_asn,
                                                   student_reg.c.dmg_eth_blk,
                                                   student_reg.c.dmg_eth_pcf,
                                                   student_reg.c.dmg_eth_wht,
                                                   student_reg.c.dmg_prg_iep,
                                                   student_reg.c.dmg_prg_lep,
                                                   student_reg.c.dmg_prg_504,
                                                   student_reg.c.dmg_sts_ecd,
                                                   student_reg.c.dmg_sts_mig,
                                                   student_reg.c.dmg_multi_race,
                                                   student_reg.c.academic_year,
                                                   assmt_query.c.asmt_subject,
                                                   assmt_query.c.asmt_type],
                                                  from_obj=[student_reg.join(assmt_query, student_reg.c.student_id == assmt_query.c.student_id)],
                                                  permission=RolesConstants.SRC_EXTRACTS,
                                                  state_code=state_code)\
            .where(student_reg.c.academic_year == academic_year)

    return academic_year_query
def get_asmt_administration(state_code,
                            district_id=None,
                            school_id=None,
                            asmt_grade=None,
                            student_ids=None,
                            asmt_year=None):
    '''
    Get asmt administration for a list of students. There is no PII in the results and it can be stored in shortlived cache
    '''
    with EdCoreDBConnection(state_code=state_code) as connection:
        fact_asmt_outcome_vw = connection.get_table(
            Constants.FACT_ASMT_OUTCOME_VW)
        dim_asmt = connection.get_table(Constants.DIM_ASMT)
        query = select([
            dim_asmt.c.asmt_period_year, fact_asmt_outcome_vw.c.asmt_type,
            fact_asmt_outcome_vw.c.asmt_grade
        ],
                       from_obj=[fact_asmt_outcome_vw, dim_asmt])
        query = query.where(fact_asmt_outcome_vw.c.asmt_rec_id == dim_asmt.c.asmt_rec_id).\
            where(fact_asmt_outcome_vw.c.state_code == state_code).\
            where(and_(fact_asmt_outcome_vw.c.rec_status == Constants.CURRENT)).\
            where(and_(fact_asmt_outcome_vw.c.asmt_type.in_([AssessmentType.SUMMATIVE, AssessmentType.INTERIM_COMPREHENSIVE]))).\
            group_by(dim_asmt.c.asmt_period_year, fact_asmt_outcome_vw.c.asmt_type, fact_asmt_outcome_vw.c.asmt_grade,).\
            order_by(fact_asmt_outcome_vw.c.asmt_type.desc(), dim_asmt.c.asmt_period_year.desc())
        if district_id:
            query = query.where(
                and_(fact_asmt_outcome_vw.c.district_id == district_id))
        if school_id:
            query = query.where(
                and_(fact_asmt_outcome_vw.c.school_id == school_id))
        if asmt_grade:
            query = query.where(
                and_(fact_asmt_outcome_vw.c.asmt_grade == asmt_grade))
        if student_ids:
            query = query.where(
                and_(fact_asmt_outcome_vw.c.student_id.in_(student_ids))
            ) if isinstance(student_ids, list) else query.where(
                and_(fact_asmt_outcome_vw.c.student_id == student_ids))
        if asmt_year:
            query = query.where(
                and_(fact_asmt_outcome_vw.c.asmt_year == asmt_year))
        results = connection.get_result(query)
    return results
def get_match_id_query(academic_year, state_code):
    with EdCoreDBConnection(state_code=state_code) as connection:
        student_reg = connection.get_table(Constants.STUDENT_REG)
        current_sr = student_reg.alias()
        prev_sr = student_reg.alias()

        match_id_query = select_with_context([current_sr.c.state_code, prev_sr.c.state_code.label('prev_state_code'), current_sr.c.state_name, current_sr.c.district_id,
                                              prev_sr.c.district_id.label('prev_district_id'), current_sr.c.district_name, current_sr.c.school_id,
                                              prev_sr.c.school_id.label('prev_school_id'), current_sr.c.school_name, current_sr.c.sex, prev_sr.c.sex.label('prev_sex'),
                                              current_sr.c.enrl_grade, prev_sr.c.enrl_grade.label('prev_enrl_grade'), current_sr.c.dmg_eth_hsp, prev_sr.c.dmg_eth_hsp.label('prev_dmg_eth_hsp'),
                                              current_sr.c.dmg_eth_ami, prev_sr.c.dmg_eth_ami.label('prev_dmg_eth_ami'), current_sr.c.dmg_eth_asn, prev_sr.c.dmg_eth_asn.label('prev_dmg_eth_asn'),
                                              current_sr.c.dmg_eth_blk, prev_sr.c.dmg_eth_blk.label('prev_dmg_eth_blk'), current_sr.c.dmg_eth_pcf, prev_sr.c.dmg_eth_pcf.label('prev_dmg_eth_pcf'),
                                              current_sr.c.dmg_eth_wht, prev_sr.c.dmg_eth_wht.label('prev_dmg_eth_wht'), current_sr.c.dmg_prg_iep,
                                              prev_sr.c.dmg_prg_iep.label('prev_dmg_prg_iep'), current_sr.c.dmg_prg_lep, prev_sr.c.dmg_prg_lep.label('prev_dmg_prg_lep'),
                                              current_sr.c.dmg_prg_504, prev_sr.c.dmg_prg_504.label('prev_dmg_prg_504'), current_sr.c.dmg_sts_ecd,
                                              prev_sr.c.dmg_sts_ecd.label('prev_dmg_sts_ecd'), current_sr.c.dmg_sts_mig,
                                              prev_sr.c.dmg_sts_mig.label('prev_dmg_sts_mig'), current_sr.c.dmg_multi_race, prev_sr.c.dmg_multi_race.label('prev_dmg_multi_race'), current_sr.c.academic_year],
                                             from_obj=[current_sr.join(prev_sr, and_(current_sr.c.student_id == prev_sr.c.student_id))], permission=RolesConstants.SRS_EXTRACTS, state_code=state_code)\
            .where(and_(current_sr.c.academic_year == academic_year, prev_sr.c.academic_year == academic_year - 1))
    return match_id_query
示例#16
0
def generate_raw_data_xml(tenant, output_paths, task_info, extract_args):
    '''
    Write raw xml data to output file

    @param tenant: Requestor's tenant ID
    @param output_paths: list of output path name's to place the selected raw data xml files
    @param task_info: Task information for recording stats
    @param extract_args: Arguments specific to generate_raw_data_xml
    '''
    query = extract_args[TaskConstants.TASK_QUERIES][QueryType.QUERY]
    root_dir = extract_args[TaskConstants.ROOT_DIRECTORY]
    if type(output_paths) is not list:
        output_paths = [output_paths]

    with EdCoreDBConnection(tenant=tenant) as connection:
        # Get results (streamed, it is important to avoid memory exhaustion)
        results = connection.get_streaming_result(query)
        _copy_files(root_dir, results, output_paths)
        # Done
        insert_extract_stats(task_info,
                             {Constants.STATUS: ExtractStatus.EXTRACTED})
示例#17
0
def get_extract_assessment_item_and_raw_query(params, extract_type):
    """
    private method to generate SQLAlchemy object or sql code for extraction of
    students for item level/raw data

    :param params: for query parameters asmt_year, asmt_type, asmt_subject,
    asmt_grade
    :param extract_type: Type of extraction: Item Level, Raw Data Level,
    Student Assessment
    """
    state_code = params.get(Constants.STATECODE)

    with EdCoreDBConnection(state_code=state_code) as connector:
        dim_asmt = connector.get_table(Constants.DIM_ASMT)
        fact_asmt_outcome_vw = connector.get_table(
            Constants.FACT_ASMT_OUTCOME_VW)
        # TODO: Look at removing dim_asmt
        query = select_with_context(
            [
                fact_asmt_outcome_vw.c.state_code,
                fact_asmt_outcome_vw.c.asmt_year,
                fact_asmt_outcome_vw.c.asmt_type, dim_asmt.c.effective_date,
                fact_asmt_outcome_vw.c.asmt_subject,
                fact_asmt_outcome_vw.c.asmt_grade,
                fact_asmt_outcome_vw.c.district_id,
                fact_asmt_outcome_vw.c.student_id
            ],
            from_obj=[
                fact_asmt_outcome_vw.join(
                    dim_asmt,
                    and_(dim_asmt.c.asmt_rec_id ==
                         fact_asmt_outcome_vw.c.asmt_rec_id))
            ],
            permission=get_required_permission(extract_type),
            state_code=state_code)
        query = _assessment_item_and_raw_where_clause_builder(
            query, fact_asmt_outcome_vw, params)

    return query
def prepare_pre_cache(tenant, state_code, batch_guid):
    '''
    prepare which state and district are pre-cached

    :param string tenant:  name of the tenant
    :param string state_code:  stateCode representing the state
    :param last_pre_cached:  dateTime of the last precached
    :rType: list
    :return:  list of results containing district guids
    '''
    with EdCoreDBConnection(tenant=tenant) as connector:
        fact_asmt_outcome_vw = connector.get_table(
            Constants.FACT_ASMT_OUTCOME_VW)
        fact_block_asmt_outcome = connector.get_table(
            Constants.FACT_BLOCK_ASMT_OUTCOME)
        query_fao = select([
            distinct(fact_asmt_outcome_vw.c.district_id).label(
                Constants.DISTRICT_ID)
        ],
                           from_obj=[fact_asmt_outcome_vw])
        query_fao = query_fao.where(
            fact_asmt_outcome_vw.c.state_code == state_code)
        query_fao = query_fao.where(
            and_(fact_asmt_outcome_vw.c.batch_guid == batch_guid))
        query_fao = query_fao.where(
            and_(fact_asmt_outcome_vw.c.rec_status == Constants.CURRENT))
        query_fbao = select([
            distinct(fact_block_asmt_outcome.c.district_id).label(
                Constants.DISTRICT_ID)
        ],
                            from_obj=[fact_block_asmt_outcome])
        query_fbao = query_fbao.where(
            fact_block_asmt_outcome.c.state_code == state_code)
        query_fbao = query_fbao.where(
            and_(fact_block_asmt_outcome.c.batch_guid == batch_guid))
        query_fbao = query_fbao.where(
            and_(fact_block_asmt_outcome.c.rec_status == Constants.CURRENT))
        results = connector.get_result(query_fao.union(query_fbao))
        return results
示例#19
0
def prepare_pre_pdf(tenant, state_code, batch_guid):
    '''
    prepare which state and district are pre-cached

    :param string tenant: name of the tenant
    :param string state_code: stateCode representing the state
    :param string batch_guid: batch GUID
    :rType: list
    :return:  list of results containing student information used to generate pdf
    '''
    with EdCoreDBConnection(tenant=tenant) as connector:
        fact_asmt_outcome_vw = connector.get_table(
            Constants.FACT_ASMT_OUTCOME_VW)
        dim_asmt = connector.get_table(Constants.DIM_ASMT)
        query = select([
            distinct(fact_asmt_outcome_vw.c.student_id).label(
                Constants.STUDENT_ID),
            dim_asmt.c.asmt_period_year.label(Constants.ASMT_PERIOD_YEAR),
            fact_asmt_outcome_vw.c.date_taken.label(Constants.DATETAKEN),
            dim_asmt.c.asmt_type.label(Constants.ASMT_TYPE),
            fact_asmt_outcome_vw.c.district_id.label(Constants.DISTRICT_ID),
            fact_asmt_outcome_vw.c.school_id.label(Constants.SCHOOL_ID),
            fact_asmt_outcome_vw.c.asmt_grade.label(Constants.ASMT_GRADE)
        ],
                       from_obj=[
                           fact_asmt_outcome_vw.join(
                               dim_asmt,
                               and_(
                                   dim_asmt.c.asmt_rec_id ==
                                   fact_asmt_outcome_vw.c.asmt_rec_id,
                                   dim_asmt.c.rec_status == Constants.CURRENT))
                       ])
        query = query.where(fact_asmt_outcome_vw.c.state_code == state_code)
        query = query.where(
            and_(fact_asmt_outcome_vw.c.batch_guid == batch_guid))
        query = query.where(
            and_(fact_asmt_outcome_vw.c.rec_status == Constants.CURRENT))
        results = connector.get_result(query)
        return results
def generate_json(tenant, output_file, task_info, extract_args):
    """
    Write data extract to JSON file.

    @param tenant: Requestor's tenant ID
    @param output_file: File pathname of extract file
    @param task_info: Task information for recording stats
    @param extract_args: Arguments specific to generate_json
    """

    query = extract_args[TaskConstants.TASK_QUERIES][QueryType.QUERY]

    with EdCoreDBConnection(tenant=tenant) as connection, open(output_file, 'w') as json_file:
        results = connection.get_result(query)

        # There should only be one result in the list
        if len(results) is 1:
            formatted = format_json(results[0])
            json.dump(formatted, json_file, indent=4)
            insert_extract_stats(task_info, {Constants.STATUS: ExtractStatus.GENERATED_JSON})
        else:
            insert_extract_stats(task_info, {Constants.STATUS: ExtractStatus.FAILED, Constants.INFO: "Results length is: " + str(len(results))})
def get_district_level_context_names(tenant, state_code, district_id):
    if state_code:
        with EdCoreDBConnection(tenant=tenant,
                                state_code=state_code) as connector:
            dim_inst_hier = connector.get_table(Constants.DIM_INST_HIER)
            # Limit result count to one
            # We limit the results to one since we'll get multiple rows with the same values
            # Think of the case of querying for state name and id, we'll get all the schools in that state
            query = select([
                dim_inst_hier.c.state_code.label(Constants.STATE_CODE),
                dim_inst_hier.c.district_id.label(Constants.DISTRICT_ID),
                dim_inst_hier.c.district_name.label(Constants.DISTRICT_NAME),
                dim_inst_hier.c.school_name.label(Constants.SCHOOL_NAME),
                dim_inst_hier.c.school_id.label(Constants.SCHOOL_ID)
            ],
                           from_obj=[dim_inst_hier])

            query = query.where(
                and_(dim_inst_hier.c.rec_status == Constants.CURRENT))
            query = query.where(and_(dim_inst_hier.c.state_code == state_code))
            query = query.where(
                and_(dim_inst_hier.c.district_id == district_id))

            # run it and format the results
            results = connector.get_result(query)
            if results:
                schools = {
                    r[Constants.SCHOOL_ID]: {
                        Constants.NAME: r[Constants.SCHOOL_NAME],
                        Constants.SCHOOLGUID: r[Constants.SCHOOL_ID]
                    }
                    for r in results
                }
                return {
                    Constants.NAME: results[0][Constants.DISTRICT_NAME],
                    'schools': schools
                }
    return {}
def get_block_asmt_administration(state_code,
                                  district_id=None,
                                  school_id=None,
                                  asmt_grade=None,
                                  student_ids=None,
                                  asmt_year=None):
    '''
    Block assessment administration years
    '''
    with EdCoreDBConnection(state_code=state_code) as connection:
        fact_block_asmt = connection.get_table(
            Constants.FACT_BLOCK_ASMT_OUTCOME)
        dim_asmt = connection.get_table(Constants.DIM_ASMT)
        query = select(
            [dim_asmt.c.asmt_period_year, fact_block_asmt.c.asmt_type],
            from_obj=[fact_block_asmt, dim_asmt])
        query = query.where(fact_block_asmt.c.asmt_rec_id == dim_asmt.c.asmt_rec_id).\
            where(fact_block_asmt.c.state_code == state_code).\
            where(and_(fact_block_asmt.c.asmt_type == AssessmentType.INTERIM_ASSESSMENT_BLOCKS)).\
            where(and_(fact_block_asmt.c.rec_status == Constants.CURRENT)).\
            group_by(dim_asmt.c.asmt_period_year, fact_block_asmt.c.asmt_type)
        if district_id:
            query = query.where(
                and_(fact_block_asmt.c.district_id == district_id))
        if school_id:
            query = query.where(and_(fact_block_asmt.c.school_id == school_id))
        if asmt_grade:
            query = query.where(
                and_(fact_block_asmt.c.asmt_grade == asmt_grade))
        if student_ids:
            query = query.where(
                and_(fact_block_asmt.c.student_id.in_(student_ids))
            ) if isinstance(student_ids, list) else query.where(
                and_(fact_block_asmt.c.student_id == student_ids))
        if asmt_year:
            query = query.where(and_(fact_block_asmt.c.asmt_year == asmt_year))
        results = connection.get_result(query)
    return results
def generate_items_csv(tenant, output_files, task_info, extract_args):
    '''
    Write item-level data to CSV file

    @param tenant: Requestor's tenant ID
    @param output_files: List of output file path's for item extract
    @param task_info: Task information for recording stats
    @param extract_args: Arguments specific to generate_items_csv
    '''
    # Get stuff
    query = extract_args[TaskConstants.TASK_QUERIES][QueryType.QUERY]
    items_root_dir = extract_args[TaskConstants.ROOT_DIRECTORY]
    item_ids = extract_args[TaskConstants.ITEM_IDS]

    with EdCoreDBConnection(tenant=tenant) as connection:
        # Get results (streamed, it is important to avoid memory exhaustion)
        results = connection.get_streaming_result(query, fetch_size=10240)

        _append_csv_files(items_root_dir, item_ids, results, output_files,
                          CSV_HEADER)
        # Done
        insert_extract_stats(task_info,
                             {Constants.STATUS: ExtractStatus.EXTRACTED})
示例#24
0
def get_summary_distribution(state_code,
                             district_id=None,
                             school_id=None,
                             asmt_type=AssessmentType.SUMMATIVE):
    '''
    Get a bucketed distribution of scores
    '''
    with EdCoreDBConnection(state_code=state_code) as connection:
        fact_asmt_outcome_vw = connection.get_table('fact_asmt_outcome')
        #  should it be always for summative?
        query = select([
            label(Constants.SCORE_BUCKET,
                  (fact_asmt_outcome_vw.c.asmt_score / get_bucket_size()) *
                  get_bucket_size()),
            count(
                case([(fact_asmt_outcome_vw.c.asmt_subject
                       == Constants.MATH, 1)],
                     else_=0)).label(Constants.TOTAL_MATH),
            count(
                case([(fact_asmt_outcome_vw.c.asmt_subject == Constants.ELA, 1)
                      ],
                     else_=0)).label(Constants.TOTAL_ELA)
        ],
                       from_obj=[fact_asmt_outcome_vw])
        query = query.where(fact_asmt_outcome_vw.c.state_code == state_code)
        query = query.where(fact_asmt_outcome_vw.c.asmt_type == asmt_type)
        query = query.where(
            fact_asmt_outcome_vw.c.rec_status == Constants.CURRENT)
        if (district_id is not None):
            query = query.where(
                fact_asmt_outcome_vw.c.district_id == district_id)
        if (school_id is not None):
            query = query.where(fact_asmt_outcome_vw.c.school_id == school_id)
        query = query.group_by(Constants.SCORE_BUCKET).order_by(
            Constants.SCORE_BUCKET)
        return connection.get_result(query)
示例#25
0
def _get_school_name(state_code, district_id, school_id):
    with EdCoreDBConnection(state_code=state_code) as connector:
        # Get handle to tables
        dim_inst_hier = connector.get_table(Constants.DIM_INST_HIER)

        # Build select
        query = select(
            [dim_inst_hier.c.school_name.label(Constants.SCHOOL_NAME)],
            from_obj=[dim_inst_hier])

        # Add where clauses
        query = query.where(dim_inst_hier.c.state_code == state_code)
        query = query.where(and_(dim_inst_hier.c.district_id == district_id))
        query = query.where(and_(dim_inst_hier.c.school_id == school_id))
        query = query.where(
            and_(dim_inst_hier.c.rec_status == Constants.CURRENT))

        # Return the result
        results = connector.get_result(query)
        if len(results) == 1:
            return results[0][Constants.SCHOOL_NAME]
        else:
            logger.error('Bulk PDF : School name not found')
            raise InvalidParameterError('School name cannot be found')
def _generate_completion_report_data(tenant, academic_year, queries):
    """
    Get all the tenant's student registration completion data for the academic year.

    @param tenant: Requestor's tenant ID
    @param academic_year: Academic year of report
    @param queries: DB queries to extract rows

    @return: List of rows to be included in the CSV report.
    """

    academic_year_query = queries[QueryType.QUERY]
    assessment_outcome_query = queries[QueryType.ASMT_OUTCOME_QUERY]

    row_data_processor = RowDataProcessor()

    with EdCoreDBConnection(tenant=tenant) as connection:
        registered_results = connection.get_streaming_result(academic_year_query)  # This result is a generator
        row_data_processor.process_yearly_row_data(registered_results)

        assessment_outcome_results = connection.get_streaming_result(assessment_outcome_query)
        row_data_processor.process_asmt_outcome_row_data(assessment_outcome_results)

    return _get_sr_comp_tenant_data_for_academic_year(row_data_processor, academic_year)
def _generate_statistics_report_data(tenant, academic_year, queries):
    """
    Get all the tenant's student registration statistics data for the academic year.

    @param tenant: Requestor's tenant ID
    @param academic_year: Academic year of report
    @param queries: DB queries to extract rows

    @return: List of rows to be included in the CSV report.
    """

    academic_year_query = queries[QueryType.QUERY]
    match_id_query = queries[QueryType.MATCH_ID_QUERY]

    row_data_processor = RowDataProcessor()

    with EdCoreDBConnection(tenant=tenant) as connection:
        academic_year_results = connection.get_streaming_result(academic_year_query)  # This result is a generator
        row_data_processor.process_yearly_row_data(academic_year_results)

        match_id_results = connection.get_streaming_result(match_id_query)
        row_data_processor.process_matched_ids_row_data(match_id_results)

    return _get_sr_stat_tenant_data_for_academic_year(row_data_processor, academic_year)
 def test_get_datasource_name_without_tenant(self):
     name = EdCoreDBConnection.get_datasource_name()
     self.assertEquals(name, None)
 def setUpClass(cls):
     super().setUpClass(EdCoreDBConnection.get_datasource_name(get_unittest_tenant_name()))
 def test_connector(self):
     conn = EdCoreDBConnection(tenant=get_unittest_tenant_name())
     self.assertIsInstance(conn, EdCoreDBConnection)
     dim_student = conn.get_table('dim_student')
     self.assertEqual(dim_student.name, 'dim_student')
def get_student_report(params):
    '''
    Individual Student Report
    '''
    student_id = params[Constants.STUDENTGUID]
    state_code = params[Constants.STATECODE]
    academic_year = params.get(Constants.ASMTYEAR)
    asmt_type = params.get(Constants.ASMTTYPE)
    asmt_type = asmt_type if asmt_type and asmt_type == AssessmentType.INTERIM_ASSESSMENT_BLOCKS else None

    with EdCoreDBConnection(state_code=state_code) as connection:
        # choose query IAB or other assessment
        query_function = {
            AssessmentType.INTERIM_ASSESSMENT_BLOCKS: __prepare_query_iab,
            None: __prepare_query
        }
        # choose arrange results for the client IAB or other assessment
        arrange_function = {
            AssessmentType.INTERIM_ASSESSMENT_BLOCKS: __arrange_results_iab,
            None: __arrange_results
        }
        query = query_function[asmt_type](connection, params)
        result = connection.get_result(query)
        if not result:
            logger.error(
                "Individual student report: there are no results for student id : %s",
                student_id)
            raise NotFoundException(
                "There are no results for student id {0}".format(student_id))
        records = [
            record for record in result
            if record['asmt_period_year'] == academic_year
        ]
        first_student = records[0] if len(records) > 0 else result[0]
        state_code = first_student[Constants.STATE_CODE]
        district_id = first_student[Constants.DISTRICT_ID]
        school_id = first_student[Constants.SCHOOL_ID]
        asmt_grade = first_student['asmt_grade']
        student_name = format_full_name(first_student['first_name'],
                                        first_student['middle_name'],
                                        first_student['last_name'])
        context = get_breadcrumbs_context(state_code=state_code,
                                          district_id=district_id,
                                          school_id=school_id,
                                          asmt_grade=asmt_grade,
                                          student_name=student_name)
        student_report_asmt_administration = get_asmt_administration_years_isr(
            state_code, student_ids=student_id)

        # color metadata
        custom_metadata_map = get_custom_metadata(
            result[0].get(Constants.STATE_CODE), None)
        # subjects map
        subjects_map = get_subjects_map()
        result = arrange_function[asmt_type](result, subjects_map,
                                             custom_metadata_map)

        result['context'] = context
        result[Constants.METADATA] = {
            Constants.BRANDING: custom_metadata_map.get(Constants.BRANDING)
        }
        result[Constants.SUBJECTS] = {v: k for k, v in subjects_map.items()}
        result['asmt_administration'] = student_report_asmt_administration
    return result
示例#32
0
def generate_isr_report_path_by_student_id(state_code,
                                           date_taken=None,
                                           asmt_year=None,
                                           pdf_report_base_dir='/',
                                           student_ids=None,
                                           asmt_type=AssessmentType.SUMMATIVE,
                                           grayScale=True,
                                           lang='en'):
    '''
    Get Individual Student Report absolute path by student_id.
    If the directory path does not exist, then create it.
    For security, the directory will be created with only the owner can read-write.
    '''
    if date_taken is None and asmt_year is None:
        raise AttributeError('Need one of date_taken or asmt_year')

    file_paths = {}
    if type(student_ids) is not list:
        student_ids = [student_ids]
    # find state_code, asmt_period_year, district_id, school_id, and asmt_grade from DB
    with EdCoreDBConnection(state_code=state_code) as connection:
        if asmt_type == AssessmentType.INTERIM_ASSESSMENT_BLOCKS:
            query = generate_query_for_iab(connection, student_ids, asmt_year)
        else:
            query = generate_query_for_summative_or_interim(
                connection, asmt_type, student_ids, asmt_year, date_taken)

        results = connection.get_result(query)
        if len(results) < len(student_ids):
            logger.error(
                "PDF error: Results count is less than student count.")
            raise NotFoundException(
                "Result count should be more than or equal to student count")
        for result in results:
            file_path_by_date = {}
            student_id = result[Constants.STUDENT_ID]
            state_code = result[Constants.STATE_CODE]
            asmt_period_year = str(result[Constants.ASMT_PERIOD_YEAR])
            date_taken = str(result[Constants.DATETAKEN]) if result.get(
                Constants.DATETAKEN) is not None else None
            district_id = result[Constants.DISTRICT_ID]
            school_id = result[Constants.SCHOOL_ID]
            asmt_grade = result.get(Constants.ASMT_GRADE)
            file_path = generate_isr_absolute_file_path_name(
                pdf_report_base_dir=pdf_report_base_dir,
                state_code=state_code,
                asmt_period_year=asmt_period_year,
                district_id=district_id,
                school_id=school_id,
                asmt_grade=asmt_grade,
                student_id=student_id,
                asmt_type=asmt_type,
                grayScale=grayScale,
                lang=lang,
                date_taken=date_taken)

            # get absolute file path name
            file_path_by_date[date_taken] = file_path
            if student_id in file_paths:
                file_path_by_date.update(file_paths[student_id])
            file_paths[student_id] = file_path_by_date
    return file_paths
示例#33
0
def get_asmt_metadata(state_code, asmt_guid):
    '''
    Generates a query for getting assessment information based on assessment guid

    :param str asmt_guid:  asessment guid
    '''
    with EdCoreDBConnection(state_code=state_code) as connector:
        dim_asmt = connector.get_table(Constants.DIM_ASMT)
        mapping = get_column_mapping(Constants.DIM_ASMT, json_mapping=True)
        query = select([
            literal("assessment").label("content"),
            dim_asmt.c.asmt_guid.label(mapping.get('asmt_guid', 'asmt_guid')),
            dim_asmt.c.asmt_type.label(mapping.get('asmt_type', 'asmt_type')),
            dim_asmt.c.asmt_period_year.label(
                mapping.get('asmt_period_year', 'asmt_period_year')),
            dim_asmt.c.asmt_period.label(
                mapping.get('asmt_period', 'asmt_period')),
            dim_asmt.c.asmt_version.label(
                mapping.get('asmt_version', 'asmt_version')),
            dim_asmt.c.asmt_subject.label(
                mapping.get('asmt_subject', 'asmt_subject')),
            dim_asmt.c.effective_date.label(
                mapping.get('effective_date', 'effective_date')),
            dim_asmt.c.asmt_score_min.label(
                mapping.get('asmt_score_min', 'asmt_score_min')),
            dim_asmt.c.asmt_score_max.label(
                mapping.get('asmt_score_max', 'asmt_score_max')),
            dim_asmt.c.asmt_perf_lvl_name_1.label(
                mapping.get('asmt_perf_lvl_name_1', 'asmt_perf_lvl_name_1')),
            dim_asmt.c.asmt_perf_lvl_name_2.label(
                mapping.get('asmt_perf_lvl_name_2', 'asmt_perf_lvl_name_2')),
            dim_asmt.c.asmt_perf_lvl_name_3.label(
                mapping.get('asmt_perf_lvl_name_3', 'asmt_perf_lvl_name_3')),
            dim_asmt.c.asmt_perf_lvl_name_4.label(
                mapping.get('asmt_perf_lvl_name_4', 'asmt_perf_lvl_name_4')),
            dim_asmt.c.asmt_perf_lvl_name_5.label(
                mapping.get('asmt_perf_lvl_name_5', 'asmt_perf_lvl_name_5')),
            dim_asmt.c.asmt_cut_point_1.label(
                mapping.get('asmt_cut_point_1', 'asmt_cut_point_1')),
            dim_asmt.c.asmt_cut_point_2.label(
                mapping.get('asmt_cut_point_2', 'asmt_cut_point_2')),
            dim_asmt.c.asmt_cut_point_3.label(
                mapping.get('asmt_cut_point_3', 'asmt_cut_point_3')),
            dim_asmt.c.asmt_cut_point_4.label(
                mapping.get('asmt_cut_point_4', 'asmt_cut_point_4')),
            dim_asmt.c.asmt_claim_1_name.label(
                mapping.get('asmt_claim_1_name', 'asmt_claim_1_name')),
            dim_asmt.c.asmt_claim_2_name.label(
                mapping.get('asmt_claim_2_name', 'asmt_claim_2_name')),
            dim_asmt.c.asmt_claim_3_name.label(
                mapping.get('asmt_claim_3_name', 'asmt_claim_3_name')),
            dim_asmt.c.asmt_claim_4_name.label(
                mapping.get('asmt_claim_4_name', 'asmt_claim_4_name')),
            dim_asmt.c.asmt_claim_1_score_min.label(
                mapping.get('asmt_claim_1_score_min',
                            'asmt_claim_1_score_min')),
            dim_asmt.c.asmt_claim_2_score_min.label(
                mapping.get('asmt_claim_2_score_min',
                            'asmt_claim_2_score_min')),
            dim_asmt.c.asmt_claim_3_score_min.label(
                mapping.get('asmt_claim_3_score_min',
                            'asmt_claim_3_score_min')),
            dim_asmt.c.asmt_claim_4_score_min.label(
                mapping.get('asmt_claim_4_score_min',
                            'asmt_claim_4_score_min')),
            dim_asmt.c.asmt_claim_1_score_max.label(
                mapping.get('asmt_claim_1_score_max',
                            'asmt_claim_1_score_max')),
            dim_asmt.c.asmt_claim_2_score_max.label(
                mapping.get('asmt_claim_2_score_max',
                            'asmt_claim_2_score_max')),
            dim_asmt.c.asmt_claim_3_score_max.label(
                mapping.get('asmt_claim_3_score_max',
                            'asmt_claim_3_score_max')),
            dim_asmt.c.asmt_claim_4_score_max.label(
                mapping.get('asmt_claim_4_score_max',
                            'asmt_claim_4_score_max')),
            dim_asmt.c.asmt_claim_perf_lvl_name_1.label(
                mapping.get('asmt_claim_perf_lvl_name_1',
                            'asmt_claim_perf_lvl_name_1')),
            dim_asmt.c.asmt_claim_perf_lvl_name_2.label(
                mapping.get('asmt_claim_perf_lvl_name_2',
                            'asmt_claim_perf_lvl_name_2')),
            dim_asmt.c.asmt_claim_perf_lvl_name_3.label(
                mapping.get('asmt_claim_perf_lvl_name_3',
                            'asmt_claim_perf_lvl_name_3'))
        ],
                       from_obj=[dim_asmt])
        query = query.where(
            and_(dim_asmt.c.asmt_guid == asmt_guid,
                 dim_asmt.c.rec_status == Constants.CURRENT))
        return query
 def setUpClass(cls, datasource_name=None, metadata=None, resources_dir=None, use_metadata_from_db=True):
     if datasource_name is None:
         datasource_name = EdCoreDBConnection.get_datasource_name(get_unittest_tenant_name())
     super().setUpClass(datasource_name=datasource_name, metadata=metadata,
                        resources_dir=resources_dir, use_metadata_from_db=use_metadata_from_db)
 def test_connector_with_one_tenant(self):
     conn = EdCoreDBConnection()
     self.assertIsInstance(conn, EdCoreDBConnection)
     dim_student = conn.get_table('dim_student')
     self.assertEqual(dim_student.name, 'dim_student')
 def test_generate_metadata(self):
     metadata = EdCoreDBConnection.generate_metadata()
     self.assertIsNotNone(metadata)
 def test_get_db_config_prefix(self):
     name = EdCoreDBConnection.get_db_config_prefix('dummy')
     self.assertEqual(name, EdCoreDBConnection.CONFIG_NAMESPACE + '.dummy.')
 def test_get_datasource_name(self):
     name = EdCoreDBConnection.get_datasource_name('dummy')
     self.assertEqual(name, EdCoreDBConnection.CONFIG_NAMESPACE + '.dummy')