Example #1
0
def test_atol_report_unrecoverable_errors(status, params, set_atol_token):
    atol = AtolAPI()
    set_atol_token('12345')
    payment_uuid = str(uuid4())

    responses.add(responses.GET, ATOL_BASE_URL + '/ATOL-ProdTest-1/report/%s' % payment_uuid,
                  status=status, **params)

    with pytest.raises(AtolUnrecoverableError):
        atol.report(payment_uuid)
Example #2
0
def atol_receive_receipt_report(self, receipt_id):
    """
    Attempt to retrieve a receipt report for given receipt_id
    If received an unrecoverable error, then stop any further attempts to receive the report
    """
    atol = AtolAPI()
    Receipt = apps.get_model('atol', 'Receipt')
    receipt = Receipt.objects.get(id=receipt_id)

    if not receipt.uuid:
        logger.error('receipt %s does not have a uuid', receipt.id)
        return

    if receipt.status not in [ReceiptStatus.initiated, ReceiptStatus.retried]:
        logger.error('receipt %s has invalid status: %s', receipt.uuid,
                     receipt.status)
        return

    try:
        report = atol.report(receipt.uuid)
    except AtolUnrecoverableError as exc:
        logger.error('unable to fetch report for receipt %s due to %s',
                     receipt.id,
                     exc,
                     exc_info=True)
        receipt.declare_failed()
    except AtolReceiptNotProcessed as exc:
        logger.warning('unable to fetch report for receipt %s due to %s',
                       receipt.id,
                       exc,
                       exc_info=True)
        logger.info('repeat receipt registration: id %s; old internal_uuid %s',
                    receipt.id, receipt.internal_uuid)
        with transaction.atomic():
            receipt.internal_uuid = uuid4()
            receipt.status = ReceiptStatus.retried
            receipt.save(update_fields=['internal_uuid', 'status'])
            transaction.on_commit(lambda: atol_create_receipt.apply_async(
                args=(receipt.id, ), countdown=60))
    except Exception as exc:
        logger.warning('failed to fetch report for receipt %s due to %s',
                       receipt.id,
                       exc,
                       exc_info=True)
        try:
            countdown = 60 * int(math.exp(self.request.retries))
            logger.info(
                'retrying to receive receipt %s with countdown %s due to %s',
                receipt.id, countdown, exc)
            self.retry(countdown=countdown)
        except MaxRetriesExceededError:
            logger.error('run out of attempts to create receipt %s due to %s',
                         receipt.id, exc)
            receipt.declare_failed()
    else:
        with transaction.atomic():
            receipt.receive(content=report.data)
Example #3
0
def atol_receive_receipt_report(self, receipt_id):
    """
    Attempt to retrieve a receipt report for given receipt_id
    If received an unrecoverable error, then stop any further attempts to receive the report
    """
    atol = AtolAPI()
    Receipt = apps.get_model('atol', 'Receipt')
    receipt = Receipt.objects.get(id=receipt_id)

    if not receipt.uuid:
        logger.error('receipt %s does not have a uuid', receipt.id)
        return

    if receipt.status != ReceiptStatus.initiated:
        logger.error('receipt %s has invalid status: %s', receipt.uuid,
                     receipt.status)
        return

    try:
        report = atol.report(receipt.uuid)
    except AtolUnrecoverableError as exc:
        logger.error('unable to fetch report for receipt %s due to %s',
                     receipt.uuid,
                     exc,
                     exc_info=True)
        receipt.declare_failed()
        return
    except Exception as exc:
        logger.warning('failed to fetch report for receipt %s due to %s',
                       receipt_id,
                       exc,
                       exc_info=True)
        try:
            countdown = 60 * int(math.exp(self.request.retries))
            logger.info(
                'retrying to receive receipt %s with countdown %s due to %s',
                receipt.id, countdown, exc)
            self.retry(countdown=countdown)
        except MaxRetriesExceededError:
            logger.error('run out of attempts to create receipt %s due to %s',
                         receipt.id, exc)
            receipt.declare_failed()
    else:
        with transaction.atomic():
            receipt.receive(content=report.data)
Example #4
0
def test_atol_create_receipt_workflow():
    uid = '973f3bef-1c39-40c9-abd0-33a91ab005ca'
    # get Token
    data = {
        'code': 1,
        'text': None,
        'token': '84a50b3a6207421aba46834d650b42a0'
    }
    url = ATOL_BASE_URL + '/getToken'
    responses.add(responses.POST, url, status=200, json=data)

    # sell
    data = {
        'uuid': uid,
        'timestamp': '13.07.2017 18:32:49',
        'status': 'wait',
        'error': None
    }
    url = ATOL_BASE_URL + '/ATOL-ProdTest-1/sell'
    responses.add(responses.POST, url, status=200, json=data)

    # report error
    data = {
        'uuid': uid,
        'timestamp': '13.07.2017 18:32:49',
        'status': 'wait',
        'error': {
            'error_id': 'e710f5de-0b20-47de-8ae8-d193016c5a4e',
            'code': 34,
            'text': 'Нет информации, попробуйте позднее',
            'type': 'system'
        },
        'payload': None
    }
    url = ATOL_BASE_URL + '/ATOL-ProdTest-1/report/' + uid
    responses.add(responses.GET, url, status=200, json=data)

    # report ok
    data = {
        'uuid': uid,
        'error': None,
        'status': 'done',
        'payload': {
            'total': 199.99,
            'fns_site': 'www.nalog.ru',
            'fn_number': '9999078900003780',
            'shift_number': 114,
            'receipt_datetime': '13.07.2017 18:32:00',
            'fiscal_receipt_number': 1412,
            'fiscal_document_number': 50066,
            'ecr_registration_number': '1029384756033729',
            'fiscal_document_attribute': 2649836604
        },
        'timestamp': '13.07.2017 18:32:50',
        'group_code': 'ATOL-ProdTest-1',
        'daemon_code': 'prod-agent-1',
        'device_code': 'KSR13.11-3-1',
        'external_id': 'TRF20801_1',
        'callback_url': '',
    }
    url = ATOL_BASE_URL + '/ATOL-ProdTest-1/report/' + uid
    responses.add(responses.GET, url, status=200, json=data)

    # sell error
    data = {
        'uuid': uid,
        'timestamp': '13.07.2017 18:32:50',
        'status': 'fail',
        'error': {
            'error_id':
            '01b46c9d-f829-4ecf-b07c-7b096d0b985e',
            'code':
            33,
            'text':
            'В системе существует чек с external_id : ec0ce0c6-7a31-4f45-b94f-a1442be3bb9c '
            'и group_code: ATOL-ProdTest-1',
            'type':
            'system',
        }
    }
    url = ATOL_BASE_URL + '/ATOL-ProdTest-1/sell'
    responses.add(responses.POST, url, status=200, json=data)

    atol = AtolAPI()

    now = datetime(2017, 11, 22, 10, 47, 32)
    payment_uuid = str(uuid4())

    sell_params = dict(timestamp=now,
                       transaction_uuid=payment_uuid,
                       purchase_name=u'Стандартная подписка на 1 месяц',
                       purchase_price='199.99',
                       user_email='*****@*****.**',
                       user_phone='+75551234567')

    receipt = atol.sell(**sell_params)

    assert receipt.uuid == '973f3bef-1c39-40c9-abd0-33a91ab005ca'
    assert receipt.data['status'] == 'wait'

    # report is not ready yet
    with pytest.raises(AtolRecoverableError):
        atol.report(receipt.uuid)

    report = atol.report(receipt.uuid)
    assert report.data['group_code'] == 'ATOL-ProdTest-1'
    assert report.data['status'] == 'done'
    assert report.data['payload']['total'] == 199.99

    # another celery worker somehow requested the same payment receipt
    double_receipt = atol.sell(**sell_params)
    assert double_receipt.uuid == '973f3bef-1c39-40c9-abd0-33a91ab005ca'
    assert double_receipt.data['status'] == 'fail'