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)
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
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)
def get_objectives(stage: str): result = ObjectivesService.query(stage) for obj in result.items: process_objective(obj) return result
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