def _write_coupon(title, description, image, qr_code_image, id_provider):
    coupon = {
        'title': title,
        'description': description,
    }
    validation_result = validate_coupon(coupon)
    if validation_result:
        return build_bad_request_response(*validation_result)
    (image_mime_type, image_body) = _extract_data_url(image)
    if image_mime_type is None or image_body is None:
        return build_bad_request_response('invalid.image')
    (qr_code_image_mime_type,
     qr_code_image_body) = _extract_data_url(qr_code_image)
    if qr_code_image_mime_type is None or qr_code_image_body is None:
        return build_bad_request_response('invalid.qr_code_image')
    image_object = s3_put_coupon_image(_make_s3_key('image'), image_body,
                                       image_mime_type)
    qr_code_image_object = s3_put_coupon_image(_make_s3_key('qr_code_image'),
                                               qr_code_image_body,
                                               qr_code_image_mime_type)
    _id = id_provider()
    dynamodb_put_coupon({
        **coupon,
        'id': _id,
        'image_s3_key': image_object.key,
        'qr_code_image_s3_key': qr_code_image_object.key,
    })
    result_coupon = dynamodb_get_coupon(_id)['Item']
    return build_ok_response(_delete_fixed_key(result_coupon))
def read_coupon(_id):
    get_coupon_result = dynamodb_get_coupon(_id)
    if 'Item' not in get_coupon_result:
        return build_not_found_response('coupon_not_found')
    coupon = get_coupon_result['Item']
    return build_ok_response({
        **_delete_fixed_key(coupon),
        **_with_s3_urls(coupon)
    })
def delete_coupon(_id):
    get_coupon_result = dynamodb_get_coupon(_id)
    if 'Item' not in get_coupon_result:
        return build_not_found_response('coupon_not_found')
    coupon = get_coupon_result['Item']
    dynamodb_delete_coupon(coupon['id'])
    s3_delete_coupon_image(coupon['image_s3_key'])
    s3_delete_coupon_image(coupon['qr_code_image_s3_key'])
    return build_ok_response(None)
def query_coupons(last_evaluated_key):
    query_coupons_result = dynamodb_query_coupons(last_evaluated_key)
    return build_ok_response(
        tuple({
            **_delete_fixed_key(coupon),
            **_with_s3_urls(coupon)
        } for coupon in query_coupons_result['Items']),
        {
            **({
                'Last-Evaluated-Key':
                json.dumps(query_coupons_result['LastEvaluatedKey'])
            } if 'LastEvaluatedKey' in query_coupons_result else {})
        },
    )
 def test_query_coupons(self, mock_s3_generate_coupon_url,
                        mock_dynamodb_query_coupons):
     mock_dynamodb_query_coupons.return_value = {
         'Items': [
             {
                 'image_s3_key': 'image_s3_key_0',
                 'qr_code_image_s3_key': 'qr_code_image_s3_key_0',
                 'fixed_key': '',
             },
             {
                 'image_s3_key': 'image_s3_key_1',
                 'qr_code_image_s3_key': 'qr_code_image_s3_key_1',
                 'fixed_key': '',
             },
         ],
         'LastEvaluatedKey': {
             'key': 'value'
         },
     }
     mock_s3_generate_coupon_url.side_effect = [
         'image_url_0', 'qr_code_image_url_0', 'image_url_1',
         'qr_code_image_url_1'
     ]
     response = query_coupons('lastKey')
     self.assertEqual(
         build_ok_response(
             (
                 {
                     'image_s3_key': 'image_s3_key_0',
                     'qr_code_image_s3_key': 'qr_code_image_s3_key_0',
                     'image_url': 'image_url_0',
                     'qr_code_image_url': 'qr_code_image_url_0',
                 },
                 {
                     'image_s3_key': 'image_s3_key_1',
                     'qr_code_image_s3_key': 'qr_code_image_s3_key_1',
                     'image_url': 'image_url_1',
                     'qr_code_image_url': 'qr_code_image_url_1',
                 },
             ),
             {'Last-Evaluated-Key': '{"key": "value"}'},
         ), response)
     mock_dynamodb_query_coupons.assert_called_once_with('lastKey')
     mock_s3_generate_coupon_url.assert_has_calls([
         mock.call('image_s3_key_0'),
         mock.call('qr_code_image_s3_key_0'),
         mock.call('image_s3_key_1'),
         mock.call('qr_code_image_s3_key_1')
     ])
 def test_update_coupon(self, mock_uuid4, mock_s3_delete_coupon_image,
                        mock_s3_put_coupon_image, mock_dynamodb_get_coupon,
                        mock_dynamodb_put_coupon):
     mock_uuid4.return_value = 'fixed_uuid'
     mock_s3_put_coupon_image.side_effect = [
         MagicMock(key='image_s3_key'),
         MagicMock(key='qr_code_image_s3_key')
     ]
     mock_dynamodb_get_coupon.return_value = {
         'Item': {
             'id': '0000001',
             'image_s3_key': 'image_s3_key',
             'qr_code_image_s3_key': 'qr_code_image_s3_key',
             'fixed_key': '',
         }
     }
     response = update_coupon('0000001', 'title', 'description',
                              'data:image/png;base64,image',
                              'data:image/png;base64,qr_code_image')
     self.assertEqual(
         build_ok_response({
             'id': '0000001',
             'image_s3_key': 'image_s3_key',
             'qr_code_image_s3_key': 'qr_code_image_s3_key',
         }), response)
     mock_s3_put_coupon_image.assert_has_calls([
         mock.call('image/fixed_uuid', 'image', 'image/png'),
         mock.call('qr_code_image/fixed_uuid', 'qr_code_image',
                   'image/png'),
     ])
     mock_dynamodb_put_coupon.assert_called_once_with({
         'id':
         '0000001',
         'title':
         'title',
         'description':
         'description',
         'image_s3_key':
         'image_s3_key',
         'qr_code_image_s3_key':
         'qr_code_image_s3_key',
     })
     mock_dynamodb_get_coupon.assert_has_calls(
         [mock.call('0000001'), mock.call('0000001')])
     mock_s3_delete_coupon_image.assert_has_calls(
         [mock.call('image_s3_key'),
          mock.call('qr_code_image_s3_key')])
 def test_delete_coupon(self, mock_s3_delete_coupon_image,
                        mock_dynamodb_get_coupon,
                        mock_dynamodb_delete_coupon):
     mock_dynamodb_get_coupon.return_value = {
         'Item': {
             'id': '0000001',
             'image_s3_key': 'image_s3_key',
             'qr_code_image_s3_key': 'qr_code_image_s3_key'
         }
     }
     response = delete_coupon('0000001')
     self.assertEqual(build_ok_response(None), response)
     mock_dynamodb_get_coupon.assert_called_once_with('0000001')
     mock_dynamodb_delete_coupon.assert_called_once_with('0000001')
     mock_s3_delete_coupon_image.assert_has_calls(
         [mock.call('image_s3_key'),
          mock.call('qr_code_image_s3_key')])
 def test_read_coupon(self, mock_s3_generate_coupon_url,
                      mock_dynamodb_get_coupon):
     mock_dynamodb_get_coupon.return_value = {
         'Item': {
             'image_s3_key': 'image_s3_key',
             'qr_code_image_s3_key': 'qr_code_image_s3_key',
             'fixed_key': ''
         }
     }
     mock_s3_generate_coupon_url.side_effect = [
         'image_url', 'qr_code_image_url'
     ]
     response = read_coupon('id')
     self.assertEqual(
         build_ok_response({
             'image_s3_key': 'image_s3_key',
             'qr_code_image_s3_key': 'qr_code_image_s3_key',
             'image_url': 'image_url',
             'qr_code_image_url': 'qr_code_image_url',
         }), response)
     mock_dynamodb_get_coupon.assert_called_once_with('id')
     mock_s3_generate_coupon_url.assert_has_calls(
         [mock.call('image_s3_key'),
          mock.call('qr_code_image_s3_key')])
 def test_query_coupons_no_last_evaluated_key(self,
                                              mock_dynamodb_query_coupons):
     mock_dynamodb_query_coupons.return_value = {'Items': []}
     response = query_coupons(None)
     self.assertEqual(build_ok_response(()), response)
     mock_dynamodb_query_coupons.assert_called_once_with(None)