def test_update_status_invalid(app): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = "draft" response = app.post_json("/plans", {"data": test_data}) assert response.json["data"].get("status") == "draft" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"status": "invalid"}}, status=422 ) assert response.json == { "status": "error", "errors": [ { "location": "body", "name": "status", "description": ["Value must be one of ['draft', 'scheduled', 'cancelled', 'complete']."], } ], } response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"status": "cancelled"}}, status=422 ) assert response.json == { "status": "error", "errors": [ {"description": ["An active cancellation object is required"], "location": "body", "name": "status"} ], }
def test_cancel_plan_1_step(app): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = "scheduled" response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"].get("status") == "scheduled" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"cancellation": {"reason": "", "status": "active"}}}, status=422, ) assert response.json == { "status": "error", "errors": [ {"location": "body", "name": "cancellation", "description": {"reason": ["String value is too short."]}} ], } response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"cancellation": {"reason": "Because", "status": "active"}}}, ) assert response.status == "200 OK" assert response.json["data"]["cancellation"]["status"] == "active" assert response.json["data"]["status"] == "cancelled" plan = app.app.registry.databases.plans.get(plan_id) assert {c["path"] for c in plan["revisions"][-1]["changes"]} == {"/cancellation", "/status"}
def test_cancel_plan_2_steps(app, initial_status): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = initial_status response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"].get("status") == initial_status plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"cancellation": {"reason": "Because", "status": "pending"}}}, ) assert response.status == "200 OK" assert response.json["data"]["cancellation"]["status"] == "pending" assert response.json["data"].get("status") == initial_status create_time = response.json["data"]["cancellation"]["date"] response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"cancellation": {"status": "active"}}} ) assert response.status == "200 OK" assert response.json["data"]["cancellation"]["status"] == "active" assert response.json["data"]["cancellation"]["date"] > create_time assert response.json["data"]["status"] == "cancelled" get_response = app.get("/plans/{}".format(plan_id)) assert get_response.json["data"]["cancellation"]["date"] == response.json["data"]["cancellation"]["date"]
def test_fail_patch_description(app, centralized_milestone, test_status): """ milestone owner can't patch description if status not in (scheduled, met) """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data[ "token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set milestone status plan_source = app.app.registry.db.get(plan["id"]) plan_source["milestones"][0]["status"] = test_status app.app.registry.db.save(plan_source) response = app.patch_json("/plans/{}/milestones/{}?acc_token={}".format( plan["id"], milestone["id"], milestone_token), {"data": { "description": "Hello" }}, status=403) assert response.json == { "status": "error", "errors": [{ "location": "body", "name": "data", "description": "Can't update description at '{}' milestone status".format( test_status) }] }
def test_fail_complete_manually(app, value): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = "scheduled" test_data["tender"]["procurementMethodType"] = value response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"]["status"] == "scheduled" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json("/plans/{}?acc_token={}".format( plan_id, acc_token), {"data": { "status": "complete" }}, status=422) assert response.json == { "status": "error", "errors": [{ "location": "body", "name": "status", "description": [ "Can't complete plan with '{}' tender.procurementMethodType". format(value) ], }], }
def test_fail_update_back_to_draft(app, initial_status): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = initial_status response = app.post_json("/plans", {"data": test_data}) assert response.json["data"].get("status") == "scheduled" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] if initial_status is None: plan = app.app.registry.db.get(plan_id) del plan["status"] app.app.registry.db.save(plan) response = app.patch_json("/plans/{}?acc_token={}".format( plan_id, acc_token), {"data": { "status": "draft" }}, status=422) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Plan status can not be changed back to 'draft'", u"location": u"body", u"name": u"status", }], }
def test_fail_patch_milestone_status(app, centralized_milestone): """ milestone owner can't invalidate it """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data[ "token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) response = app.patch_json("/plans/{}/milestones/{}?acc_token={}".format( plan["id"], milestone["id"], milestone_token), {"data": { "status": Milestone.STATUS_INVALID }}, status=403) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Can't update milestone status from 'scheduled' to 'invalid'", u"location": u"body", u"name": u"data" }] }
def test_cancel_compatibility_completed_plan(app): """ well I don't know if it's an appropriate case. it's probably not """ app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" plan = response.json["data"] acc_token = response.json["access"]["token"] obj = app.app.registry.db.get(plan["id"]) del obj["status"] obj["tender_id"] = "a" * 32 app.app.registry.db.save(obj) response = app.get("/plans/{}".format(plan["id"])) assert response.json["data"]["status"] == "complete" # complete ! response = app.patch_json( "/plans/{}?acc_token={}".format(plan["id"], acc_token), { "data": { "cancellation": { "reason": "Because it's possible", "status": "active" } } }) assert response.status == "200 OK" assert response.json["data"]["status"] == "cancelled" # cancelled !
def test_plan_update_draft(app, mode, status): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) if mode != "real": test_data["mode"] = "test" test_data["status"] = "draft" response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"].get("status") == "draft" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": { "status": status }}) assert response.status == "200 OK" assert response.json["data"].get("status") == status response = app.get("/plans?mode={}".format(mode)) assert response.status == "200 OK" assert len(response.json["data"]) == 1 assert response.json["data"][0]["id"] == plan_id response = app.get("/plans?feed=changes&mode={}".format(mode)) assert response.status == "200 OK" assert len(response.json["data"]) == 1 assert response.json["data"][0]["id"] == plan_id
def test_success_patch_plan_procuring_entity_not_in_time( app, centralized_milestone, test_status): """ As plan owner I can change procuringEntity later that 2 working days before plan.tender.tenderPeriod.startDate if there're no approval milestones in scheduled or met """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set plan.tender.tenderPeriod.startDate and milestone status plan_source = app.app.registry.db.get(plan["id"]) plan_source["tender"]["tenderPeriod"]["startDate"] = get_now().isoformat() plan_source["milestones"][0]["status"] = test_status app.app.registry.db.save(plan_source) request_entity = { "identifier": { "scheme": u"UA-EDR", "id": u"222222", "legalName": u"ЦЗО 2" }, "name": u"ЦЗО 2" } response = app.patch_json("/plans/{}?acc_token={}".format( plan["id"], plan_token), {"data": { "procuringEntity": request_entity }}, status=200) assert response.json["data"]["procuringEntity"] == request_entity
def test_success_patch_milestone_status(app, centralized_milestone, test_status): """ milestone owner can set its status to met or notMet """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data[ "token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) response = app.patch_json( "/plans/{}/milestones/{}?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": { "status": test_status }}) assert response.status_code == 200 result_plan = app.app.registry.db.get(plan["id"]) result = result_plan.get("milestones")[0] assert result_plan["dateModified"] == result["dateModified"] assert result["status"] == test_status assert result["dateModified"] > milestone["dateModified"] if test_status == Milestone.STATUS_MET: assert result["dateModified"] == result["dateMet"] else: assert "dateMet" not in result
def test_forbidden_patch_milestone(app, centralized_milestone): """ plan owner or just broker can't patch milestone """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data[ "token"] plan, plan_token = plan_data["data"], plan_data["token"] response = app.patch_json("/plans/{}/milestones/{}?acc_token={}".format( plan["id"], milestone["id"], plan_token), { "data": { "description": "What", "dueDate": "2001-10-30T11:15:26.641038+03:00" } }, status=403) assert response.json == { "status": "error", "errors": [{ "location": "url", "name": "permission", "description": "Forbidden" }] }
def test_fail_complete_manually(app, value): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = "scheduled" test_data["tender"]["procurementMethodType"] = value if value == "aboveThresholdUA.defense": patch_date = get_now() + timedelta(days=1) else: patch_date = get_now() - timedelta(days=1) if value in ("aboveThresholdUA.defense", "simple.defense"): with patch( "openprocurement.planning.api.validation.RELEASE_SIMPLE_DEFENSE_FROM", patch_date): response = app.post_json("/plans", {"data": test_data}, status=403) assert response.status == "403 Forbidden" assert response.json["errors"] == [{ u'description': u'procuringEntity with general kind cannot publish this type of procedure.' u' Procurement method types allowed for this kind: centralizedProcurement, reporting,' u' negotiation, negotiation.quick, priceQuotation, belowThreshold, aboveThresholdUA, aboveThresholdEU,' u' competitiveDialogueUA, competitiveDialogueEU, esco, closeFrameworkAgreementUA.', u'location': u'body', u'name': u'kind' }] test_data["procuringEntity"]["kind"] = "defense" with patch( "openprocurement.planning.api.validation.RELEASE_SIMPLE_DEFENSE_FROM", patch_date): response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"]["status"] == "scheduled" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json("/plans/{}?acc_token={}".format( plan_id, acc_token), {"data": { "status": "complete" }}, status=422) assert response.json == { "status": "error", "errors": [{ "location": "body", "name": "status", "description": [ "Can't complete plan with '{}' tender.procurementMethodType". format(value) ], }], }
def test_forbidden_update_milestone_documents(app, centralized_milestone): """ Plan owner or just broker can't manage milestone documents """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data[ "token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) response = app.post_json( "/plans/{}/milestones/{}/documents?acc_token={}".format( plan["id"], milestone["id"], plan_token), {"data": {}}, status=403) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Forbidden", u"location": u"url", u"name": u"permission" }] } # put document = milestone["documents"][0] response = app.put_json( "/plans/{}/milestones/{}/documents/{}?acc_token={}".format( plan["id"], milestone["id"], document["id"], plan_token), {"data": {}}, status=403) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Forbidden", u"location": u"url", u"name": u"permission" }] } # patch response = app.patch_json( "/plans/{}/milestones/{}/documents/{}?acc_token={}".format( plan["id"], milestone["id"], document["id"], plan_token), {"data": {}}, status=403) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Forbidden", u"location": u"url", u"name": u"permission" }] }
def test_patch_milestone(app, centralized_milestone): """ milestone owner can patch it """ milestone_data, plan_data = centralized_milestone["milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data["token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) request_data = { "id": "a" * 32, "description": "What?", "dueDate": "2001-10-30T11:15:26.641038+03:00", "documents": [ { "title": "text.txt", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "text/plain", } ], "status": Milestone.STATUS_MET, "author": { "identifier": { "scheme": "UA-EDR", "id": "222222", "legalName": "ЦЗО 2" }, "name": "ЦЗО 2" }, "dateModified": "2001-10-30T11:15:26.641038+03:00", "dateMet": "1917-10-30T11:15:26.641038+03:00", "owner": "wtf", "owner_token": "b" * 4, } response = app.patch_json( "/plans/{}/milestones/{}?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": request_data} ) assert response.status_code == 200 result_plan = app.app.registry.databases.plans.get(plan["id"]) result = result_plan.get("milestones")[0] # fields that haven"t been changed assert result["id"] == milestone["id"] assert result["documents"] == milestone["documents"] assert result["author"] == milestone["author"] assert result["owner"] == milestone["owner"] assert result["owner_token"] == milestone_token assert result_plan["dateModified"] == result["dateModified"] # changed assert result["dueDate"] == request_data["dueDate"] assert result["status"] == request_data["status"] assert result["description"] == request_data["description"] assert result["dateModified"] > milestone["dateModified"] assert result["dateModified"] == result["dateMet"] == response.json["data"]["dateMet"]
def test_fail_patch_due_date(app, centralized_milestone): """ milestone owner can patch some its fileds """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data[ "token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) response = app.patch_json( "/plans/{}/milestones/{}?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": { "status": Milestone.STATUS_MET }}, ) assert response.json["data"]["status"] == Milestone.STATUS_MET response = app.patch_json( "/plans/{}/milestones/{}?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": { "dueDate": "2001-10-30T11:15:26.641038+03:00" }}, status=403) assert response.json == { "status": "error", "errors": [{ "location": "body", "name": "data", "description": "Can't update dueDate at 'met' milestone status" }] }
def test_plan_update_scheduled_to_complete(app): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = "scheduled" response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"].get("status") == "scheduled" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json("/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"status": "complete"}}) assert response.status == "200 OK" assert response.json["data"].get("status") == "complete"
def test_fail_patch_plan_procuring_entity_not_in_time(app, centralized_milestone): """ As plan owner I can't change procuringEntity later that 2 working days before plan.tender.tenderPeriod.startDate if there're milestones in scheduled or met """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set plan.tender.tenderPeriod.startDate plan_source = app.app.registry.db.get(plan["id"]) plan_source["tender"]["tenderPeriod"]["startDate"] = get_now().isoformat() app.app.registry.db.save(plan_source) response = app.patch_json("/plans/{}?acc_token={}".format( plan["id"], plan_token), { "data": { "procuringEntity": { "identifier": { "scheme": u"UA-EDR", "id": u"222222", "legalName": u"ЦЗО 2" }, "name": u"ЦЗО 2", "address": { "countryName": u"Україна", "postalCode": u"01220", "region": u"м. Київ", "locality": u"м. Київ", "streetAddress": u"вул. Банкова, 11, корпус 1", }, "kind": u"general", } } }, status=403) assert response.json == { u'status': u'error', u'errors': [{ u'description': u"Can't update procuringEntity later than 2 business days before tenderPeriod.StartDate", u'location': u'body', u'name': u'data' }] }
def test_success_patch_plan_procuring_entity_in_time(app, centralized_milestone, test_statuses): """ As plan owner I can change procuringEntity, so milestone status becomes "invalid" if it was "scheduled" or "met" but "notMet" status should not be changed """ test_status, expected_status = test_statuses milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set milestone status plan_source = app.app.registry.db.get(plan["id"]) plan_source["milestones"][0]["status"] = test_status app.app.registry.db.save(plan_source) new_procuring_entity = { "identifier": { "scheme": u"UA-EDR", "id": u"222222", "legalName": u"ЦЗО 2" }, "name": u"ЦЗО 2", "address": { "countryName": u"Україна", "postalCode": u"01220", "region": u"м. Київ", "locality": u"м. Київ", "streetAddress": u"вул. Банкова, 11, корпус 1", }, "kind": u"general", } response = app.patch_json( "/plans/{}?acc_token={}".format(plan["id"], plan_token), {"data": { "procuringEntity": new_procuring_entity }}) assert response.status_code == 200 assert response.json["data"]["procuringEntity"] == new_procuring_entity assert response.json["data"]["milestones"][0]["status"] == expected_status assert response.json["data"]["dateModified"] > plan["dateModified"] if expected_status == Milestone.STATUS_INVALID and test_status != Milestone.STATUS_INVALID: assert response.json["data"]["milestones"][0][ "dateModified"] == response.json["data"]["dateModified"]
def test_success_complete_manually(app, value): procurement_method, procurement_method_type = value app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["status"] = "scheduled" test_data["tender"]["procurementMethod"] = procurement_method test_data["tender"]["procurementMethodType"] = procurement_method_type response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"]["status"] == "scheduled" plan_id = response.json["data"]["id"] acc_token = response.json["access"]["token"] response = app.patch_json( "/plans/{}?acc_token={}".format(plan_id, acc_token), {"data": {"status": "complete"}}, status=200 ) assert response.json["data"]["status"] == "complete"
def test_success_patch_description(app, centralized_milestone, test_status): """ milestone owner can patch description if status in (scheduled, met) """ milestone_data, plan_data = centralized_milestone["milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data["token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set milestone status plan_source = app.app.registry.databases.plans.get(plan["id"]) plan_source["milestones"][0]["status"] = test_status app.app.registry.databases.plans.save(plan_source) new_description = "Changes are coming" response = app.patch_json( "/plans/{}/milestones/{}?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": {"description": new_description}}, status=200 ) assert response.json["data"]["description"] == new_description
def test_success_patch_plan_procuring_entity_not_in_time(app, centralized_milestone, test_status): """ As plan owner I can change procuringEntity later that 2 working days before plan.tender.tenderPeriod.startDate if there're no approval milestones in scheduled or met """ milestone_data, plan_data = centralized_milestone["milestone"], centralized_milestone["plan"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set plan.tender.tenderPeriod.startDate and milestone status plan_source = app.app.registry.databases.plans.get(plan["id"]) plan_source["tender"]["tenderPeriod"]["startDate"] = get_now().isoformat() plan_source["milestones"][0]["status"] = test_status app.app.registry.databases.plans.save(plan_source) request_entity = { "id": uuid4().hex, "identifier": { "scheme": "UA-EDR", "id": "222222", "legalName": "ЦЗО 2" }, "name": "ЦЗО 2", "address": { "countryName": "Україна", "postalCode": "01220", "region": "м. Київ", "locality": "м. Київ", "streetAddress": "вул. Банкова, 11, корпус 1", }, "kind": "general", } response = app.patch_json( "/plans/{}?acc_token={}".format(plan["id"], plan_token), {"data": { "procuringEntity": request_entity }}, status=200 ) assert response.json["data"]["procuringEntity"] == request_entity
def test_fail_patch_due_date(app, centralized_milestone, test_status): """ milestone owner can't patch dueDate if status != scheduled """ milestone_data, plan_data = centralized_milestone["milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data["token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) # set milestone status plan_source = app.app.registry.databases.plans.get(plan["id"]) plan_source["milestones"][0]["status"] = test_status app.app.registry.databases.plans.save(plan_source) response = app.patch_json( "/plans/{}/milestones/{}?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": {"dueDate": "2001-10-30T11:15:26.641038+03:00"}}, status=403 ) assert response.json == {"status": "error", "errors": [ {"location": "body", "name": "data", "description": "Can't update dueDate at '{}' milestone status".format(test_status)}]}
def test_success_patch_plan_without_invalidating_milestone( app, centralized_milestone): """ As plan owner I can change the plan, and milestone should remain "scheduled" """ milestone_data, plan_data = centralized_milestone[ "milestone"], centralized_milestone["plan"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) assert milestone_data["data"]["status"] == "scheduled" response = app.patch_json( "/plans/{}?acc_token={}".format(plan["id"], plan_token), {"data": { "items": [{ "description": "smt" }] }}) assert response.status_code == 200 assert response.json["data"]["items"][0]["description"] == "smt" assert response.json["data"]["milestones"][0]["status"] == "scheduled"
def test_validations_before_and_after_tender(app): app.authorization = ("Basic", ("broker", "broker")) request_tender_data = deepcopy(below_tender_data) request_plan_data = deepcopy(test_plan_data) plan = create_plan_for_tender(app, request_tender_data, request_plan_data) # changing procuringEntity pe_change = { "identifier": { "scheme": "UA-EDR", "id": "111983", "legalName": "ДП Державне Управління Справами" }, "name": "ДУС", } response = app.patch_json( "/plans/{}?acc_token={}".format(plan["data"]["id"], plan["access"]["token"]), {"data": { "procuringEntity": pe_change }}, ) assert response.status == "200 OK" # adding tender request_tender_data["procuringEntity"]["identifier"]["id"] = pe_change[ "identifier"]["id"] request_tender_data["procuringEntity"]["identifier"]["scheme"] = pe_change[ "identifier"]["scheme"] response = app.post_json("/plans/{}/tenders".format(plan["data"]["id"]), {"data": request_tender_data}) assert response.status == "201 Created" # removing status (if the tender was created before the plan statuses release) plan_from_db = app.app.registry.databases.plans.get(plan["data"]["id"]) del plan_from_db["status"] app.app.registry.databases.plans.save(plan_from_db) response = app.get("/plans/{}".format(plan["data"]["id"])) assert response.json["data"]["status"] == "complete" # try to change procuringEntity response = app.patch_json( "/plans/{}?acc_token={}".format(plan["data"]["id"], plan["access"]["token"]), { "data": { "procuringEntity": { "identifier": { "scheme": "UA-EDR", "id": "111983", "legalName": "ДП Державне Управління Справами", }, "name": "ДУС", } } }, status=422, ) assert response.json == { "status": "error", "errors": [{ "description": "Changing this field is not allowed after tender creation", "location": "body", "name": "procuringEntity", }], } # try to change budgetBreakdown response = app.patch_json( "/plans/{}?acc_token={}".format(plan["data"]["id"], plan["access"]["token"]), { "data": { "budget": { "breakdown": [{ "description": "Changed description" }] } } }, status=422, ) assert response.json == { "status": "error", "errors": [{ "description": "Changing this field is not allowed after tender creation", "location": "body", "name": "budget.breakdown", }], } # try to change anything except procuringEntity and budgetBreakdown response = app.patch_json( "/plans/{}?acc_token={}".format(plan["data"]["id"], plan["access"]["token"]), { "data": { "procurementMethodType": "whatever", "items": [{ "classification": { "scheme": "ДК021", "description": "Antiperspirants", "id": "33711120-4" } }], "classification": { "scheme": "ДК021", "description": "Antiperspirants", "id": "33711120-4" }, } }, ) assert response.status == "200 OK" # try again response = app.patch_json( "/plans/{}?acc_token={}".format(plan["data"]["id"], plan["access"]["token"]), {"data": { "procurementMethodType": "another" }}, status=422, ) assert response.json == { "status": "error", "errors": [{ "location": "body", "name": "status", "description": "Can't update plan in 'complete' status" }], }
def test_update_milestone_documents(app, centralized_milestone): """ as a milestone owner I can manage it's documents """ milestone_data, plan_data = centralized_milestone["milestone"], centralized_milestone["plan"] milestone, milestone_token = milestone_data["data"], milestone_data["token"] plan, plan_token = plan_data["data"], plan_data["token"] app.authorization = ("Basic", ("broker", "broker")) plan_date_modified = plan["dateModified"] milestone_date_modified = milestone["dateModified"] request_data = { "title": "sign.p7s", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "application/pk7s", } response = app.post_json( "/plans/{}/milestones/{}/documents?acc_token={}".format(plan["id"], milestone["id"], milestone_token), {"data": request_data}, ) assert response.status_code == 201 result_plan = app.app.registry.databases.plans.get(plan["id"]) result_milestone = result_plan.get("milestones")[0] assert len(result_milestone["documents"]) == 2 new_doc = result_milestone["documents"][1] assert new_doc["title"] == request_data["title"] assert new_doc["hash"] == request_data["hash"] assert new_doc["format"] == request_data["format"] assert new_doc["url"].split("Signature")[0] == request_data["url"].split("Signature")[0] assert result_plan["dateModified"] > plan_date_modified plan_date_modified = result_plan["dateModified"] assert result_plan["milestones"][0]["dateModified"] > milestone_date_modified milestone_date_modified = result_plan["milestones"][0]["dateModified"] # put request_data = { "title": "sign-2.p7s", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "application/signature", } response = app.put_json( "/plans/{}/milestones/{}/documents/{}?acc_token={}".format( plan["id"], milestone["id"], new_doc["id"], milestone_token), {"data": request_data}, ) assert response.status_code == 200 result_plan = app.app.registry.databases.plans.get(plan["id"]) result_milestone = result_plan.get("milestones")[0] assert len(result_milestone["documents"]) == 3 old_doc = new_doc new_doc = result_milestone["documents"][2] assert new_doc["id"] == old_doc["id"] assert new_doc["title"] == request_data["title"] assert new_doc["hash"] == request_data["hash"] assert new_doc["format"] == request_data["format"] assert new_doc["url"].split("Signature")[0] == request_data["url"].split("Signature")[0] assert result_plan["dateModified"] > plan_date_modified plan_date_modified = result_plan["dateModified"] assert result_plan["milestones"][0]["dateModified"] > milestone_date_modified milestone_date_modified = result_plan["milestones"][0]["dateModified"] # patch request_data = { "title": "sign-3.p7s", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "ms/sms", "documentOf": "my ma", "documentType": "notice", "language": "c++", } response = app.patch_json( "/plans/{}/milestones/{}/documents/{}?acc_token={}".format( plan["id"], milestone["id"], new_doc["id"], milestone_token), {"data": request_data}, ) assert response.status_code == 200 result_plan = app.app.registry.databases.plans.get(plan["id"]) result_milestone = result_plan.get("milestones")[0] assert len(result_milestone["documents"]) == 3 patched_doc = result_milestone["documents"][2] assert patched_doc["id"] == new_doc["id"] assert patched_doc["hash"] == new_doc["hash"] assert patched_doc["url"].split("Signature")[0] == new_doc["url"].split("Signature")[0] assert patched_doc["format"] == request_data["format"] assert patched_doc["title"] == request_data["title"] assert patched_doc["documentOf"] == request_data["documentOf"] assert patched_doc["documentType"] == request_data["documentType"] assert patched_doc["language"] == request_data["language"] assert result_plan["dateModified"] > plan_date_modified assert result_plan["milestones"][0]["dateModified"] > milestone_date_modified
def test_fail_update_complete_or_cancelled_plan(app, status): app.authorization = ("Basic", ("broker", "broker")) test_data = deepcopy(test_plan_data) test_data["documents"] = [{ "title": u"укр.doc", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "application/msword", }] test_data["status"] = status if status == "cancelled": test_data["cancellation"] = dict(reason="Because", status="active") response = app.post_json("/plans", {"data": test_data}) assert response.status == "201 Created" assert response.json["data"].get("status") == status plan_id = response.json["data"]["id"] doc_id = response.json["data"]["documents"][0]["id"] acc_token = response.json["access"]["token"] # patch response = app.patch_json("/plans/{}?acc_token={}".format( plan_id, acc_token), {"data": {}}, status=422) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Can't update plan in '{}' status".format(status), u"location": u"body", u"name": u"status", }], } # docs response = app.post_json( "/plans/{}/documents?acc_token={}".format(plan_id, acc_token), { "data": { "title": u"укр.doc", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "application/msword", } }, status=422, ) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Can't update plan in '{}' status".format(status), u"location": u"body", u"name": u"status", }], } response = app.put_json( "/plans/{}/documents/{}?acc_token={}".format(plan_id, doc_id, acc_token), { "data": { "title": u"укр_2.doc", "url": generate_docservice_url(app), "hash": "md5:" + "0" * 32, "format": "application/msword", } }, status=422, ) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Can't update plan in '{}' status".format(status), u"location": u"body", u"name": u"status", }], } response = app.patch_json( "/plans/{}/documents/{}?acc_token={}".format(plan_id, doc_id, acc_token), {"data": { "title": u"whatever.doc" }}, status=422, ) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Can't update plan in '{}' status".format(status), u"location": u"body", u"name": u"status", }], } # tender creation response = app.post_json("/plans/{}/tenders".format(plan_id), {"data": {}}, status=422) assert response.json == { u"status": u"error", u"errors": [{ u"description": u"Can't update plan in '{}' status".format(status), u"location": u"body", u"name": u"status", }], }