Beispiel #1
0
def test_fail_duplicate(app, tender, plan):
    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {"data": {"id": plan["data"]["id"]}},
    )
    assert response.status == "200 OK"

    # the same
    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {"data": {"id": plan["data"]["id"]}},
        status=422
    )
    assert response.json == {'status': 'error', 'errors': [
        {'description': "Can't update plan in 'complete' status", 'location': 'body', 'name': 'status'}]}

    # what if plan hasn't been updated for an unknown reason
    plan_obj = app.app.registry.databases.plans.get(plan["data"]["id"])
    del plan_obj["tender_id"]
    plan_obj["status"] = "scheduled"
    app.app.registry.databases.plans.save(plan_obj)

    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {"data": {"id": plan["data"]["id"]}},
        status=422
    )
    assert response.json == {'status': 'error', 'errors': [
        {'description': ['The list should not contain duplicates'], 'location': 'body', 'name': 'plans'}]}
Beispiel #2
0
def test_post_tender_plan_success(app, tender, plan):
    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"],
                                                tender["access"]["token"]),
        {"data": {
            "id": plan["data"]["id"]
        }},
    )
    assert response.json["data"] == [{'id': plan["data"]["id"]}]

    response = app.get("/tenders/{}".format(tender["data"]["id"]))
    assert response.json["data"]["dateModified"] > tender["data"][
        "dateModified"]

    response = app.get("/plans/{}".format(plan["data"]["id"]))
    assert response.json["data"]["tender_id"] == tender["data"]["id"]
    assert response.json["data"]["dateModified"] > plan["data"]["dateModified"]

    # second plan
    response = app.post_json("/plans", {"data": deepcopy(test_plan_data)})
    another_plan = response.json

    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"],
                                                tender["access"]["token"]),
        {"data": {
            "id": another_plan["data"]["id"]
        }},
    )
    assert response.json["data"] == [{
        'id': plan["data"]["id"]
    }, {
        'id': another_plan["data"]["id"]
    }]
Beispiel #3
0
def test_fail_non_central(app, plan):
    app.authorization = ("Basic", ("broker", "broker"))

    test_data = deepcopy(test_tender_data)
    test_data["procuringEntity"]["kind"] = "general"
    response = app.post_json("/tenders", dict(data=test_data))
    assert response.status == "201 Created"
    tender = response.json

    response = app.post_json("/tenders/{}/plans?acc_token={}".format(
        tender["data"]["id"], tender["access"]["token"]),
                             {"data": {
                                 "id": plan["data"]["id"]
                             }},
                             status=403)
    assert response.json == {
        "status":
        "error",
        "errors": [{
            "location":
            "body",
            "name":
            "data",
            "description":
            "Only allowed for procurementEntity.kind = 'central'"
        }]
    }
Beispiel #4
0
def test_fail_not_draft(app, plan):
    app.authorization = ("Basic", ("broker", "broker"))

    test_data = deepcopy(test_tender_data)
    del test_data["status"]
    response = app.post_json("/tenders", dict(data=test_data))
    assert response.status == "201 Created"
    tender = response.json

    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {"data": {"id": plan["data"]["id"]}},
        status=403
    )
    assert response.json == {"status": "error", "errors": [
        {"location": "body", "name": "data", "description": "Only allowed in draft tender status"}]}
Beispiel #5
0
def test_fail_saving_plan(app, tender, plan):
    plan_obj = app.app.registry.db.get(plan["data"]["id"])
    plan_obj["status"] = "will cause a data validation error"
    app.app.registry.db.save(plan_obj)

    # got an error
    response = app.post_json("/tenders/{}/plans?acc_token={}".format(
        tender["data"]["id"], tender["access"]["token"]),
                             {"data": {
                                 "id": plan["data"]["id"]
                             }},
                             status=422)
    assert response.json == {
        "status":
        "error",
        "errors": [{
            "location":
            "body",
            "name":
            "status",
            "description": [
                "Value must be one of ['draft', 'scheduled', 'cancelled', 'complete']."
            ]
        }]
    }

    # check that the tender hasn't been changed
    tender_obj = app.app.registry.db.get(tender["data"]["id"])
    assert tender_obj.get("plans") is None
def test_post_cancellation(app, tender_data):
    """
    posting an active cancellation should trigger the validation
    """
    tender, tender_token = post_tender(app, tender_data)

    def mock_validate(request, cancellation=None):
        raise_operation_error(request, "hello")

    if get_now() < RELEASE_2020_04_19:
        with mock.patch(
                "openprocurement.tender.core.utils.validate_absence_of_pending_accepted_satisfied_complaints",
                mock_validate):
            cancellation = dict(**test_cancellation)
            cancellation.update({"status": "active"})
            response = app.post_json(
                "/tenders/{}/cancellations?acc_token={}".format(
                    tender["id"], tender_token), {"data": cancellation},
                status=403)
            assert response.json == {
                u'status':
                u'error',
                u'errors': [{
                    u'description': u'hello',
                    u'location': u'body',
                    u'name': u'data'
                }]
            }
Beispiel #7
0
def test_post_cancellation(app, tender_data):
    """
    posting an active cancellation should trigger the validation
    """
    tender, tender_token = post_tender(app, tender_data)

    def mock_validate(request):
        raise_operation_error(request, "hello")

    with mock.patch(
            "openprocurement.tender.core.views.cancellation.validate_absence_of_pending_accepted_satisfied_complaints",
            mock_validate):
        response = app.post_json(
            "/tenders/{}/cancellations?acc_token={}".format(
                tender["id"], tender_token),
            {"data": {
                "reason": "cancellation reason",
                "status": "active",
            }},
            status=403)
        assert response.json == {
            u'status':
            u'error',
            u'errors': [{
                u'description': u'hello',
                u'location': u'body',
                u'name': u'data'
            }]
        }
Beispiel #8
0
def test_post_tender_plan_data_empty(app, tender):
    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {"data": {}},
        status=422
    )
    assert response.json == {'status': 'error', 'errors': [
        {'description': ['This field is required.'], 'location': 'body', 'name': 'id'}]}
Beispiel #9
0
def test_post_tender_plan_empty(app, tender):
    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {},
        status=422
    )
    assert response.json == {"status": "error", "errors": [
        {"location": "body", "name": "data", "description": "Data not available"}]}
Beispiel #10
0
def test_post_tender_plan_404(app, tender):
    response = app.post_json(
        "/tenders/{}/plans?acc_token={}".format(tender["data"]["id"], tender["access"]["token"]),
        {"data": {"id": tender["data"]["id"]}},
        status=404
    )
    assert response.json == {'status': 'error', 'errors': [
        {'description': 'Not Found', 'location': 'url', 'name': 'plan_id'}]}
Beispiel #11
0
def post_tender(app, data):
    if data["procurementMethodType"] in (STAGE_2_EU_TYPE, STAGE_2_UA_TYPE):
        app.authorization = ("Basic", ("competitive_dialogue", ""))
    else:
        app.authorization = ("Basic", ("broker", "broker"))
    test_data = deepcopy(data)
    response = app.post_json("/tenders", dict(data=test_data))
    assert response.status == "201 Created"
    return response.json["data"], response.json["access"]["token"]
Beispiel #12
0
def test_complaint_value_with_lots(app):
    """
    Value should be based on a lot value if lots are present
    """
    test_data = deepcopy(test_tender_data)
    test_data["lots"] = deepcopy(test_lots)
    test_data["lots"].append(deepcopy(test_lots[0]))
    test_data["lots"][0]["value"]["amount"] = 500
    test_data["lots"][1]["value"]["amount"] = 99999999999999
    tender = create_tender(app, test_data)

    req_data = deepcopy(complaint_data)
    # a chip complaint
    req_data["relatedLot"] = tender["data"]["lots"][0]["id"]

    with patch("openprocurement.tender.core.models.RELEASE_2020_04_19",
               get_now() - timedelta(days=1)):
        response = app.post_json(
            "/tenders/{}/complaints".format(tender["data"]["id"]),
            {"data": req_data},
        )

    response_data = response.json["data"]
    assert "value" in response_data
    assert response_data["value"] == {
        "currency": "UAH",
        "amount": COMPLAINT_MIN_AMOUNT
    }

    # an expensive one
    req_data["relatedLot"] = tender["data"]["lots"][1]["id"]
    with patch("openprocurement.tender.core.models.RELEASE_2020_04_19",
               get_now() - timedelta(days=1)):
        response = app.post_json(
            "/tenders/{}/complaints".format(tender["data"]["id"]),
            {"data": req_data},
        )
    response_data = response.json["data"]
    assert "value" in response_data
    assert response_data["value"] == {
        "currency": "UAH",
        "amount": COMPLAINT_MAX_AMOUNT
    }
def test_patch_cancellation(app, tender_data):
    """
    only patching to active should trigger the validation
    """
    tender, tender_token = post_tender(app, tender_data)

    def mock_validate(request, cancellation=None):
        raise_operation_error(request, "hello")

    def patch(data):
        return "openprocurement.tender.core.utils.validate_absence_of_pending_accepted_satisfied_complaints"

    with mock.patch(patch(tender_data), mock_validate):
        if get_now() < RELEASE_2020_04_19:
            response = app.post_json(
                "/tenders/{}/cancellations?acc_token={}".format(
                    tender["id"], tender_token),
                {"data": test_cancellation},
            )
            assert response.status_code == 201
            cancellation = response.json["data"]

            response = app.patch_json(
                "/tenders/{}/cancellations/{}?acc_token={}".format(
                    tender["id"], cancellation["id"], tender_token),
                {"data": {
                    "reason": "another reason",
                }},
            )
            assert response.status_code == 200

            response = app.patch_json(
                "/tenders/{}/cancellations/{}?acc_token={}".format(
                    tender["id"], cancellation["id"],
                    tender_token), {"data": {
                        "status": "active",
                    }},
                status=403)
            assert response.json == {
                u'status':
                u'error',
                u'errors': [{
                    u'description': u'hello',
                    u'location': u'body',
                    u'name': u'data'
                }]
            }
Beispiel #14
0
def post_tender(app, data):
    if data["procurementMethodType"] == "aboveThresholdUA.defense":
        release_simpledef_date = get_now() + timedelta(days=1)
    else:
        release_simpledef_date = get_now() - timedelta(days=1)
    release_simpledef_patcher = mock.patch(
        "openprocurement.tender.core.validation.RELEASE_SIMPLE_DEFENSE_FROM",
        release_simpledef_date)

    release_simpledef_patcher.start()
    if data["procurementMethodType"] in (STAGE_2_EU_TYPE, STAGE_2_UA_TYPE):
        app.authorization = ("Basic", ("competitive_dialogue", ""))
    else:
        app.authorization = ("Basic", ("broker", "broker"))
    test_data = deepcopy(data)
    response = app.post_json("/tenders", dict(data=test_data))
    release_simpledef_patcher.stop()
    assert response.status == "201 Created"
    return response.json["data"], response.json["access"]["token"]
Beispiel #15
0
def test_patch_cancellation(app, tender_data):
    """
    only patching to active should trigger the validation
    """
    tender, tender_token = post_tender(app, tender_data)

    def mock_validate(request):
        raise_operation_error(request, "hello")

    def patch(data):
        excl_procedures = ["belowThreshold", "reporting", "closeFrameworkAgreementSelectionUA"]
        if data["procurementMethodType"] not in excl_procedures:
            return "openprocurement.tender.core.views.cancellation.validate_absence_of_pending_accepted_satisfied_complaints"
        else:
            return "openprocurement.tender.belowthreshold.views.cancellation.validate_absence_of_pending_accepted_satisfied_complaints"

    with mock.patch(patch(tender_data), mock_validate):
        if get_now() < RELEASE_2020_04_19:
            response = app.post_json(
                "/tenders/{}/cancellations?acc_token={}".format(tender["id"], tender_token),
                {"data": test_cancellation},
            )
            assert response.status_code == 201
            cancellation = response.json["data"]

            response = app.patch_json(
                "/tenders/{}/cancellations/{}?acc_token={}".format(tender["id"], cancellation["id"], tender_token),
                {"data": {
                    "reason": "another reason",
                }},
            )
            assert response.status_code == 200

            response = app.patch_json(
                "/tenders/{}/cancellations/{}?acc_token={}".format(tender["id"], cancellation["id"], tender_token),
                {"data": {
                    "status": "active",
                }},
                status=403
            )
            assert response.json == {u'status': u'error', u'errors': [
                {u'description': u'hello', u'location': u'body', u'name': u'data'}]}
Beispiel #16
0
def test_complaint_value_change(app):
    """
    value should be calculated only once for a complaint
    """
    test_tender_data["value"]["amount"] = 1000  # we want minimum complaint value
    tender = create_tender(app, test_tender_data)
    with patch("openprocurement.tender.core.models.RELEASE_2020_04_19", get_now() - timedelta(days=1)):
        response = app.post_json(
            "/tenders/{}/complaints".format(tender["data"]["id"]),
            {"data": complaint_data},
        )
    response_data = response.json["data"]
    assert "value" in response_data
    expected_value = {"currency": "UAH", "amount": COMPLAINT_MIN_AMOUNT}
    assert response_data["value"] == expected_value

    # if we deploy new constant values the value shouldn't change
    with patch("openprocurement.tender.core.models.COMPLAINT_MIN_AMOUNT", 40):
        response = app.get("/tenders/{}".format(tender["data"]["id"]))
        complaint = response.json["data"].get("complaints")[0]
        assert complaint["value"] == expected_value
Beispiel #17
0
def plan(app):
    app.authorization = ("Basic", ("broker", "broker"))
    response = app.post_json("/plans", {"data": deepcopy(test_plan_data)})
    return response.json
def test_post_cancellation_openeu(app):
    """
    test without mocking (just in case)
    """
    tender, tender_token = post_tender(app, eu_tender_data)
    tender_data = app.app.registry.db.get(tender["id"])

    # award complaint
    complaint = deepcopy(test_complaint)
    complaint.update(
        resolutionType="resolved",
        cancellationReason="whatever",
    )
    tender_data["awards"] = [{
        "id": "0" * 32,
        "bid_id": "0" * 32,
        "suppliers": [test_organization],
        "complaints": [complaint]
    }]
    app.app.registry.db.save(tender_data)

    cancellation = dict(**test_cancellation)
    cancellation.update({"status": "active"})
    if get_now() < RELEASE_2020_04_19:
        with mock.patch(
                "openprocurement.tender.core.validation.RELEASE_2020_04_19",
                get_now() - timedelta(1)):
            response = app.post_json(
                "/tenders/{}/cancellations?acc_token={}".format(
                    tender["id"], tender_token), {"data": cancellation},
                status=403)
        assert response.json == {
            u'status':
            u'error',
            u'errors': [{
                u'description':
                u"Can't perform operation for there is an award complaint in pending status",
                u'location': u'body',
                u'name': u'data'
            }]
        }

        # qualification complaints
        complaint = deepcopy(test_complaint)
        complaint.update(
            status="accepted",
            resolutionType="resolved",
            cancellationReason="whatever",
        )
        tender_data["qualifications"] = [{
            "id": "0" * 32,
            "complaints": [complaint]
        }]
        app.app.registry.db.save(tender_data)

        cancellation = dict(**test_cancellation)
        cancellation.update({"status": "active"})
        with mock.patch(
                "openprocurement.tender.core.validation.RELEASE_2020_04_19",
                get_now() - timedelta(1)):
            response = app.post_json(
                "/tenders/{}/cancellations?acc_token={}".format(
                    tender["id"], tender_token), {"data": cancellation},
                status=403)
        assert response.json == {
            u'status':
            u'error',
            u'errors': [{
                u'description':
                u"Can't perform operation for there is a qualification complaint in accepted status",
                u'location': u'body',
                u'name': u'data'
            }]
        }

        # tender complaint
        complaint = deepcopy(test_complaint)
        complaint.update(
            status="satisfied",
            resolutionType="resolved",
            cancellationReason="whatever",
        )
        tender_data["complaints"] = [complaint]
        app.app.registry.db.save(tender_data)

        cancellation = dict(**test_cancellation)
        cancellation.update({"status": "active"})
        with mock.patch(
                "openprocurement.tender.core.validation.RELEASE_2020_04_19",
                get_now() - timedelta(1)):
            response = app.post_json(
                "/tenders/{}/cancellations?acc_token={}".format(
                    tender["id"], tender_token), {"data": cancellation},
                status=403)
        assert response.json == {
            u'status':
            u'error',
            u'errors': [{
                u'description':
                u"Can't perform operation for there is a tender complaint in satisfied status",
                u'location': u'body',
                u'name': u'data'
            }]
        }
Beispiel #19
0
def test_post_cancellation_openeu(app):
    """
    test without mocking (just in case)
    """
    tender, tender_token = post_tender(app, eu_tender_data)
    tender_data = app.app.registry.db.get(tender["id"])

    # award complaint
    tender_data["awards"] = [{
        "id":
        "0" * 32,
        "bid_id":
        "0" * 32,
        "suppliers": [test_organization],
        "complaints": [{
            "status": "pending",
            "title": "complaint title",
            "description": "complaint description",
            "author": test_author,
            "resolutionType": "resolved",
            "cancellationReason": "whatever",
        }]
    }]
    app.app.registry.db.save(tender_data)

    with mock.patch(
            "openprocurement.tender.core.validation.RELEASE_2020_04_19",
            get_now() - timedelta(1)):
        response = app.post_json(
            "/tenders/{}/cancellations?acc_token={}".format(
                tender["id"], tender_token),
            {"data": {
                "reason": "cancellation reason",
                "status": "active",
            }},
            status=403)
    assert response.json == {
        u'status':
        u'error',
        u'errors': [{
            u'description':
            u"Can't perform operation for there is an award complaint in pending status",
            u'location': u'body',
            u'name': u'data'
        }]
    }

    # qualification complaints
    tender_data["qualifications"] = [{
        "id":
        "0" * 32,
        "complaints": [{
            "status": "accepted",
            "title": "complaint title",
            "description": "complaint description",
            "author": test_author,
            "resolutionType": "resolved",
            "cancellationReason": "whatever",
        }]
    }]
    app.app.registry.db.save(tender_data)

    with mock.patch(
            "openprocurement.tender.core.validation.RELEASE_2020_04_19",
            get_now() - timedelta(1)):
        response = app.post_json(
            "/tenders/{}/cancellations?acc_token={}".format(
                tender["id"], tender_token),
            {"data": {
                "reason": "cancellation reason",
                "status": "active",
            }},
            status=403)
    assert response.json == {
        u'status':
        u'error',
        u'errors': [{
            u'description':
            u"Can't perform operation for there is a qualification complaint in accepted status",
            u'location': u'body',
            u'name': u'data'
        }]
    }

    # tender complaint
    tender_data["complaints"] = [{
        "status": "satisfied",
        "title": "complaint title",
        "description": "complaint description",
        "author": test_author,
        "resolutionType": "resolved",
        "cancellationReason": "whatever",
    }]
    app.app.registry.db.save(tender_data)

    with mock.patch(
            "openprocurement.tender.core.validation.RELEASE_2020_04_19",
            get_now() - timedelta(1)):
        response = app.post_json(
            "/tenders/{}/cancellations?acc_token={}".format(
                tender["id"], tender_token),
            {"data": {
                "reason": "cancellation reason",
                "status": "active",
            }},
            status=403)
    assert response.json == {
        u'status':
        u'error',
        u'errors': [{
            u'description':
            u"Can't perform operation for there is a tender complaint in satisfied status",
            u'location': u'body',
            u'name': u'data'
        }]
    }
Beispiel #20
0
def test_post_tender_plan_403(app, tender):
    app.post_json("/tenders/{}/plans".format(tender["data"]["id"]), status=403)
Beispiel #21
0
def create_tender(app, tender_data):
    app.authorization = ("Basic", ("broker", "broker"))
    response = app.post_json("/tenders", dict(data=tender_data))
    assert response.status == "201 Created"
    return response.json