コード例 #1
0
async def create_tito_registration(secrets, event, registration, square_data):
    log = logging.getLogger(__name__)

    json_result = await put_tito_generic(secrets,
                                         event,
                                         'registrations',
                                         json={'registration': registration})

    query = Fields('registration')
    find = query.find(json_result)
    if len(find) > 0:
        find = find[0]
        registration_results = find.value
        asyncio.create_task(
            write_tito_registration({
                **registration_results,
                **json_result
            }, event))
        registration_slug = registration_results['slug']
        asyncio.create_task(
            put_tito_generic(
                secrets, event,
                f"registrations/{registration_slug}/confirmations"))
        asyncio.create_task(
            update_tito_tickets(secrets, event, json_result, square_data))
    else:
        logger.log_struct({
            'msg': "no registrations found",
            **json_result
        },
                          severity='DEBUG')
    return json_result
コード例 #2
0
def get_enrollments_errors(response: dict) -> dict:
    # $.enrollments.importSummaries[*][?(@.status='ERROR')].description
    jsonpath_expr = Child(
        Where(
            Child(Child(Fields("enrollments"), Fields("importSummaries")),
                  Slice()), Cmp(Fields("status"), eq, "ERROR")),
        Fields("description"))
    matches = jsonpath_expr.find(response)
    return {str(match.full_path): match.value for match in matches}
コード例 #3
0
def get_entity_errors(response: dict) -> dict:
    # $[?(@.status='ERROR')].description
    jsonpath_expr = Child(Where(Root(), Cmp(Fields("status"), eq, "ERROR")),
                          Fields("description"))
    # We write the JSONPath expression programmatically because
    # currently jsonpath-ng does not support parsing comparison
    # expressions like ``[?(@.status='ERROR')]``
    matches = jsonpath_expr.find(response)
    return {str(match.full_path): match.value for match in matches}
コード例 #4
0
    def test_data_model_field(self) -> None:
        data_model_body = 'def get_source_ip(event):\n\treturn "source_ip"'
        data_model_mappings = [{'name': 'destination_ip', 'path': 'dst_ip'}, {'name': 'source_ip', 'method': 'get_source_ip'}]
        data_model = DataModel({'id': 'data.model.id', 'body': data_model_body, 'versionId': 'version', 'mappings': data_model_mappings})

        self.assertEqual('data.model.id', data_model.data_model_id)
        self.assertEqual(data_model_body, data_model.body)
        self.assertEqual('version', data_model.version)

        expected_path_value = Fields('dst_ip')
        self.assertEqual(expected_path_value, data_model.paths['destination_ip'])
コード例 #5
0
ファイル: openmrs_config.py プロジェクト: solleks/commcare-hq
def get_property_map(case_config):
    """
    Returns a map of case properties to OpenMRS patient properties and
    attributes, and a value source dict to deserialize them.
    """
    property_map = {}

    for person_prop, value_source_dict in case_config['person_properties'].items():
        if 'case_property' in value_source_dict:
            jsonpath = parse_jsonpath('person.' + person_prop)
            property_map[value_source_dict['case_property']] = (jsonpath, value_source_dict)

    for attr_type_uuid, value_source_dict in case_config['person_attributes'].items():
        # jsonpath-ng offers programmatic JSONPath expressions. For details on how to create JSONPath
        # expressions programmatically see the
        # `jsonpath-ng documentation <https://github.com/h2non/jsonpath-ng#programmatic-jsonpath>`__
        #
        # The `Where` JSONPath expression "*jsonpath1* `where` *jsonpath2*" returns nodes matching *jsonpath1*
        # where a child matches *jsonpath2*. `Cmp` does a comparison in *jsonpath2*. It accepts a
        # comparison operator and a value. The JSONPath expression for matching simple attribute values is::
        #
        #     (person.attributes[*] where attributeType.uuid eq attr_type_uuid).value
        #
        # This extracts the person attribute values where their attribute type UUIDs match those configured in
        # case_config['person_attributes'].
        #
        # Person attributes with Concept values have UUIDs. The following JSONPath uses Union to match both simple
        # values and Concept values.
        if 'case_property' in value_source_dict:
            jsonpath = Union(
                # Simple values: Return value if it has no children.
                # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).(value where not *)
                Child(
                    Where(
                        Child(Child(Fields('person'), Fields('attributes')), Slice()),
                        Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_type_uuid)
                    ),
                    WhereNot(Fields('value'), Fields('*'))
                ),
                # Concept values: Return value.uuid if value.uuid exists:
                # (person.attributes[*] where attributeType.uuid eq attr_type_uuid).value.uuid
                Child(
                    Where(
                        Child(Child(Fields('person'), Fields('attributes')), Slice()),
                        Cmp(Child(Fields('attributeType'), Fields('uuid')), eq, attr_type_uuid)
                    ),
                    Child(Fields('value'), Fields('uuid'))
                )
            )
            property_map[value_source_dict['case_property']] = (jsonpath, value_source_dict)

    for name_prop, value_source_dict in case_config['person_preferred_name'].items():
        if 'case_property' in value_source_dict:
            jsonpath = parse_jsonpath('person.preferredName.' + name_prop)
            property_map[value_source_dict['case_property']] = (jsonpath, value_source_dict)

    for addr_prop, value_source_dict in case_config['person_preferred_address'].items():
        if 'case_property' in value_source_dict:
            jsonpath = parse_jsonpath('person.preferredAddress.' + addr_prop)
            property_map[value_source_dict['case_property']] = (jsonpath, value_source_dict)

    for id_type_uuid, value_source_dict in case_config['patient_identifiers'].items():
        if 'case_property' in value_source_dict:
            if id_type_uuid == 'uuid':
                jsonpath = parse_jsonpath('uuid')
            else:
                # The JSONPath expression below is the equivalent of::
                #
                #     (identifiers[*] where identifierType.uuid eq id_type_uuid).identifier
                #
                # Similar to `person_attributes` above, this will extract the person identifier values where
                # their identifier type UUIDs match those configured in case_config['patient_identifiers']
                jsonpath = Child(
                    Where(
                        Child(Fields('identifiers'), Slice()),
                        Cmp(Child(Fields('identifierType'), Fields('uuid')), eq, id_type_uuid)
                    ),
                    Fields('identifier')
                )
            property_map[value_source_dict['case_property']] = (jsonpath, value_source_dict)

    return property_map
コード例 #6
0
async def sync_event(secrets, event):
    j = await read_registrations()
    st = storage.get_storage()

    tito_registrations = j[st.col0]['tito'][st.col1][event][st.col2]
    square_registrations = j[st.col0]['square'][st.col1][event][st.col2]

    # TODO: filter out test or production tito entries

    # square order_id is used as the source in tito to prevent duplicates
    query = Slice().child(Fields('source'))
    find = query.find(tito_registrations)
    tito_sources = {m.value for m in find}

    square_by_date = sorted(square_registrations,
                            key=lambda reg: isoparse(reg['closed_at']))

    order_from_square_tito_add = []
    order_from_square = []
    order_dates = {}
    releases, rel_ids = await get_tito_release_names(secrets, event)
    for order in square_by_date:
        order_id = order['order_id']
        items = []
        tito = {'discount_code': ''}

        query = parse("$..note")
        match = query.find(order)
        note = [m.value for m in match]
        cust = order.get('customer', None)
        order_date = order['closed_at']

        email = ''
        name = ''
        if cust:
            email = cust.get('email_address', '')
            name = cust.get('given_name', '') + ' ' + cust.get(
                'family_name', '')

        tito['name'] = name
        tito['email'] = email
        tito['source'] = order_id
        tito['line_items'] = []
        for line_item in order['line_items']:
            item_name = line_item['name']
            if 'variation_name' in line_item:
                item_name = item_name + " - " + line_item['variation_name']
            quantity = int(line_item['quantity'])

            tito_name = await square_ticket_tito_name(secrets, event,
                                                      item_name)
            if not tito_name:
                continue

            if 'dealer' in item_name.lower():  # two badger per dealer space
                quantity *= 2

            item = {'release_id': rel_ids[tito_name], 'quantity': quantity}
            tito['line_items'].append(item)
            for _ in range(int(quantity)):
                items.append(tito_name)
        if not tito['name']:
            tito['name'] = ' '.join(note)

        # if there are no line_items, then its not a membership sale
        if tito['line_items'] and not order_id in tito_sources:
            order_from_square_tito_add.append(tito)

        tito = tito.copy()
        tito['order_date'] = order_date
        tito['note'] = note
        order_from_square.append(tito)
        order_dates[order_id] = order_date

    square_map = square_registration_order_map(square_registrations)
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as pool:
        futures = pool.map(create_tito_registration,
                           [secrets for _ in order_from_square_tito_add],
                           [event for _ in order_from_square_tito_add],
                           order_from_square_tito_add, [
                               square_map[item['source']]
                               for item in order_from_square_tito_add
                           ])

    registration_creation_results = await asyncio.gather(*futures)
    new_tito_registrations = [
        r['registration'] for r in registration_creation_results
        if 'registration' in r
    ]

    # merge tito native and from square orders, sort by date made
    # sort tito by
    #  'completed_at': '2019-12-22T22:16:16.000-08:00',
    #  filter Source: None

    for reg in [*tito_registrations, *new_tito_registrations]:
        source = reg.get('source', None)
        if source is None:
            reg['order_date'] = reg['completed_at']
        else:
            # order originated in square
            if source in order_dates:
                reg['order_date'] = order_dates[source]
                reg['square_data'] = square_map[source]
            else:
                logger.log_struct(
                    {
                        'msg':
                        'Could find order_id in square data.  Deletion?',
                        'order_id': source
                    },
                    severity='warning')

    sorted_by_date = sorted([*tito_registrations, *new_tito_registrations],
                            key=lambda item: isoparse(item['order_date']))

    # add badge numbers
    badge_number = 2  # 1 is reserved
    tasks = []
    for registration in sorted_by_date:
        membership_count = len([
            0 for ticket in registration['tickets']
            if is_membership_ticket(ticket['release_title'])
        ])

        tasks.append(
            asyncio.create_task(
                update_tito_tickets(secrets,
                                    event,
                                    registration,
                                    registration.get('square_data', {}),
                                    badge_number=badge_number)))
        badge_number = badge_number + membership_count

    # wait for everything to complete before sync is done
    updates = await asyncio.gather(*tasks)

    logger.log_struct({
        'event': event,
        'count.square': len(square_registrations),
        'count.tito': len(tito_registrations),
        'count.tito.added': len(order_from_square_tito_add),
        'sorted': [order['name'] for order in sorted_by_date],
        'updates': updates,
        'registrations': len(sorted_by_date)
    })
    return (event, order_from_square_tito_add)
コード例 #7
0
ファイル: test_utils.py プロジェクト: unai/gymnasdicts
        ),
        (
            [("b", 2, True), ("a", 1, False), ("b", 1, True)],
            lambda x: x[2],
            [[("a", 1, False)], [("b", 2, True), ("b", 1, True)]],
        ),
    ],
)
def test_group_by(iterable, key, expected):
    assert list(group_by(iterable, key)) == expected


@pytest.mark.parametrize(
    "pointer, expected",
    [
        (Child(Fields("a"), Fields("b")), ("a", "b")),
        (Child(Root(), Fields("a")), ("a", )),
        (Child(Fields("a"), Child(Fields("b"), Fields("c"))), ("a", "b", "c")),
    ],
)
def test__pointer_to_tuple(pointer, expected):
    assert _pointer_to_tuple(pointer) == expected


@pytest.mark.parametrize(
    "text, expected",
    [
        ("$.a[:]", ("a", )),
        ("$.a[*].b", ("a", "b")),
        ("$['a'][*]", ("a", )),
        ("$['a'][*]['b']", ("a", "b")),
コード例 #8
0
async def get_membership_items(secrets, client):
    membership_item_names = {}
    locations = set()
    result = client.catalog.search_catalog_objects(
        body={
            "include_related_objects": True,
            "object_types": ["ITEM"],
            "query": {
                "prefix_query": {
                    "attribute_name": "name",
                    "attribute_prefix": "f"
                }
            },
            "limit": 100
        })

    if result.is_success():
        json_result = result.body

        dats = parse("objects[*]").find(json_result)
        for dat in dats:
            item_id = [f.value for f in Fields('id').find(dat.value)][0]
            item_name = [
                f.value for f in parse('item_data.name').find(dat.value)
            ][0]

            item_loc = [
                f.value
                for f in Fields('present_at_location_ids').find(dat.value)
            ]

            if item_loc:
                item_loc = item_loc[0]

            membership_item_names[item_id] = item_name
            locations.update(item_loc)

            vdats = parse('item_data.variations[*]').find(dat.value)

            for vdat in vdats:
                item_id = [f.value for f in Fields('id').find(vdat.value)][0]
                var_item_name = [
                    f.value
                    for f in parse('item_variation_data.name').find(vdat.value)
                ][0]

                item_loc = [
                    f.value
                    for f in Fields('present_at_location_ids').find(vdat.value)
                ]
                if item_loc:
                    item_loc = item_loc[0]

                composit_name = f"{item_name} - {var_item_name}"
                membership_item_names[item_id] = composit_name
                locations.update(item_loc)

    elif result.is_error():
        print(result.errors)

    logger.log_struct(
        {
            "membership_item_names": membership_item_names,
            "item locations": list(locations)
        },
        severity='DEBUG')
    return membership_item_names, locations