def test_get():
    with pytest.raises(NotFoundException):
        ObjectivesService.get("puberty", "spirituality", 0, 1)
    with pytest.raises(NotFoundException):
        ObjectivesService.get("puberty", "spirituality", 1, 0)
    with pytest.raises(NotFoundException):
        ObjectivesService.get("puberty", "spirituality", 6, 1)
    with pytest.raises(NotFoundException):
        ObjectivesService.get("puberty", "spirituality", 1, 3)
    ObjectivesService.get("puberty", "spirituality", 1, 1)
Example #2
0
    def start_task(cls, authorizer: Authorizer, stage: str, area: str,
                   subline: str, tasks: List[str], description: str):
        from core.services.beneficiaries import BeneficiariesService
        line_, subline_ = subline.split('.')
        objective = ObjectivesService.get(stage, area, int(line_),
                                          int(subline_))

        now = datetime.now(timezone.utc)
        task = Task(created=int(now.timestamp() * 1000),
                    completed=False,
                    objective_key=join_key(stage, area, subline),
                    original_objective=objective,
                    personal_objective=description,
                    tasks=[
                        Subtask(completed=False, description=description)
                        for description in tasks
                    ])

        try:
            BeneficiariesService.update(authorizer,
                                        active_task=task.to_db_dict())
        except BeneficiariesService.exceptions(
        ).ConditionalCheckFailedException:
            return None
        return task
Example #3
0
 def _add_objectives_as_completed(cls, authorizer: Authorizer,
                                  objectives: List[ObjectiveKey]):
     # noinspection PyProtectedMember
     model = cls.get_interface()._model
     client = model.get_table().meta.client
     now = datetime.now(timezone.utc)
     now = int(now.timestamp() * 1000)
     n_chunks = math.ceil(len(objectives) / 25)
     # do batch writes in chunks of 25 to avoid errors
     for i_chunk in range(n_chunks):
         start = i_chunk * 25
         end = min((i_chunk + 1) * 25, len(objectives))
         chunk = objectives[start:end]
         request_items = {
             model.__table_name__: [{
                 'PutRequest': {
                     'Item': {
                         'completed':
                         True,
                         'created':
                         now,
                         'objective':
                         join_key(authorizer.stage, key.area,
                                  f'{key.line}.{key.subline}'),
                         'original-objective':
                         ObjectivesService.get(authorizer.stage, key.area,
                                               key.line, key.subline),
                         'personal-objective':
                         None,
                         'score':
                         0,
                         'tasks': [],
                         'user':
                         authorizer.sub
                     },
                 }
             } for key in chunk]
         }
         client.batch_write_item(RequestItems=request_items)
def test_get_stage():
    prepuberty = ObjectivesService.get_stage_objectives("prepuberty")
    puberty = ObjectivesService.get_stage_objectives("puberty")
    assert prepuberty != puberty
def test_complete_task(ddb_stubber: Stubber):
    now = int(time.time())

    get_params = {
        'Key': {
            'user': '******'
        },
        'ProjectionExpression': 'target',
        'TableName': 'beneficiaries'
    }

    get_response = {
        'Item': {
            'user': {
                'S': 'abcABC1234'
            },
            'group': {
                'S': 'district::group'
            },
            'unit-user': {
                'S': 'unit::abcABC12345'
            },
            'full-name': {
                'S': 'Name'
            },
            'nickname': {
                'S': 'Name'
            },
            'birthdate': {
                'S': '01-01-2001'
            },
            'score': {
                'M': {}
            },
            'n_tasks': {
                'M': {}
            },
            'bought_items': {
                'M': {}
            },
            'set_base_tasks': {
                'BOOL': False
            },
            'target': {
                'M': {
                    'original-objective': {
                        'S': 'Original'
                    },
                    'personal-objective': {
                        'S': 'Personal'
                    },
                    'objective': {
                        'S': 'puberty::corporality::2.1'
                    },
                    'score': {
                        'N': str(0)
                    }
                }
            }
        }
    }

    beneficiary_update_params = {
        'TableName':
        'beneficiaries',
        'Key': {
            'user': '******'
        },
        'ReturnValues':
        'UPDATED_OLD',
        'UpdateExpression':
        'SET #attr_target=:val_target ADD #attr_score.#attr_score_corporality :val_score_corporality, '
        '#attr_n_tasks.#attr_n_tasks_corporality :val_n_tasks_corporality',
        'ExpressionAttributeNames': {
            '#attr_score': 'score',
            '#attr_n_tasks': 'n_tasks',
            '#attr_n_tasks_corporality': 'corporality',
            '#attr_score_corporality': 'corporality',
            '#attr_target': 'target',
        },
        'ConditionExpression':
        Attr('target').ne(None),
        'ExpressionAttributeValues': {
            ':val_target': None,
            ':val_n_tasks_corporality': 1,
            ':val_score_corporality': 80
        }
    }
    beneficiary_update_response = {
        "Attributes": {
            'n_tasks': {
                'M': {
                    'corporality': {
                        'N': str(2)
                    }  # this is one less than its current value
                }
            },
            "target": {
                'M': {
                    'tasks': {
                        'L': [{
                            'M': {
                                'completed': {
                                    'BOOL': True
                                },
                                'description': {
                                    'S': 'Sub-task 1'
                                },
                            }
                        }, {
                            'M': {
                                'completed': {
                                    'BOOL': True
                                },
                                'description': {
                                    'S': 'Sub-task 2'
                                }
                            }
                        }]
                    },
                    'personal-objective': {
                        'S': 'A new task'
                    },
                    'created': {
                        'N': str(now)
                    },
                    'objective': {
                        'S': 'puberty::corporality::2.1'
                    },
                    'original-objective': {
                        'S': ObjectivesService.get('puberty', 'corporality', 2,
                                                   1)
                    },
                }
            }
        }
    }

    tasks_params = {
        'TableName': 'tasks',
        'ReturnValues': 'NONE',
        'Item': {
            'completed':
            True,
            'created':
            ANY,
            'objective':
            'puberty::corporality::2.1',
            'original-objective':
            ANY,
            'personal-objective':
            'A new task',
            'tasks': [{
                'completed': True,
                'description': 'Sub-task 1'
            }, {
                'completed': True,
                'description': 'Sub-task 2'
            }],
            'user':
            '******',
        }
    }

    tasks_response = {
        'Attributes': {
            'created': {
                'N': str(time.time())
            },
            'objective': {
                'S': 'puberty::corporality::2.1'
            },
            'original-objective': {
                'S': 'Original'
            },
            'personal-objective': {
                'S': 'A new task'
            },
            'tasks': {
                'L': [{
                    'M': {
                        'completed': {
                            'BOOL': True
                        },
                        'description': {
                            'S': 'Sub-task 1'
                        }
                    }
                }, {
                    'M': {
                        'completed': {
                            'BOOL': True
                        },
                        'description': {
                            'S': 'Sub-task 2'
                        }
                    }
                }]
            },
            'user': {
                'S': 'user-sub'
            },
        }
    }

    update_response = {'Attributes': {'generated_token_last': {'N': str(10)}}}

    update_params = {
        'ExpressionAttributeNames': {
            '#attr_generated_token_last': 'generated_token_last'
        },
        'ExpressionAttributeValues': {
            ':val_generated_token_last': 1
        },
        'Key': {
            'user': '******'
        },
        'ReturnValues':
        'UPDATED_NEW',
        'TableName':
        'beneficiaries',
        'UpdateExpression':
        'ADD #attr_generated_token_last :val_generated_token_last'
    }
    logs_params = {
        'TableName': 'logs',
        'ReturnValues': 'NONE',
        'Item': {
            'tag': 'STATS::COMPLETED::PUBERTY::CORPORALITY::2.1',
            'log': 'Completed an objective!',
            'data': {},
            'timestamp': 1577836800000,
            'user': '******'
        }
    }

    logs_response = {}

    ddb_stubber.add_response('get_item', get_response, get_params)
    ddb_stubber.add_response('update_item', beneficiary_update_response,
                             beneficiary_update_params)
    ddb_stubber.add_response('put_item', tasks_response, tasks_params)
    ddb_stubber.add_response('update_item', update_response, update_params)
    ddb_stubber.add_response('put_item', logs_response, logs_params)

    response = complete_active_task(
        HTTPEvent({
            "pathParameters": {
                "sub": 'user-sub'
            },
            "requestContext": {
                "authorizer": {
                    "claims": {
                        "sub": 'user-sub'
                    }
                }
            }
        }))
    assert response.status == 200
    Schema({
        'message': 'Completed task',
        'task': {
            'tasks': [
                {
                    'completed': True,
                    'description': 'Sub-task 1'
                },
                {
                    'completed': True,
                    'description': 'Sub-task 2'
                },
            ],
            'personal-objective':
            'A new task',
            'created':
            Decimal(now),
            'objective':
            'puberty::corporality::2.1',
            'original-objective':
            'Comprendo que los cambios que se estan '
            'produciendo en mi cuerpo influyen en mi manera de ser.',
            'completed':
            True,
        },
        'reward': str
    }).validate(response.body)
    reward_token = response.body['reward']
    decoded = jwt.JWT().decode(reward_token, do_verify=False)
    Schema({
        'index':
        10,
        'sub':
        'user-sub',
        'iat':
        1577836800,
        'exp':
        1577836800 + 7 * 24 * 60 * 60,
        'area':
        'corporality',
        'reason':
        'COMPLETE_OBJECTIVE',
        'static': [
            {
                'type': 'NEEDS',
                'rarity': 'RARE'
            },
            {
                'type': 'ZONE',
                'rarity': 'RARE'
            },
            {
                'type': 'POINTS',
                'rarity': 'RARE'
            },
        ],
        'boxes': [[{
            'type': 'AVATAR',
            'rarity': 'RARE'
        }, {
            'type': 'DECORATION',
            'rarity': 'COMMON'
        }],
                  [{
                      'type': 'DECORATION',
                      'rarity': 'RARE'
                  }, {
                      'type': 'AVATAR',
                      'rarity': 'COMMON'
                  }],
                  [{
                      'type': 'AVATAR',
                      'rarity': 'RARE'
                  }, {
                      'type': 'DECORATION',
                      'rarity': 'RARE'
                  }]]
    }).validate(decoded)
    ddb_stubber.assert_no_pending_responses()
def test_start_task(ddb_stubber: Stubber):
    now = datetime.now(timezone.utc)
    now = int(now.timestamp() * 1000)

    params = {
        'TableName': 'beneficiaries',
        'Key': {
            'user': '******'
        },
        'ReturnValues': 'UPDATED_NEW',
        'ConditionExpression': '#attr_target = :val_target_condition',
        'UpdateExpression': 'SET #attr_target=:val_target',
        'ExpressionAttributeNames': {
            '#attr_target': 'target'
        },
        'ExpressionAttributeValues': {
            ':val_target_condition': None,
            ':val_target': {
                'completed':
                False,
                'created':
                now,
                'objective':
                'puberty::corporality::2.3',
                'original-objective':
                ObjectivesService.get('puberty', 'corporality', 2, 3),
                'personal-objective':
                'A new task',
                'score':
                80,
                'tasks': [{
                    'completed': False,
                    'description': 'Sub-task 1',
                }, {
                    'completed': False,
                    'description': 'Sub-task 2'
                }]
            }
        }
    }
    response = {}
    ddb_stubber.add_response('update_item', response, params)
    with patch('time.time', lambda: now):
        start_task(
            HTTPEvent({
                "pathParameters": {
                    "sub": 'user-sub',
                    "stage": 'puberty',
                    "area": 'corporality',
                    "subline": "2.3"
                },
                "body":
                json.dumps({
                    "description": "A new task",
                    "sub-tasks": ["Sub-task 1", "Sub-task 2"]
                }),
                "requestContext": {
                    "authorizer": {
                        "claims": {
                            "sub": 'user-sub'
                        }
                    }
                }
            }))
    ddb_stubber.assert_no_pending_responses()
def test_get_active_task(ddb_stubber: Stubber):
    params = {
        'TableName': 'beneficiaries',
        'Key': {
            'user': '******'
        },
        'ProjectionExpression': 'target'
    }
    response = {
        'Item': {
            'target': {
                'M': {
                    'completed': {
                        'BOOL': False
                    },
                    'created': {
                        'N': str(int(time.time()))
                    },
                    'objective': {
                        'S': 'puberty::corporality::2.3'
                    },
                    'original-objective': {
                        'S': ObjectivesService.get('puberty', 'corporality', 2,
                                                   3)
                    },
                    'personal-objective': {
                        'S': 'A new task'
                    },
                    'tasks': {
                        'L': [{
                            'M': {
                                'completed': {
                                    'BOOL': False
                                },
                                'description': {
                                    'S': 'Sub-task 1'
                                },
                            }
                        }, {
                            'M': {
                                'completed': {
                                    'BOOL': False
                                },
                                'description': {
                                    'S': 'Sub-task 2'
                                }
                            }
                        }]
                    }
                }
            }
        }
    }
    ddb_stubber.add_response('get_item', response, params)

    timestamp = str(int(time.time()) * 1000 - 24 * 60 * 60 * 1000 - 1)
    ddb_stubber.add_response(
        'query', {
            'Items': [{
                'user': {
                    'S': 'u-sub'
                },
                'tag': {
                    'S':
                    'STATS::PROGRESS::PUBERTY::CORPORALITY::2.3::' +
                    str(timestamp)
                },
                'timestamp': {
                    'N': timestamp
                },
                'log': {
                    'S': 'A log!'
                },
            }]
        }, {
            'KeyConditionExpression':
            Key('user').eq('u-sub') & Key('tag').begins_with(
                'STATS::PROGRESS::PUBERTY::CORPORALITY::2.3::'),
            'Limit':
            1,
            'ScanIndexForward':
            False,
            'TableName':
            'logs'
        })
    response = get_user_active_task(
        HTTPEvent({
            "pathParameters": {
                "sub": 'u-sub',
                "stage": 'puberty',
                "area": 'sociability',
                "subline": "2.3"
            },
            "requestContext": {
                "authorizer": {
                    "claims": {
                        "sub": 'u-sub'
                    }
                }
            }
        }))
    ddb_stubber.assert_no_pending_responses()

    assert response.status == 200
    Schema({
        'area':
        'corporality',
        'stage':
        'puberty',
        'line':
        2,
        'subline':
        3,
        'completed':
        False,
        'created':
        1577836800,
        'objective':
        'puberty::corporality::2.3',
        'original-objective':
        'Trato de superar las dificultades fĂ­sicas propias de mi crecimiento.',
        'personal-objective':
        'A new task',
        'tasks': [{
            'completed': False,
            'description': 'Sub-task 1'
        }, {
            'completed': False,
            'description': 'Sub-task 2'
        }],
        'eligible_for_progress_reward':
        True,
        'score':
        80,
        'token':
        str
    }).validate(response.body)
    decoded = jwt.JWT().decode(response.body['token'], do_verify=False)
    assert Schema({
        'sub': 'u-sub',
        'iat': 1577836800,
        'exp': 1577836800 + 1 * 24 * 60 * 60,
        'objective': 'puberty::corporality::2.3'
    }).validate(decoded)
Example #8
0
def get_objectives(stage: str):
    result = ObjectivesService.query(stage)
    for obj in result.items:
        process_objective(obj)
    return result
Example #9
0
def get_objective(stage: str, area: str, line: int, sub_line: int):
    result = ObjectivesService.get(stage, area, line, sub_line)
    process_objective(result.item)
    return result