def __init__(cls, what, bases=None, dict_=None):
        super().__init__(what, bases, dict_)

        if hasattr(cls, 'public_interface'):
            # create a class with a specific set of fields
            class SpecificObjectFieldGroup(ObjectFieldGroup):
                def __init__(self, fields):
                    super().__init__(fields, cls)

            # field group for the constructor parameters
            cls.constructor_parameters = ArgsFieldGroup(cls.public_interface)
            # field group for the public properties
            cls.properties = SpecificObjectFieldGroup(cls.public_interface)
            # field group for private members
            cls.internal = cls.constructor_parameters.derive(
                prefix_name_with_underscore, SpecificObjectFieldGroup)
            # mapping from constructor params to private members
            cls.constructor_to_internal = Mapping(cls.constructor_parameters,
                                                  cls.internal)
            # mapping from public properties to private members
            cls.properties_to_internal = Mapping(cls.properties, cls.internal)

            # dynamically create properties
            for property_field, internal in cls.properties_to_internal:
                property_field.create_property_on_class(cls, internal.name)
Beispiel #2
0
def households_from_gsheet(session, extract_from_parish_list):
    household_gsheet = get_gsheet_fields(
        Household, {
            'reference no': 'id',
            'address1': 'ADDRESS1',
            'address2': 'ADDRESS2',
            'address3': 'ADDRESS3',
            'county': 'County',
            'eircode': 'EIRCODE',
            'telephone': 'landline',
        })
    household_mapping = Mapping(household_gsheet,
                                Household.constructor_parameters,
                                field_casts={
                                    'address1': strip_commas_and_spaces,
                                    'address2': strip_commas_and_spaces,
                                    'address3': strip_commas_and_spaces,
                                    'county': strip_commas_and_spaces,
                                    'eircode': strip_commas_and_spaces,
                                })
    household_rows = extract_from_parish_list(
        'households', 'A1', ('id', 'ADDRESS1', 'ADDRESS2', 'ADDRESS3',
                             'County', 'EIRCODE', 'landline'))
    households = list(
        model_instances(household_rows, household_mapping, Household))
    session.add_all(households)
Beispiel #3
0
def nominal_accounts_from_gsheet(session, extract_from_detailed_ledger):
    nominal_account_gsheet = get_gsheet_fields(
        NominalAccount, {
            'code': 'Code',
            'description': 'Description',
            'SOFA heading': 'SOFA heading',
            'category': 'Category',
            'sub category': 'Sub-category',
        })
    nominal_account_gsheet['SOFA heading'] = StringField('SOFA heading')
    nominal_account_gsheet['Category'] = StringField('Category')
    nominal_account_gsheet['Sub-category'] = StringField('Sub-category')
    field_casts = {
        'SOFA heading': conform_sofa_heading,
        'Category': conform_category,
        'Sub-category': conform_sub_category,
    }
    nominal_account_mapping = Mapping(nominal_account_gsheet,
                                      NominalAccount.constructor_parameters,
                                      field_casts=field_casts)
    nominal_accounts = extract_from_detailed_ledger(
        'RCB Nominal Accounts', 'A1',
        ('Code', 'Description', 'SOFA heading', 'Category', 'Sub-category'))
    load_class(session, nominal_accounts, nominal_account_mapping,
               NominalAccount)
    def __init__(self, item_instance_class, account_collection):
        self._item_instance_class = item_instance_class
        self._account_collection = account_collection

        csv_field_account = StringField('account')
        csv_field_date = StringField('date')
        csv_field_details = StringField('details')
        csv_field_currency = StringField('currency')
        csv_field_debit = StringField('debit')
        csv_field_credit = StringField('credit')
        csv_field_balance = StringField('balance')
        csv_field_detail_override = ComputedStringField(
            'detail_override', lambda fg, i: None)
        csv_field_designated_balance = ComputedStringField(
            'designated_balance',
            lambda fg, i: StatementItemDesignatedBalance.No)

        statement_item_csv_fields = ListFieldGroup(
            (csv_field_account, UnusedField('_unused_'), csv_field_date,
             UnusedField('_unused_'), csv_field_details, csv_field_currency,
             csv_field_debit, csv_field_credit, csv_field_balance,
             csv_field_detail_override, csv_field_designated_balance))

        field_mappings = tuple(
            zip((csv_field_account, csv_field_date, csv_field_details,
                 csv_field_currency, csv_field_debit, csv_field_credit,
                 csv_field_balance, csv_field_detail_override,
                 csv_field_designated_balance),
                item_instance_class.constructor_parameters))

        self.csv_to_constructor = Mapping(
            statement_item_csv_fields,
            item_instance_class.constructor_parameters,
            field_mappings,
            field_casts=dict(date=cast_dmy_date_from_string))
Beispiel #5
0
def funds_from_gsheet(session, extract_from_detailed_ledger):

    fund_gsheet = get_gsheet_fields(
        Fund, {
            'name': 'fund',
            'restriction': 'type',
            'is parish fund': 'parish fund',
            'is realised': 'realised',
            'account': 'bank account id'
        })
    fund_gsheet['restriction'] = StringField('restriction')
    fund_gsheet['parish fund'] = StringField('parish fund')
    fund_gsheet['realised'] = StringField('realised')
    fund_gsheet['bank account id'] = StringField('bank account id')
    field_casts = {
        'type':
        conform_fund_restriction,
        'parish fund':
        conform_yes_no,
        'realised':
        conform_yes_no,
        'bank account id':
        AccountQuery(session).instance_finder('reference_no', int)
    }
    fund_mapping = Mapping(fund_gsheet,
                           Fund.constructor_parameters,
                           field_casts=field_casts)
    funds = extract_from_detailed_ledger(
        'funds', 'A11',
        ('fund', 'type', 'parish fund', 'realised', 'bank account id'))
    load_class(session, funds, fund_mapping, Fund)
Beispiel #6
0
def _statement_items_for_gsheet(statement_items):
    gsheet_fields = _statement_item_gsheet_export_fields()
    gsheet_field_names = [field.name for field in gsheet_fields]
    gsheet_field_group = TupleFieldGroup(gsheet_fields)
    internal_to_gsheet = Mapping(StatementItem.internal, gsheet_field_group)
    statement_items_for_gsheet = (internal_to_gsheet.cast_from(statement_item)
                                  for statement_item in statement_items)
    return gsheet_field_names, statement_items_for_gsheet
Beispiel #7
0
def subjects_from_gsheet(session, extract_from_detailed_ledger):
    subject_gsheet = get_gsheet_fields(Subject, {
        'name': 'subject',
    })
    subject_mapping = Mapping(subject_gsheet, Subject.constructor_parameters)
    subjects = extract_from_detailed_ledger(
        'report lookups', 'A3',
        ('subject', 'select vestry summary', 'easter vestry summary'))
    load_class(session, subjects, subject_mapping, Subject)
Beispiel #8
0
def accounts_from_gsheet(session, extract_from_detailed_ledger):
    account_gsheet = get_gsheet_fields(Account, {'reference no': 'id'})
    account_gsheet['status'] = StringField('status')
    account_mapping = Mapping(account_gsheet,
                              Account.constructor_parameters,
                              field_casts=field_casts)
    accounts = extract_from_detailed_ledger(
        'bank accounts', 'A1',
        ('id', 'purpose', 'status', 'name', 'institution', 'sort code',
         'account no', 'BIC', 'IBAN'))
    load_class(session, accounts, account_mapping, Account)
Beispiel #9
0
def statement_item_csv(statement_items, csv_file):

    csv_fields = _statement_item_export_fields()
    csv_field_names = [field.name for field in csv_fields]
    csv_field_group = DictFieldGroup(csv_fields)

    internal_to_csv = Mapping(StatementItem.internal, csv_field_group)

    csv_writer = DictWriter(csv_file, csv_field_names, dialect=excel_tab)
    csv_writer.writeheader()

    for statement_item in statement_items:
        csv_writer.writerow(internal_to_csv.cast_from(statement_item))

    return csv_file
Beispiel #10
0
def tax_rebates_from_gsheet(session, extract_from_detailed_ledger):

    gs_field_parishioner_id = IntField('id')
    gs_field_status = StringField('status')
    gs_field_2015_rebate = StringField('2015 rebate')
    gs_field_2016_rebate = StringField('2016 rebate')
    gs_field_2017_rebate = StringField('2017 rebate')
    gs_field_2018_rebate = StringField('2018 rebate')

    tax_rebate_gsheet = ListFieldGroup(
        (
            gs_field_parishioner_id,
            UnusedField('household id'),
            UnusedField('new pps'),
            gs_field_status,
            gs_field_2015_rebate,
            gs_field_2016_rebate,
            gs_field_2017_rebate,
            gs_field_2018_rebate,
        )
    )

    field_mappings = tuple(zip(
        (
            gs_field_parishioner_id,
            gs_field_status,
            gs_field_2015_rebate,
            gs_field_2016_rebate,
            gs_field_2017_rebate,
            gs_field_2018_rebate,
        ),
        TaxRebate.constructor_parameters
    ))

    field_casts = {
        'id': PersonQuery(session).instance_finder('parishioner_reference_no', int),
    }
    tax_rebate_mapping = Mapping(tax_rebate_gsheet, TaxRebate.constructor_parameters, field_mappings, field_casts)
    tax_rebates = extract_from_detailed_ledger(
        'tax rebate responses',
        'A1',
        ('id', 'household id', 'new pps', 'status', '2015 rebate', '2016 rebate', '2017 rebate', '2018 rebate')
    )
    load_class(session, tax_rebates, tax_rebate_mapping, TaxRebate)
Beispiel #11
0
def statement_item_from_gsheet(session, extract_from_detailed_ledger):

    statement_item_gsheet = get_gsheet_fields(StatementItem, None)
    field_casts = {
        'account': AccountQuery(session).instance_finder('account_no', None),
        'date': cast_dmy_date_from_string,
        'debit': strip_commas,
        'credit': strip_commas,
        'balance': ignore_na,
        'designated balance': cast_designated_balance,
    }
    statement_item_mapping = Mapping(statement_item_gsheet,
                                     StatementItem.constructor_parameters,
                                     field_casts=field_casts)
    statement_items = extract_from_detailed_ledger(
        'bank statements', 'A1',
        ('account', 'date', 'details', 'currency', 'debit', 'credit',
         'balance', 'detail override', 'designated balance'))
    load_class(session, statement_items, statement_item_mapping, StatementItem)
Beispiel #12
0
def tax_rebate_submissions_from_gsheet(session, extract_from_tax_rebates):

    gs_field_status = StringField('status')
    gs_field_year = IntField('year')
    gs_field_cal_rebate = StringField('calculated rebate')
    gs_field_filing_date = StringField('filing date')
    gs_field_est_rebate = StringField('estimated rebate from CDS1')
    gs_field_notice_no = StringField('notice number')
    gs_field_notes = StringField('notes')

    tax_rebates_gsheet = ListFieldGroup(
        (gs_field_status, gs_field_year, UnusedField('parishoner count'),
         UnusedField('donor count'), UnusedField('donations'),
         gs_field_cal_rebate, gs_field_filing_date, gs_field_est_rebate,
         gs_field_notice_no, gs_field_notes))

    field_mappings = tuple(
        zip((gs_field_status, gs_field_year, gs_field_cal_rebate,
             gs_field_filing_date, gs_field_est_rebate, gs_field_notice_no,
             gs_field_notes), TaxRebateSubmission.constructor_parameters))

    field_casts = {
        'status':
        lambda v, _: SubmissionStatus.Posted
        if v == 'posted' else SubmissionStatus.Revoked,
        'calculated rebate':
        strip_commas,
        'filing date':
        cast_dmy_date_from_string,
        'estimated rebate from CDS1':
        strip_commas
    }
    tax_rebates_mapping = Mapping(tax_rebates_gsheet,
                                  TaxRebateSubmission.constructor_parameters,
                                  field_mappings, field_casts)
    tax_rebate_submissions = extract_from_tax_rebates(
        'records', 'B1',
        ('status', 'year', 'parishoner count', 'donor count', 'donations',
         'calculated rebate', 'filing date', 'estimated rebate from CDS1',
         'notice number', 'notes'))
    load_class(session, tax_rebate_submissions, tax_rebates_mapping,
               TaxRebateSubmission)
Beispiel #13
0
def envelopes_from_gsheet(session, extract_from_detailed_ledger):

    gs_field_year = IntField('year')
    gs_field_counterparty = IntField('counterpartyid')
    gs_field_parishioner = IntField('parishionerid')
    gs_field_envelope_number = IntField('envelope number')

    envelope_gsheet = ListFieldGroup((
        gs_field_year,
        gs_field_counterparty,
        gs_field_parishioner,
        UnusedField('household id'),
        gs_field_envelope_number,
    ))

    field_mappings = tuple(
        zip((
            gs_field_year,
            gs_field_counterparty,
            gs_field_parishioner,
            gs_field_envelope_number,
        ), Envelope.constructor_parameters))

    field_casts = {
        'counterpartyid':
        CounterpartyQuery(session).instance_finder('reference_no', int),
        'parishionerid':
        PersonQuery(session).instance_finder('parishioner_reference_no', int),
    }
    envelope_mapping = Mapping(envelope_gsheet,
                               Envelope.constructor_parameters, field_mappings,
                               field_casts)
    envelopes = extract_from_detailed_ledger(
        'FWE records', 'A1', ('year', 'counterpartyid', 'parishionerid',
                              'household id', 'envelope number'))
    load_class(session, envelopes, envelope_mapping, Envelope)
Beispiel #14
0
def counterparty_from_gsheet(session, extract_from_detailed_ledger):

    gs_field_id = IntField('id')
    gs_field_bank_text = StringField('bank text')
    gs_field_person = IntField('parishoner id')
    gs_field_organisation = IntField('household id')
    gs_field_name_override = StringField('name override')
    gs_field_method = StringField('method')
    gs_field_so_card = StringField('SO card?')
    gs_field_by_email = StringField('by email')
    gs_field_notes = StringField('notes')

    counterparty_gsheet = ListFieldGroup((
        gs_field_id,
        gs_field_bank_text,
        gs_field_person,
        gs_field_organisation,
        UnusedField('main contact'),
        UnusedField('.'),
        gs_field_name_override,
        UnusedField('name'),
        UnusedField('_'),
        UnusedField('reverse lookup parishoner id'),
        UnusedField('reverse lookup cp id'),
        UnusedField('__'),
        UnusedField('___'),
        UnusedField('____'),
        UnusedField('_____'),
        UnusedField('______'),
        gs_field_method,
        gs_field_so_card,
        gs_field_by_email,
        gs_field_notes,
    ))

    field_mappings = tuple(
        zip((
            gs_field_id,
            gs_field_bank_text,
            gs_field_person,
            gs_field_organisation,
            gs_field_name_override,
            gs_field_method,
            gs_field_so_card,
            gs_field_by_email,
            gs_field_notes,
        ), Counterparty.constructor_parameters))

    field_casts = {
        'parishoner id':
        PersonQuery(session).instance_finder('parishioner_reference_no', int),
        'household id':
        OrganisationQuery(session).instance_finder('reference_no', int),
        'SO card?':
        cast_yes_no,
        'by email':
        cast_yes_no,
    }

    counterparty_mapping = Mapping(counterparty_gsheet,
                                   Counterparty.constructor_parameters,
                                   field_mappings, field_casts)
    counterparties = extract_from_detailed_ledger(
        'counterparties', 'A1',
        ('id', 'bank text', 'parishoner id', 'household id', 'main contact',
         '.', 'name override', 'name', '_', 'reverse lookup parishoner id',
         'reverse lookup cp id', '__', '___', '____', '_____', '______',
         'method', 'SO card?', 'by email', 'notes'))
    load_class(session, counterparties, counterparty_mapping, Counterparty)
Beispiel #15
0
def parishioners_from_gsheet(session, extract_from_parish_list):

    gs_field_id = IntField('id')
    gs_field_surname = StringField('SURNAME')
    gs_field_first_name = StringField('FIRST_NAME')
    gs_field_title = StringField('TITLE')
    gs_field_status = StringField('STATUS')
    gs_field_main_contact = StringField('main_contact')
    gs_field_household_ref_no = IntField('household_id')
    gs_field_mobile = StringField('mobile')
    gs_field_other_personal = StringField('other personal')
    gs_field_email = StringField('email')
    gs_field_gdpr_response = StringField('gdpr response?')
    gs_field_by_email = StringField('email?')
    gs_field_by_phone = StringField('phone?')
    gs_field_by_post = StringField('post?')
    gs_field_news = StringField('news?')
    gs_field_finance = StringField('finance?')

    parishioner_gsheet = ListFieldGroup((
        gs_field_id,
        gs_field_surname,
        gs_field_first_name,
        gs_field_title,
        gs_field_status,
        gs_field_main_contact,
        gs_field_household_ref_no,
        UnusedField('ADDRESS1'),
        UnusedField('ADDRESS2'),
        UnusedField('ADDRESS3'),
        UnusedField('County'),
        UnusedField('EIRCODE'),
        UnusedField('TELEPHONE'),
        gs_field_mobile,
        gs_field_other_personal,
        gs_field_email,
        gs_field_gdpr_response,
        gs_field_by_email,
        gs_field_by_phone,
        gs_field_by_post,
        gs_field_news,
        gs_field_finance,
    ))

    field_mappings = tuple(
        zip((
            gs_field_id,
            gs_field_surname,
            gs_field_first_name,
            gs_field_title,
            gs_field_status,
            gs_field_main_contact,
            gs_field_household_ref_no,
            gs_field_mobile,
            gs_field_other_personal,
            gs_field_email,
            gs_field_gdpr_response,
            gs_field_by_email,
            gs_field_by_phone,
            gs_field_by_post,
            gs_field_news,
            gs_field_finance,
        ), Parishioner.constructor_parameters))

    parishioner_mapping = Mapping(parishioner_gsheet,
                                  Parishioner.constructor_parameters,
                                  field_mappings)
    parishioner_rows = extract_from_parish_list(
        'parishioners', 'A1',
        ('id', 'SURNAME', 'FIRST_NAME', 'TITLE', 'STATUS', 'main contact?',
         'household id', 'ADDRESS1', 'ADDRESS2', 'ADDRESS3', 'County',
         'EIRCODE', 'landline', 'mobile', 'other personal', 'email',
         'gdpr response?', 'email?', 'phone?', 'post?', 'news?', 'finance?'))
    parishioners = list(
        model_instances(parishioner_rows, parishioner_mapping, Parishioner))
    session.add_all(parishioners)
Beispiel #16
0
def transactions_from_gsheet(session, extract_from_detailed_ledger):

    gs_field_reference_no = StringField('id')
    gs_field_public_code = StringField('reference')
    gs_field_year = StringField('year')
    gs_field_month = StringField('month')
    gs_field_day = StringField('day')
    gs_field_counterparty = StringField('counterparty_id')
    gs_field_payment_method = StringField('payment_method')
    gs_field_description = StringField('description')
    gs_field_amount = StringField('amount')
    gs_field_subject = StringField('subject')
    gs_field_income_expenditure = StringField('income_expenditure')
    gs_field_FY = StringField('FY')
    gs_field_fund = StringField('fund')
    gs_field_comments = StringField('comments')

    transaction_gsheet = ListFieldGroup((
        gs_field_reference_no,
        gs_field_fund,
        gs_field_public_code,
        UnusedField('bank account'),
        UnusedField('compositeId'),
        gs_field_year,
        gs_field_month,
        gs_field_day,
        gs_field_counterparty,
        UnusedField('counterparty name'),
        UnusedField('household_id'),
        gs_field_payment_method,
        gs_field_description,
        gs_field_amount,
        gs_field_subject,
        gs_field_income_expenditure,
        gs_field_FY,
        UnusedField('sign'),
        UnusedField('net'),
        UnusedField('from bank statement'),
        UnusedField('reconciles'),
        UnusedField('bank stmt year'),
        UnusedField('year reconciles?'),
        UnusedField('monthText'),
        UnusedField('quarter'),
        UnusedField('subjectSummary'),
        UnusedField('fund type'),
        gs_field_comments,
    ))
    field_casts = {
        'counterparty_id':
        CounterpartyQuery(session).instance_finder('reference_no', int),
        'payment_method':
        cast_payment_method,
        'amount':
        strip_commas,
        'subject':
        SubjectQuery(session).instance_finder('name', None),
        'income_expenditure':
        cast_income_expenditure,
        'fund':
        FundQuery(session).instance_finder('name', None),
    }
    field_mappings = tuple(
        zip((
            gs_field_reference_no,
            gs_field_public_code,
            gs_field_year,
            gs_field_month,
            gs_field_day,
            gs_field_counterparty,
            gs_field_payment_method,
            gs_field_description,
            gs_field_amount,
            gs_field_subject,
            gs_field_income_expenditure,
            gs_field_FY,
            gs_field_fund,
            gs_field_comments,
        ), Transaction.constructor_parameters))
    transaction_mapping = Mapping(transaction_gsheet,
                                  Transaction.constructor_parameters,
                                  field_mappings, field_casts)
    transactions = extract_from_detailed_ledger(
        'transactions', 'A1',
        ('id', 'fund', 'reference', 'bank account', 'compositeId', 'year',
         'month', 'day', 'counterparty_id', 'counterparty_name',
         'household_id', 'payment_method', 'description', 'amount', 'subject',
         'income/expenditure', 'FY', 'sign', 'net', 'from bank statement',
         'reconciles', 'bank stmt year', 'year reconciles?', 'monthText',
         'quarter', 'subjectSummary', 'fund type', 'comments'))
    load_class(session, transactions, transaction_mapping, Transaction)
Beispiel #17
0
}


def conform_value(value, _):
    return ACCOUNT_STATUS_MAP.get(value.lower(), AccountStatus.Active)


field_casts = dict(status=conform_value)

account_csv_fields = Account.constructor_parameters.derive(
    replace_underscore_with_space, DictFieldGroup)
account_csv_fields['reference no'].name = 'id'
account_csv_fields['status'] = StringField('status')

csv_to_constructor = Mapping(account_csv_fields,
                             Account.constructor_parameters,
                             field_casts=field_casts)


def accounts_from_csv(account_csv):
    items = []
    for row in DictReader(account_csv):
        account_args = csv_to_constructor.cast_from(row)
        items.append(Account(**account_args))

    collection = AccountCollection(items)
    return collection


def accounts_from_gsheet(session, extract_from_detailed_ledger):
    account_gsheet = get_gsheet_fields(Account, {'reference no': 'id'})
Beispiel #18
0
def node_connection_field(model_class, query_class, node_class, description):
    """ Make a ConnectionField for a model class

    :param query_class: query class for model
    :param node_class: ObjectType
    :param description: string describing the collection
    :return: ConnectionField
    """
    entity_name = node_class.__name__

    class NodeConnection(object):
        @with_session
        def resolve_total_count(self, args, context, info, session):
            return len(query_class(session))

        @with_session
        def resolve_filtered_count(self, args, context, info, session):
            return context['count']

        @with_session
        def resolve_page_info(self, args, context, info, session):
            return context['pageInfo']

    connection_class = type(
        '{}Connection'.format(entity_name),
        # inherit class methods from NodeConnection and other behaviour from
        # graphene.relay.Connection
        (NodeConnection, Connection),
        # equivalent to
        # total_count = graphene.Int()
        # filtered_count = graphene.Int()
        # class Meta:
        #     node = node_class
        {
            'total_count': graphene.Int(),
            'filtered_count': graphene.Int(),
            'Meta': type('Meta', (object, ), {
                'node': node_class,
            })
        })

    untyped_filter_field_group = model_class.properties.derive(
        field_group_class=PartialDictFieldGroup)
    typed_filter_field_group = model_class.internal.derive(
        field_group_class=PartialDictFieldGroup)
    filter_casts = _filter_casts(model_class, typed_filter_field_group)
    filter_to_internal = Mapping(untyped_filter_field_group,
                                 typed_filter_field_group,
                                 field_casts=filter_casts)

    camel_case_field_group = model_class.properties.derive(
        snake_to_camel_case, PartialDictFieldGroup)
    order_by_field_group = model_class.internal.derive(make_boolean,
                                                       PartialDictFieldGroup)
    order_by_to_mapped = Mapping(camel_case_field_group, order_by_field_group)

    @with_session
    def resolver(self, args, context, info, session):
        query = query_class(session)

        filters = args.get('filters')
        if filters:
            typed = filter_to_internal.cast_from(filters)
            criteria = tuple(query.criteria_from_dict(typed))
            query.filter(*criteria)

        filtered_count = len(query)

        order_by = args.get('orderBy')
        if order_by:
            order_by_values = OrderedDict(_parse_order_by(order_by))
            mapped = order_by_to_mapped.cast_from(order_by_values)
            # TODO only add this sort by id if there is no other sort by a unique field
            # required in order have stable sorting and paging when sorting by a non-unique field
            mapped['_id'] = True
            criteria = tuple(query.sort_criteria_from_dict(mapped))
            query.order_by(*criteria)

        offset = 0
        after = args.get('after')
        if after:
            offset = int(Node.from_global_id(after)[1])
            query.offset(offset)
            offset += 1
            args.pop('after')

        first = args.get('first')
        if first:
            limit = int(first)
            query.limit(limit)

        instances = list(query.collection())

        context['count'] = filtered_count
        context['pageInfo'] = PageInfo(
            start_cursor=offset_to_cursor(query.start_index),
            end_cursor=offset_to_cursor(query.end_index),
            has_previous_page=False
            if query.start_index is None else query.start_index > 0,
            has_next_page=False if query.end_index is None else
            query.end_index < filtered_count - 1)
        return instances

    # equivalent to
    # class SomeFilterInput(graphene.InputObjectType):
    #   refNo = graphene.Argument(graphene.Int)
    #   ...
    filter_input = type('{}FilterInput'.format(entity_name),
                        (graphene.InputObjectType, ),
                        get_filter_fields(model_class))

    connection_field = ConnectionField(
        connection_class,
        resolver=resolver,
        description=description,
        filters=graphene.Argument(filter_input),
        orderBy=graphene.Argument(graphene.String),
    )

    return connection_field