Ejemplo n.º 1
0
 def test_variaous_cases(self):
     from common.utils import nhs_titlecase
     tests = [
         (
             'THING BY THE CHURCH',
             'Thing by the Church'
         ),
         (
             'DR AS RAGHUNATH AND PTNRS',
             'Dr AS Raghunath and Ptnrs'
         ),
         (
             'OUT OF HOURS',
             'Out of Hours'
         ),
         (
             'NHS CORBY CCG',
             'NHS Corby CCG'
         ),
         (
             'CN HIV THREE BOROUGHS TEAM',
             'CN HIV Three Boroughs Team'
         ),
         (
             'DMC VICARAGE LANE',
             'DMC Vicarage Lane'
         ),
         (
             'DR CHEUNG KK PRACTICE',
             'Dr Cheung KK Practice'
         ),
         (
             'DR PM OPIE & DR AE SPALDING PRACTICE',
             'Dr PM Opie & Dr AE Spalding Practice'
         ),
         (
             'LUNDWOOD MEDICAL CENTRE PMS PRACTICE',
             'Lundwood Medical Centre PMS Practice'
         ),
         (
             "ST ANN'S MEDICAL CENTRE",
             "St Ann's Medical Centre"
         ),
         (
             "C&RH BIGGIN HILL",
             "C&RH Biggin Hill")
     ]
     for words, expected in tests:
         self.assertEquals(nhs_titlecase(words), expected)
Ejemplo n.º 2
0
def truncate_subject(prefix, subject):
    assert subject, "Subject must not be empty"
    max_length = 78 - len(prefix) - len(settings.EMAIL_SUBJECT_PREFIX)
    ellipsis = '...'
    subject = nhs_titlecase(subject)
    if len(subject) <= max_length:
        truncated = subject
    else:
        if 'by' in subject:
            end_bit = subject.split('by')[-1]
            end_bit = 'by' + end_bit
        else:
            end_bit = ''
        start_bit = subject[:(max_length - len(end_bit) - len(ellipsis))]
        truncated = start_bit + ellipsis + end_bit
    return prefix + truncated
Ejemplo n.º 3
0
def truncate_subject(prefix, subject):
    assert subject, "Subject must not be empty"
    max_length = 78 - len(prefix)
    ellipsis = "..."
    subject = nhs_titlecase(subject)
    if len(subject) <= max_length:
        truncated = subject
    else:
        if " by " in subject:
            end_bit = subject.split(" by ")[-1]
            end_bit = "by " + end_bit
        else:
            end_bit = ""
        if len(end_bit) + len(ellipsis) > max_length:
            end_bit = ""
        start_bit = subject[:(max_length - len(end_bit) - len(ellipsis))]
        truncated = start_bit + ellipsis + end_bit
    return prefix + truncated
Ejemplo n.º 4
0
 def test_various_cases(self):
     tests = [
         ("THING BY THE CHURCH", "Thing by the Church"),
         ("DR AS RAGHUNATH AND PTNRS", "Dr AS Raghunath and Ptnrs"),
         ("OUT OF HOURS", "Out of Hours"),
         ("NHS CORBY CCG", "NHS Corby CCG"),
         ("CN HIV THREE BOROUGHS TEAM", "CN HIV Three Boroughs Team"),
         ("DMC VICARAGE LANE", "DMC Vicarage Lane"),
         ("DR CHEUNG KK PRACTICE", "Dr Cheung KK Practice"),
         (
             "DR PM OPIE & DR AE SPALDING PRACTICE",
             "Dr PM Opie & Dr AE Spalding Practice",
         ),
         (
             "LUNDWOOD MEDICAL CENTRE PMS PRACTICE",
             "Lundwood Medical Centre PMS Practice",
         ),
         ("ST ANN'S MEDICAL CENTRE", "St Ann's Medical Centre"),
         ("C&RH BIGGIN HILL", "C&RH Biggin Hill"),
     ]
     for words, expected in tests:
         self.assertEqual(nhs_titlecase(words), expected)
def price_per_unit(request, format=None):
    """Returns price per unit data for presentations and practices or
    CCGs

    """
    entity_code = request.query_params.get("entity_code")
    entity_type = request.query_params.get("entity_type")
    date = request.query_params.get("date")
    bnf_code = request.query_params.get("bnf_code")
    aggregate = bool(request.query_params.get("aggregate"))
    if not date:
        raise NotValid("You must supply a date")
    if not (entity_code or bnf_code or aggregate):
        raise NotValid(
            "You must supply a value for entity_code or bnf_code, or set the "
            "aggregate flag")

    params = {"date": date}
    filename = date

    if bnf_code:
        params["bnf_code"] = bnf_code
        get_object_or_404(Presentation, pk=bnf_code)
        filename += "-%s" % bnf_code

    if entity_code:
        entity = _get_org_or_404(entity_code, entity_type)
        params["entity_code"] = entity_code
        filename += "-%s" % entity_code
        if not entity_type:
            if isinstance(entity, PCT):
                entity_type = "CCG"
            else:
                entity_type = "practice"

    extra_conditions = ""

    if bnf_code:
        extra_conditions += """
        AND {ppusavings_table}.bnf_code = %(bnf_code)s"""

    if entity_code:
        if isinstance(entity, Practice):
            extra_conditions += """
        AND {ppusavings_table}.practice_id = %(entity_code)s"""
        else:
            extra_conditions += """
        AND {ppusavings_table}.pct_id = %(entity_code)s"""

            if bnf_code:
                extra_conditions += """
        AND {ppusavings_table}.practice_id IS NOT NULL"""
            else:
                extra_conditions += """
        AND {ppusavings_table}.practice_id IS NULL"""
    else:
        if entity_type == "practice":
            extra_conditions += """
                AND {ppusavings_table}.practice_id IS NOT NULL"""
        elif entity_type == "CCG":
            extra_conditions += """
                AND {ppusavings_table}.practice_id IS NULL"""

    sql = ppu_sql(conditions=extra_conditions)

    if aggregate:
        sql = _aggregate_ppu_sql(sql, entity_type)

    with connection.cursor() as cursor:
        cursor.execute(sql, params)
        results = utils.dictfetchall(cursor)

    for result in results:
        if result["practice_name"] is not None:
            result["practice_name"] = nhs_titlecase(result["practice_name"])
        if result["pct_name"] is not None:
            result["pct_name"] = nhs_titlecase(result["pct_name"])

    response = Response(results)
    if request.accepted_renderer.format == "csv":
        filename = "%s-ppd.csv" % (filename)
        response["content-disposition"] = "attachment; filename=%s" % filename
    return response
Ejemplo n.º 6
0
def price_per_unit(request, format=None):
    """
    Returns price per unit data for presentations and practices or
    CCGs
    """
    entity_code = request.query_params.get("entity_code", "")
    entity_type = request.query_params.get("entity_type", "").lower()
    date = request.query_params.get("date")
    bnf_code = request.query_params.get("bnf_code")
    aggregate = bool(request.query_params.get("aggregate"))
    if not date:
        raise NotValid("You must supply a date")
    if not (entity_code or bnf_code or aggregate):
        raise NotValid(
            "You must supply a value for entity_code or bnf_code, or set the "
            "aggregate flag")
    if not entity_type:
        entity_type = "ccg" if len(entity_code) == 3 else "practice"

    filename = date
    if bnf_code:
        filename += "-%s" % bnf_code
    if entity_code:
        filename += "-%s" % entity_code

    # This not a particularly orthogonal API. Below we're just replicating the
    # logic of the original API which we can think about simplifying later.
    #
    # Handle the special All England case
    if aggregate:
        # If we're not looking at a specific code then we want to aggregate all
        # practices together
        if not bnf_code:
            entity_type = "all_standard_practices"
            entity_codes = [None]
        # Otherwise we want the results over all CCGs
        else:
            entity_type = "ccg"
            entity_codes = get_row_grouper(entity_type).ids
    else:
        # If we don't specify a particular org then we want all orgs of that
        # type
        if not entity_code:
            entity_codes = get_row_grouper(entity_type).ids
        else:
            # When looking at a specific BNF code for a specific CCG we
            # actually want the results over its practices
            if entity_type == "ccg" and bnf_code:
                entity_type = "practice"
                entity_codes = _get_practice_codes_for_ccg(entity_code)
            # Otherwise we should just show the specified org
            else:
                entity_codes = [entity_code]

    if bnf_code:
        results = get_savings_for_orgs(bnf_code, date, entity_type,
                                       entity_codes)
    else:
        results = get_all_savings_for_orgs(date, entity_type, entity_codes)

    # Fetch the names of all the orgs involved and prepare to reformat the
    # response to match the old API
    if entity_type == "practice":
        org_id_field = "practice"
        org_name_field = "practice_name"
        org_names = {
            code: nhs_titlecase(name)
            for (code, name) in Practice.objects.filter(
                code__in=entity_codes).values_list("code", "name")
        }
    elif entity_type == "ccg":
        org_id_field = "pct"
        org_name_field = "pct_name"
        org_names = {
            code: nhs_titlecase(name)
            for (code, name) in PCT.objects.filter(
                code__in=entity_codes).values_list("code", "name")
        }
    elif entity_type == "all_standard_practices":
        org_id_field = "pct"
        org_name_field = "pct_name"
        org_names = {None: "NHS England"}
    else:
        raise ValueError(entity_type)

    # All BNF codes which had a price concession that month
    concession_codes = set(_get_concession_bnf_codes(date))

    # Reformat response to match the old API
    for row in results:
        org_id = row.pop("org_id")
        row[org_id_field] = org_id
        row[org_name_field] = org_names[org_id]
        row["price_concession"] = row["presentation"] in concession_codes

    response = Response(results)
    if request.accepted_renderer.format == "csv":
        filename = "%s-ppd.csv" % (filename)
        response["content-disposition"] = "attachment; filename=%s" % filename
    return response
Ejemplo n.º 7
0
 def cased_name(self):
     return nhs_titlecase(self.name)
Ejemplo n.º 8
0
def price_per_unit(request, format=None):
    """Returns price per unit data for presentations and practices or
    CCGs

    """
    entity_code = request.query_params.get('entity_code')
    date = request.query_params.get('date')
    bnf_code = request.query_params.get('bnf_code')
    if not date:
        raise NotValid("You must supply a date")
    if not (entity_code or bnf_code):
        raise NotValid("You must supply a value for entity_code or bnf_code")

    params = {'date': date}
    filename = date

    practice_level = False

    if bnf_code:
        params['bnf_code'] = bnf_code
        get_object_or_404(Presentation, pk=bnf_code)
        filename += "-%s" % bnf_code

    if entity_code:
        params['entity_code'] = entity_code
        if len(entity_code) == 3:
            get_object_or_404(PCT, pk=entity_code)
        else:
            get_object_or_404(Practice, pk=entity_code)
            practice_level = True
        filename += "-%s" % entity_code

    # We cannot use the ORM here since there is no ForeignKey from PPUSaving to
    # DMDProduct.
    sql = '''
    SELECT DISTINCT ON (
            {dmdproduct_table}.bnf_code,
            {ppusavings_table}.pct_id,
            {ppusavings_table}.practice_id
        )
        {ppusavings_table}.id AS id,
        {ppusavings_table}.date AS date,
        {ppusavings_table}.lowest_decile AS lowest_decile,
        {ppusavings_table}.quantity AS quantity,
        {ppusavings_table}.price_per_unit AS price_per_unit,
        {ppusavings_table}.possible_savings AS possible_savings,
        {ppusavings_table}.formulation_swap AS formulation_swap,
        {ppusavings_table}.pct_id AS pct,
        {ppusavings_table}.practice_id AS practice,
        {ppusavings_table}.bnf_code AS presentation,
        {practice_table}.name AS practice_name,
        {dmdproduct_table}.flag_non_bioequivalence AS flag_bioequivalence,
        subquery.price_concession IS NOT NULL as price_concession,
        COALESCE({dmdproduct_table}.name, {presentation_table}.name) AS name
    FROM {ppusavings_table}
    LEFT OUTER JOIN {presentation_table}
        ON {ppusavings_table}.bnf_code = {presentation_table}.bnf_code
    LEFT OUTER JOIN {practice_table}
        ON {ppusavings_table}.practice_id = {practice_table}.code
    LEFT OUTER JOIN {dmdproduct_table}
        ON {ppusavings_table}.bnf_code = {dmdproduct_table}.bnf_code
    LEFT OUTER JOIN (SELECT DISTINCT vpid, 1 AS price_concession
                     FROM {dmdvmpp_table}
                     INNER JOIN {ncsoconcession_table}
                         ON {dmdvmpp_table}.vppid = {ncsoconcession_table}.vmpp_id
                     WHERE {ncsoconcession_table}.date = %(date)s) AS subquery
        ON {dmdproduct_table}.vpid = subquery.vpid
    WHERE
        {ppusavings_table}.date = %(date)s
        AND {dmdproduct_table}.concept_class = 1'''

    if bnf_code:
        sql += '''
        AND {ppusavings_table}.bnf_code = %(bnf_code)s'''

    if entity_code:
        if practice_level:
            sql += '''
        AND {ppusavings_table}.practice_id = %(entity_code)s'''
        else:
            sql += '''
        AND {ppusavings_table}.pct_id = %(entity_code)s'''

            if bnf_code:
                sql += '''
        AND {ppusavings_table}.practice_id IS NOT NULL'''
            else:
                sql += '''
        AND {ppusavings_table}.practice_id IS NULL'''

    sql = sql.format(
        ppusavings_table=PPUSaving._meta.db_table,
        practice_table=Practice._meta.db_table,
        presentation_table=Presentation._meta.db_table,
        dmdproduct_table=DMDProduct._meta.db_table,
        dmdvmpp_table=DMDVmpp._meta.db_table,
        ncsoconcession_table=NCSOConcession._meta.db_table,
    )

    with connection.cursor() as cursor:
        cursor.execute(sql, params)
        results = utils.dictfetchall(cursor)

    for result in results:
        if result['practice_name'] is not None:
            result['practice_name'] = nhs_titlecase(result['practice_name'])

    response = Response(results)
    if request.accepted_renderer.format == 'csv':
        filename = "%s-ppd.csv" % (filename)
        response['content-disposition'] = "attachment; filename=%s" % filename
    return response