class InstrumentVoucherJdbcRepository extends JdbcRepository {

    public Pagination<InstrumentVoucher> search(InstrumentVoucherSearch domain) {
        InstrumentVoucherSearchEntity instrumentVoucherSearchEntity = new InstrumentVoucherSearchEntity();
        instrumentVoucherSearchEntity.toEntity(domain);

        String searchQuery = "select :selectfields from :tablename :condition  :orderby   ";

        Map<String, Object> paramValues = new HashMap<>();
        StringBuffer params = new StringBuffer();

        if (instrumentVoucherSearchEntity.getSortBy() != null && !instrumentVoucherSearchEntity.getSortBy().isEmpty()) {
            validateSortByOrder(instrumentVoucherSearchEntity.getSortBy());
            validateEntityFieldName(instrumentVoucherSearchEntity.getSortBy(), InstrumentVoucherEntity.class);
        }

        String orderBy = "order by id";
        if (instrumentVoucherSearchEntity.getSortBy() != null && !instrumentVoucherSearchEntity.getSortBy().isEmpty())
            orderBy = "order by " + instrumentVoucherSearchEntity.getSortBy();

        searchQuery = searchQuery.replace(":tablename", InstrumentVoucherEntity.TABLE_NAME);

        searchQuery = searchQuery.replace(":selectfields", " * ");

        // implement jdbc specfic search
        if (instrumentVoucherSearchEntity.getTenantId() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("tenantId =:tenantId");
            paramValues.put("tenantId", instrumentVoucherSearchEntity.getTenantId());
        }

        if (instrumentVoucherSearchEntity.getInstruments() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("instrumentId in (:instruments)");
            paramValues.put("instruments",
                    new ArrayList<String>(Arrays.asList(instrumentVoucherSearchEntity.getInstruments().split(","))));
        }

        if (instrumentVoucherSearchEntity.getReceiptIds() != null) {
            if (params.length() > 0)
                params.append(" and ");
            params.append("receiptHeaderId in (:receiptIds)");
            paramValues.put("receiptIds",
                    new ArrayList<String>(Arrays.asList(instrumentVoucherSearchEntity.getReceiptIds().split(","))));
        }

        Pagination<InstrumentVoucher> page = new Pagination<>();
        if (instrumentVoucherSearchEntity.getOffset() != null)
            page.setOffset(instrumentVoucherSearchEntity.getOffset());
        if (instrumentVoucherSearchEntity.getPageSize() != null)
            page.setPageSize(instrumentVoucherSearchEntity.getPageSize());

        if (params.length() > 0)
            searchQuery = searchQuery.replace(":condition", " where " + params.toString());
        else

            searchQuery = searchQuery.replace(":condition", "");

        searchQuery = searchQuery.replace(":orderby", orderBy);

        page = (Pagination<InstrumentVoucher>) getPagination(searchQuery, page, paramValues);
        searchQuery = searchQuery + " :pagination";

        searchQuery = searchQuery.replace(":pagination",
                "limit " + page.getPageSize() + " offset " + page.getOffset() * page.getPageSize());

        BeanPropertyRowMapper row = new BeanPropertyRowMapper(InstrumentVoucherEntity.class);

        List<InstrumentVoucherEntity> instrumentVoucherEntities = namedParameterJdbcTemplate.query(searchQuery.toString(),
                paramValues, row);

        page.setTotalResults(instrumentVoucherEntities.size());

        List<InstrumentVoucher> instrumentVouchers = new ArrayList<>();
        for (InstrumentVoucherEntity instrumentVoucherEntity : instrumentVoucherEntities) {
            instrumentVouchers.add(instrumentVoucherEntity.toDomain());
        }
        page.setPagedData(instrumentVouchers);

        return page;
    }

    public  InstrumentVoucherJdbcRepository(NamedParameterJdbcTemplate namedParameterJdbcTemplate);

}