Example #1
0
def validate_operation_submission_in_not_allowed_period(request, **kwargs):
    framework = request.validated["framework"]
    enquiryPeriod = framework.get("enquiryPeriod")
    operation = OPERATIONS.get(request.method)
    period = framework.get("period")
    if (
        not enquiryPeriod
        or "endDate" not in enquiryPeriod
        or not period
        or "endDate" not in period
    ):
        raise_operation_error(
            request,
            "Submission cannot be {} without framework enquiryPeriod or period".format(operation)
        )
    enquiryPeriod_endDate = parse_date(enquiryPeriod["endDate"])
    period_endDate = parse_date(period["endDate"])
    now = get_now()

    if now < enquiryPeriod_endDate or now > period_endDate:
        raise_operation_error(
            request,
            "Submission can be {} only during the period: from ({}) to ({}).".format(
                operation, enquiryPeriod_endDate, period_endDate),
        )
Example #2
0
def validate_agreement_signing(request, **kwargs):
    tender = request.validated["tender"]
    data = request.validated["data"]
    config = getAdapter(tender, IContentConfigurator)
    if request.context.status != "active" and "status" in data and data[
            "status"] == "active":
        if "period" not in data or not data["period"]:
            raise_operation_error(request,
                                  "Period is required for agreement signing.")
        if not data["period"]["startDate"] or not data["period"]["endDate"]:
            raise_operation_error(
                request,
                "startDate and endDate are required in agreement.period.")
        agreement_start_date = parse_date(data["period"]["startDate"])
        agreement_end_date = parse_date(data["period"]["endDate"])
        calculated_end_date = agreement_start_date + config.max_agreement_period
        if calculated_end_date < agreement_end_date:
            raise_operation_error(
                request,
                "Agreement period can't be greater than {}.".format(
                    duration_isoformat(config.max_agreement_period)),
            )
        awards = [
            a for a in tender.awards
            if a.id in request.context.get_awards_id()
        ]
        lots_id = set([a.lotID for a in awards] + [None])
        pending_complaints = [
            i for i in tender.complaints
            if i.status in tender.block_complaint_status
            and i.relatedLot in lots_id
        ]
        pending_awards_complaints = [
            i for a in tender.awards for i in a.complaints
            if i.status in tender.block_complaint_status and a.lotID in lots_id
        ]
        if pending_complaints or pending_awards_complaints:
            raise_operation_error(
                request,
                "Can't sign agreement before reviewing all complaints")
        empty_unitprices = []
        active_contracts = []
        for contract in request.context.contracts:
            if contract.status == "active":
                active_contracts.append(contract.id)
                for unit_price in contract.unitPrices:
                    empty_unitprices.append(unit_price.value.amount is None)
        if any(empty_unitprices):
            raise_operation_error(
                request,
                "Can't sign agreement without all contracts.unitPrices.value.amount"
            )
        if len(active_contracts) < config.min_bids_number:
            raise_operation_error(
                request, "Agreement don't reach minimum active contracts.")
Example #3
0
 def test_tender_award_complaint_period(self, name, date_str,
                                        mock_normalized_date_str,
                                        mock_midnight_date_str,
                                        expected_date_str,
                                        expected_sb_date_str):
     tender_award_complaint_period(
         self,
         parse_date(date_str),
         parse_date(mock_normalized_date_str),
         parse_date(mock_midnight_date_str),
         parse_date(expected_date_str),
         parse_date(expected_sb_date_str),
     )
Example #4
0
def next_check_value_with_unanswered_question(self):
    response = self.app.post_json(
        "/tenders/{}/questions".format(self.tender_id),
        {
            "data": {
                "title": "question title",
                "description": "question description",
                "questionOf": "lot",
                "relatedItem": self.initial_lots[0]["id"],
                "author": test_author,
            }
        },
    )
    question = response.json["data"]
    self.assertEqual(question["questionOf"], "lot")
    self.assertEqual(question["relatedItem"], self.initial_lots[0]["id"])

    self.set_status("active.auction", extra={"status": "active.tendering"})
    response = self.check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.tendering")
    self.assertNotIn("next_check", response.json["data"])

    cancellation = dict(**test_cancellation)
    cancellation.update({
        "status": "active",
        "cancellationOf": "lot",
        "relatedLot": self.initial_lots[0]["id"],
    })
    response = self.app.post_json(
        "/tenders/{}/cancellations?acc_token={}".format(
            self.tender_id, self.tender_token),
        {"data": cancellation},
    )
    cancellation_id = response.json["data"]["id"]

    if RELEASE_2020_04_19 < get_now():
        activate_cancellation_with_complaints_after_2020_04_19(
            self, cancellation_id)
    else:
        response = self.app.get("/tenders/{}".format(self.tender_id))
        self.assertIn("next_check", response.json["data"])
        self.assertEqual(
            parse_date(response.json["data"]["next_check"]),
            parse_date(response.json["data"]["tenderPeriod"]["endDate"]))
    response = self.check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.auction")
    self.assertIn("next_check", response.json["data"])
    self.assertGreater(
        parse_date(response.json["data"]["next_check"]),
        parse_date(response.json["data"]["tenderPeriod"]["endDate"]))
    def recalculate_tender_periods(self):
        tender = self.request.validated["tender"]
        cancellation = self.request.validated["cancellation"]
        tenderer_action_date = self.context.tendererActionDate

        enquiry_period = tender.enquiryPeriod
        complaint_period = tender.complaintPeriod
        tender_period = tender.tenderPeriod
        auction_period = tender.auctionPeriod

        date = cancellation.complaintPeriod.startDate
        diff = calculate_date_diff(tenderer_action_date, date)
        delta = diff.days
        delta_plus = 1 if diff.seconds > 3599 else 0

        delta += delta_plus

        delta = timedelta(days=1 if not delta else delta)

        if tender.status == "active.tendering" and tender.enquiryPeriod:

            if enquiry_period.startDate < date <= tender_period.endDate:
                enquiry_period.endDate = calculate_tender_business_date(
                    enquiry_period.endDate, delta, tender, True)

                enquiry_period.clarificationsUntil = calculate_tender_business_date(
                    enquiry_period.clarificationsUntil, delta, tender, True)

                tender_period.endDate = calculate_tender_business_date(
                    tender_period.endDate, delta, tender, True)

                complaint_period.endDate = calculate_tender_business_date(
                    complaint_period.endDate, delta, tender, True)

                if auction_period.shouldStartAfter:
                    auction_period.shouldStartAfter = calculate_tender_business_date(
                        parse_date(auction_period.shouldStartAfter), delta,
                        tender, True).isoformat()

                if auction_period.startDate:
                    auction_period.startDate = calculate_tender_business_date(
                        auction_period.startDate, delta, tender, True)

            elif auction_period and tender_period.endDate and auction_period.shouldStartAfter\
                    and tender_period.endDate < date <= parse_date(auction_period.shouldStartAfter):

                auction_period.shouldStartAfter = calculate_tender_business_date(
                    auction_period.shouldStartAfter, delta, tender, True)
                auction_period.startDate = calculate_tender_business_date(
                    auction_period.startDate, delta, tender, True)
Example #6
0
def get_version_from_date(request, doc, revisions):
    version_date = parse_date(request.headers.get(VERSION_BY_DATE, pytz.utc))
    if version_date > parse_date(
            doc["dateModified"]) or version_date < parse_date(
                revisions[1]["date"]):
        return return404(request, "header", "version")
    for version, revision in reversed(list(enumerate(revisions))):
        doc = get_valid_apply_patch_doc(doc, request, revision)
        if version_date < parse_date(find_dateModified(revisions[:version])):
            continue
        else:
            doc["dateModified"] = find_dateModified(revisions[:version + 1])
            return (doc, parse_hash(revision["rev"]),
                    parse_hash(revisions[version - 1].get("rev", "")))
    return404(request, "header", "version")
Example #7
0
def next_check_value_with_unanswered_claim(self):
    claim = deepcopy(test_claim)
    claim["relatedLot"] = self.initial_lots[0]["id"]
    response = self.app.post_json(
        "/tenders/{}/complaints".format(self.tender_id),
        {"data": claim},
    )
    self.assertEqual(response.status, "201 Created")
    complaint = response.json["data"]
    self.assertEqual(complaint["relatedLot"], self.initial_lots[0]["id"])

    self.set_status("active.auction", extra={"status": "active.tendering"})
    orig_auth = self.app.authorization
    response = self.check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.tendering")
    self.assertNotIn("next_check", response.json["data"])

    self.app.authorization = orig_auth
    cancellation = dict(**test_cancellation)
    cancellation.update({
        "status": "active",
        "cancellationOf": "lot",
        "relatedLot": self.initial_lots[0]["id"],
    })
    response = self.app.post_json(
        "/tenders/{}/cancellations?acc_token={}".format(
            self.tender_id, self.tender_token),
        {"data": cancellation},
    )

    cancellation_id = response.json["data"]["id"]

    if RELEASE_2020_04_19 < get_now():
        activate_cancellation_with_complaints_after_2020_04_19(
            self, cancellation_id)
    else:
        response = self.app.get("/tenders/{}".format(self.tender_id))
        self.assertIn("next_check", response.json["data"])
        self.assertEqual(
            parse_date(response.json["data"]["next_check"]),
            parse_date(response.json["data"]["tenderPeriod"]["endDate"]))
    response = self.check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.auction")
    self.assertIn("next_check", response.json["data"])
    self.assertGreater(
        parse_date(response.json["data"]["next_check"]),
        parse_date(response.json["data"]["tenderPeriod"]["endDate"]))
Example #8
0
def switch_tender_cancellation_complaints_draft(self):
    # first we post a cancellation
    tender = self.db.get(self.tender_id)
    cancellation = deepcopy(test_cancellation)
    cancellation["status"] = "pending"
    cancellation["complaintPeriod"] = dict(
        startDate=get_now(),
        endDate=get_now() + timedelta(days=10),
    )
    cancellation = Cancellation(cancellation)
    cancellation_data = cancellation.serialize("embedded")
    tender.update(cancellations=[cancellation_data])
    self.db.save(tender)

    # let's post a draft complaint
    response = self.app.post_json(
        "/tenders/{}/cancellations/{}/complaints".format(
            self.tender_id, cancellation.id),
        {"data": test_draft_complaint},
    )
    self.assertEqual(response.json["data"]["status"], "draft")

    # get tender and check next_check
    response = self.app.get("/tenders/{}".format(self.tender_id))
    self.assertEqual(
        parse_date(response.json["data"].get("next_check")),
        parse_date(cancellation_data["complaintPeriod"]["endDate"]),
    )

    # and once the date passed
    tender = self.db.get(self.tender_id)
    tender["cancellations"][0]["complaintPeriod"] = dict(
        startDate=(get_now() - timedelta(days=30)).isoformat(),
        endDate=(get_now() - timedelta(days=20)).isoformat())
    self.db.save(tender)

    # switch
    response = self.check_chronograph()
    self.assertNotEqual(response.json["data"].get("next_check"),
                        cancellation_data["complaintPeriod"]["endDate"])

    # check complaint status
    response = self.app.get("/tenders/{}/cancellations/{}/complaints".format(
        self.tender_id, cancellation.id))
    complaint = response.json["data"][0]
    self.assertEqual(complaint["status"], "mistaken")
    self.assertEqual(complaint["rejectReason"], "complaintPeriodEnded")
Example #9
0
 def to_native(self, value, context=None):
     if isinstance(value, datetime):
         return value
     try:
         return parse_date(value, default_timezone=TZ)
     except ValueError:
         raise ConversionError(self.messages["parse"].format(value))
     except OverflowError as e:
         raise ConversionError(str(e))
def set_auction_period(self):
    def check_chronograph(auction_period_data=None):
        if self.initial_lots:
            data = {
                "data": {
                    "lots": [{
                        "auctionPeriod": auction_period_data
                    }]
                }
            } if auction_period_data else None
            ch_response = self.check_chronograph(data)
            ch_response_item = ch_response.json["data"]["lots"][0]
        else:
            data = {
                "data": {
                    "auctionPeriod": auction_period_data
                }
            } if auction_period_data else None
            ch_response = self.check_chronograph(data)
            ch_response_item = ch_response.json["data"]
        return ch_response, ch_response_item

    self.set_status("active.tendering", {"status": "active.enquiries"})

    response, item = check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.tendering")
    self.assertIn("auctionPeriod", item)
    self.assertIn("shouldStartAfter", item["auctionPeriod"])
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertIn("T00:00:00+", item["auctionPeriod"]["shouldStartAfter"])
    self.assertEqual(
        parse_date(response.json["data"]["next_check"]),
        parse_date(response.json["data"]["tenderPeriod"]["endDate"]))

    response, item = check_chronograph(
        auction_period_data={"startDate": "9999-01-01T00:00:00"})
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(item["auctionPeriod"]["startDate"],
                     "9999-01-01T00:00:00+02:00")

    response, item = check_chronograph(auction_period_data={"startDate": None})
    self.assertEqual(response.status, "200 OK")
    self.assertNotIn("startDate", item["auctionPeriod"])
Example #11
0
def switch_award_complaints_draft(self):
    response = self.app.patch_json(
        "/tenders/{}/awards/{}?acc_token={}".format(self.tender_id,
                                                    self.award_id,
                                                    self.tender_token),
        {"data": {
            "status": "active"
        }},
    )
    self.assertEqual(response.json["data"]["status"], "active")
    award_data = response.json["data"]

    # let's post a draft complaint
    token = list(self.initial_bids_tokens.values())[0]
    response = self.app.post_json(
        "/tenders/{}/awards/{}/complaints?acc_token={}".format(
            self.tender_id, self.award_id, token),
        {"data": test_draft_complaint},
    )
    self.assertEqual(response.json["data"]["status"], "draft")

    # get tender and check next_check
    response = self.app.get("/tenders/{}".format(self.tender_id))
    self.assertEqual(
        parse_date(response.json["data"].get("next_check")),
        parse_date(award_data["complaintPeriod"]["endDate"]),
    )

    # and once the date passed
    tender = self.db.get(self.tender_id)
    tender["awards"][0]["complaintPeriod"] = dict(
        startDate=(get_now() - timedelta(days=20)).isoformat(),
        endDate=(get_now() - timedelta(days=10)).isoformat())
    self.db.save(tender)

    # switch
    response = self.check_chronograph()
    data = response.json["data"]
    complaint = data["awards"][0]["complaints"][0]
    self.assertEqual(complaint["status"], "mistaken")
    self.assertEqual(complaint["rejectReason"], "complaintPeriodEnded")
    self.assertNotEqual(data.get("next_check"),
                        award_data["complaintPeriod"]["endDate"])
Example #12
0
    def setUp(self):
        super(BaseSubmissionContentWebTest, self).setUp()
        self.initial_submission_data["frameworkID"] = self.framework_id
        response = self.app.patch_json(
            "/frameworks/{}?acc_token={}".format(self.framework_id, self.framework_token),
            {"data": {"status": "active"}}
        )
        submission_date = parse_date(response.json["data"]["enquiryPeriod"]["endDate"])

        self.freezer = freeze_time((submission_date + timedelta(hours=1)).isoformat(), tick=True)
        self.freezer.start()
Example #13
0
def validate_header(request):
    version = request.validated[VERSION] = request.headers.get(VERSION, "")
    request.validated[HASH] = request.headers.get(HASH, "")
    if request.headers.get(VERSION_BY_DATE, "") != "":
        try:
            request.validated[VERSION_BY_DATE] = parse_date(
                request.headers.get(VERSION_BY_DATE, ""), pytz.utc)
        except:
            if (version and
                (not version.isdigit() or int(version) < 1)) or version == "":
                return404(request, "header", "version")
            else:
                request.validated[VERSION_BY_DATE] = ""
                return
    if (version and
        (not version.isdigit() or int(version) < 1)) and request.headers.get(
            VERSION_BY_DATE, "") == "":
        return404(request, "header", "version")
def test_post_milestone(app, centralized_plan):
    plan, access_token = centralized_plan

    app.authorization = ("Basic", ("broker", "broker"))
    response = app.post_json(
        "/plans/{}/milestones".format(plan["id"]),
        {"data": test_milestone_data(app)}
    )
    assert response.status_code == 201
    milestone = response.json["data"]
    assert set(milestone.keys()) == {"status", "description", "title", "author", "id", "owner", 
                                     "type", "dateModified", "dueDate", "documents"}
    assert milestone["description"] == MILESTONE_APPROVAL_DESCRIPTION
    assert milestone["status"] == Milestone.STATUS_SCHEDULED
    date_modified = parse_date(milestone["dateModified"])
    assert get_now() - date_modified < timedelta(seconds=1)
    assert "documents" in milestone
    assert "access" in response.json
    assert "token" in response.json["access"]

    response = app.get("/plans/{}".format(plan["id"]))
    assert response.json["data"]["dateModified"] == milestone["dateModified"]
Example #15
0
 def test_parse_date_invalid_format(self):
     dt_str = "test"
     with self.assertRaises(ValueError) as e:
         parse_date(dt_str)
Example #16
0
 def test_parse_date_with_no_time_and_tz(self):
     dt_str = "2020-01-01"
     dt_result = parse_date(dt_str)
     dt_expected = utc.localize(datetime(2020, 1, 1))
     self.assertEqual(dt_result, dt_expected)
Example #17
0
 def test_parse_date(self):
     dt_str = "2020-01-01T12:00:00+02:00"
     dt_result = parse_date(dt_str)
     dt_expected = timezone("Europe/Kiev").localize(
         datetime(2020, 1, 1, 12, 0, 0))
     self.assertEqual(dt_result, dt_expected)
Example #18
0
def check_auction_period(period, tender):
    if period and period.startDate and period.shouldStartAfter:
        start = parse_date(period.shouldStartAfter)
        date = calculate_tender_date(start, AUCTION_PERIOD_TIME, tender, True)
        return period.startDate > date
    return False
Example #19
0
    def test_milestone(self):
        """
        test alp milestone is created in two cases
        1. amount less by >=40% than mean of amount before auction
        2. amount less by >=30%  than the next amount
        :return:
        """
        # sending auction results
        auction_results = deepcopy(self.initial_bids)
        if "lotValues" in self.initial_bids[0]:
            lot_id = auction_results[0]["lotValues"][0]["relatedLot"]
            auction_results[0]["lotValues"][0]["value"]["amount"] = 29  # only 1 case
            auction_results[1]["lotValues"][0]["value"]["amount"] = 30  # both 1 and 2 case
            auction_results[2]["lotValues"][0]["value"]["amount"] = 350  # only 2 case
            auction_results[3]["lotValues"][0]["value"]["amount"] = 500  # no milestones
        else:
            lot_id = None
            auction_results[0]["value"]["amount"] = 29   # only 1 case
            auction_results[1]["value"]["amount"] = 30   # both 1 and 2 case
            auction_results[2]["value"]["amount"] = 350   # only 2 case
            auction_results[3]["value"]["amount"] = 500  # no milestones

        with change_auth(self.app, ("Basic", ("auction", ""))):
            url = "/tenders/{}/auction".format(self.tender_id)
            if lot_id:
                url += "/" + lot_id
            response = self.app.post_json(
                url,
                {"data": {"bids": auction_results}},
                status=200
            )
        tender = response.json["data"]
        self.assertEqual("active.qualification", tender["status"])
        self.assertGreater(len(tender["awards"]), 0)
        award = tender["awards"][0]
        bid_id = award["bid_id"]
        self.assertEqual(bid_id, auction_results[0]["id"])

        if get_now() < RELEASE_2020_04_19:
            return self.assertEqual(len(award.get("milestones", [])), 0)

        # check that a milestone's been created
        self.assertEqual(len(award.get("milestones", [])), 1)
        milestone = award["milestones"][0]
        self.assertEqual(milestone["code"], "alp")
        self.assertEqual(milestone["description"], ALP_MILESTONE_REASONS[0])

        # try to change award status
        unsuccessful_data = {"status": "unsuccessful"}
        response = self.app.patch_json(
            "/tenders/{}/awards/{}?acc_token={}".format(
                self.tender_id, award["id"], self.tender_token
            ),
            {"data": unsuccessful_data},
            status=403
        )
        expected_due_date = calculate_complaint_business_date(
            parse_date(milestone["date"]),
            timedelta(days=1),
            tender,
            working_days=True,
        )
        self.assertEqual(
            response.json,
            {
                u'status': u'error', u'errors': [{
                    u'description': u"Can't change status to 'unsuccessful' until milestone.dueDate: {}".format(
                        expected_due_date.isoformat()
                    ),
                    u'location': u'body', u'name': u'data'
                }]
            }
        )

        # try to post/put/patch docs
        for doc_type in ["evidence", None]:
            self._test_doc_upload(
                tender["procurementMethodType"], doc_type,
                bid_id, self.initial_bids_tokens[bid_id], expected_due_date
            )

        # setting "dueDate" to now
        self.wait_until_award_milestone_due_date(award_index=0)

        # after milestone dueDate tender owner can change award status
        response = self.app.patch_json(
            "/tenders/{}/awards/{}?acc_token={}".format(
                self.tender_id, award["id"], self.tender_token
            ),
            {"data": unsuccessful_data},
            status=200
        )
        self.assertEqual(response.json["data"]["status"], "unsuccessful")

        # check second award
        response = self.app.get(
            "/tenders/{}/awards?acc_token={}".format(self.tender_id, self.tender_token),
            status=200
        )
        self.assertGreater(len(response.json["data"]), 1)
        second_award = response.json["data"][1]
        self.assertEqual(len(second_award.get("milestones", [])), 1)
        self.assertEqual(second_award["milestones"][0]["description"], u" / ".join(ALP_MILESTONE_REASONS))

        # proceed to the third award
        self.wait_until_award_milestone_due_date(award_index=1)
        response = self.app.patch_json(
            "/tenders/{}/awards/{}?acc_token={}".format(
                self.tender_id, second_award["id"], self.tender_token
            ),
            {"data": unsuccessful_data},
            status=200
        )
        self.assertEqual(response.json["data"]["status"], "unsuccessful")
        # checking 3rd award
        response = self.app.get(
            "/tenders/{}/awards?acc_token={}".format(self.tender_id, self.tender_token),
            status=200
        )
        self.assertGreater(len(response.json["data"]), 2)
        third_award = response.json["data"][2]
        self.assertEqual(len(third_award.get("milestones", [])), 1)
        self.assertEqual(third_award["milestones"][0]["description"], ALP_MILESTONE_REASONS[1])

        # proceed to the last award
        self.wait_until_award_milestone_due_date(award_index=2)
        response = self.app.patch_json(
            "/tenders/{}/awards/{}?acc_token={}".format(
                self.tender_id, third_award["id"], self.tender_token
            ),
            {"data": unsuccessful_data},
            status=200
        )
        self.assertEqual(response.json["data"]["status"], "unsuccessful")
        # checking last award
        response = self.app.get(
            "/tenders/{}/awards?acc_token={}".format(self.tender_id, self.tender_token),
            status=200
        )
        self.assertGreater(len(response.json["data"]), 3)
        last_award = response.json["data"][3]
        self.assertNotIn("milestones", last_award)
test_tender_ua_data = deepcopy(tender_defense)
bid = deepcopy(bid)
bid2 = deepcopy(bid2)

bid.update(subcontracting)
bid.update(qualified)
bid2.update(qualified)
bid.update({"selfEligible": True})
bid2.update({"selfEligible": True})

TARGET_DIR = 'docs/source/tendering/defense/http/'


@mock.patch("openprocurement.tender.core.validation.RELEASE_SIMPLE_DEFENSE_FROM",
            parse_date(MOCK_DATETIME) + timedelta(days=365))
class TenderUAResourceTest(BaseTenderUAWebTest, MockWebTestMixin):
    AppClass = DumpsWebTestApp

    relative_to = os.path.dirname(__file__)
    initial_data = test_tender_ua_data
    docservice = True
    docservice_url = DOCS_URL
    auctions_url = AUCTIONS_URL

    def setUp(self):
        super(TenderUAResourceTest, self).setUp()
        self.setUpMock()

    def tearDown(self):
        self.tearDownMock()
def patch_tender(self):
    response = self.app.get("/tenders")
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(len(response.json["data"]), 0)

    response = self.app.post_json("/tenders", {"data": self.initial_data})
    self.assertEqual(response.status, "201 Created")
    tender = response.json["data"]
    self.tender_id = response.json["data"]["id"]
    owner_token = response.json["access"]["token"]
    dateModified = tender.pop("dateModified")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token), {"data": {"status": "cancelled"}}
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    self.assertNotEqual(response.json["data"]["status"], "cancelled")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token), {"data": {"procuringEntity": {"kind": "general"}}}
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    self.assertNotEqual(response.json["data"]["procuringEntity"]["kind"], "general")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {"data": {"tenderPeriod": {"startDate": tender["enquiryPeriod"]["endDate"]}}},
        status=422,
    )
    self.assertEqual(response.status, "422 Unprocessable Entity")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(
        response.json["errors"],
        [
            {
                "location": "body",
                "name": "tenderPeriod",
                "description": ["tenderPeriod must be at least 6 full business days long"],
            }
        ],
    )

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token), {"data": {"procurementMethodRationale": "Open"}}
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    self.assertIn("invalidationDate", response.json["data"]["enquiryPeriod"])
    new_tender = response.json["data"]
    new_enquiryPeriod = new_tender.pop("enquiryPeriod")
    new_dateModified = new_tender.pop("dateModified")
    tender.pop("enquiryPeriod")
    tender["procurementMethodRationale"] = "Open"
    self.assertEqual(tender, new_tender)
    self.assertNotEqual(dateModified, new_dateModified)

    revisions = self.db.get(tender["id"]).get("revisions")
    self.assertTrue(
        any(
            [
                i
                for i in revisions[-1]["changes"]
                if i["op"] == "remove" and i["path"] == "/procurementMethodRationale"
            ]
        )
    )

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token), {"data": {"dateModified": new_dateModified}}
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    new_tender2 = response.json["data"]
    new_enquiryPeriod2 = new_tender2.pop("enquiryPeriod")
    new_dateModified2 = new_tender2.pop("dateModified")
    self.assertEqual(new_tender, new_tender2)
    self.assertNotEqual(new_enquiryPeriod, new_enquiryPeriod2)
    self.assertNotEqual(new_dateModified, new_dateModified2)

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {"data": {"items": [self.initial_data["items"][0]]}},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {"data": {"items": [{}, self.initial_data["items"][0]]}},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    item0 = response.json["data"]["items"][0]
    item1 = response.json["data"]["items"][1]
    self.assertNotEqual(item0.pop("id"), item1.pop("id"))
    self.assertEqual(item0, item1)

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token), {"data": {"items": [{}]}}
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(len(response.json["data"]["items"]), 1)

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {"data": {"items": [{"classification": {"scheme": "ДК021", "id": "44620000-2", "description": "Cartons 2"}}]}},
        status=200,
    )

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {
            "data": {
                "items": [
                    {
                        "classification": {
                            "scheme": "ДК021",
                            "id": "55523100-3",
                            "description": "Послуги з харчування у школах",
                        }
                    }
                ]
            }
        },
        status=403,
    )
    self.assertEqual(response.status, "403 Forbidden")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(response.json["errors"][0]["description"], "Can't change classification")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {
            "data": {
                "items": [
                    {
                        "additionalClassifications": [
                            tender["items"][0]["additionalClassifications"][0] for i in range(3)
                        ]
                    }
                ]
            }
        },
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {"data": {"items": [{"additionalClassifications": tender["items"][0]["additionalClassifications"]}]}},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token),
        {"data": {"enquiryPeriod": {
            "startDate": calculate_tender_business_date(
                parse_date(new_dateModified2), -timedelta(3), None, True
            ).isoformat(),
            "endDate": new_dateModified2
        }}},
        status=403,
    )
    self.assertEqual(response.status, "403 Forbidden")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(response.json["errors"][0]["description"], "Can't change enquiryPeriod")

    self.set_status("complete")

    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(tender["id"], owner_token), {"data": {"status": "active.auction"}}, status=403
    )
    self.assertEqual(response.status, "403 Forbidden")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(response.json["errors"][0]["description"], "Can't update tender in current (complete) status")
Example #22
0
    def test_24hours_milestone(self):
        self.app.authorization = ("Basic", ("broker", ""))

        # try upload documents
        response = self.app.get("/tenders/{}".format(self.tender_id))
        context = response.json["data"]["{}s".format(self.context_name)][0]
        bid_id = context.get("bid_id") or context.get("bidID")  # awards and qualifications developed on different days
        winner_token = self.initial_bids_tokens[bid_id]
        upload_allowed_by_default = response.json["data"]["procurementMethodType"] in \
                                    ("aboveThresholdUA.defense", "simple.defense")
        self.assert_upload_docs_status(bid_id, winner_token, success=upload_allowed_by_default)

        # invalid creation
        response = self.app.post_json(
            "/tenders/{}/{}s/{}/milestones".format(self.tender_id, self.context_name, self.context_id),
            {
                "data": {}
            },
            status=403
        )
        self.assertEqual(
            response.json,
            {"status": "error", "errors": [{"location": "url", "name": "permission", "description": "Forbidden"}]}
        )
        response = self.app.post_json(
            "/tenders/{}/{}s/{}/milestones?acc_token={}".format(
                self.tender_id,
                self.context_name,
                self.context_id,
                self.tender_token
            ),
            {
                "data": {
                    "code": "alp"
                }
            },
            status=403
        )
        if get_now() > RELEASE_2020_04_19:
            self.assertEqual(
                response.json,
                {"status": "error", "errors": [{"description": "The only allowed milestone code is '24h'",
                                                "location": "body", "name": "data"}]}
            )
        else:
            self.assertEqual(
                response.json,
                {"status": "error", "errors": [{"location": "body", "name": "data", "description": "Forbidden"}]}
            )
            return

        # valid creation
        request_data = {
            "code": "24h",
            "description": "One ring to bring them all and in the darkness bind them",
            "dueDate": (get_now() + timedelta(days=10)).isoformat()
        }
        response = self.app.post_json(
            "/tenders/{}/{}s/{}/milestones?acc_token={}".format(
                self.tender_id, self.context_name, self.context_id, self.tender_token
            ),
            {"data": request_data},
        )
        self.assertEqual(response.status, "201 Created")
        created_milestone = response.json["data"]

        # get milestone from tender
        response = self.app.get("/tenders/{}".format(self.tender_id))
        tender_data = response.json["data"]
        context = tender_data["{}s".format(self.context_name)][0]
        public_milestone = context["milestones"][0]

        self.assertEqual(created_milestone, public_milestone)
        self.assertEqual(
            set(created_milestone.keys()),
            {
                "id",
                "date",
                "code",
                "description",
                "dueDate",
            }
        )
        self.assertEqual(created_milestone["code"], request_data["code"])
        self.assertEqual(created_milestone["description"], request_data["description"])
        self.assertNotEqual(created_milestone["dueDate"], request_data["dueDate"])
        expected_date = calculate_tender_date(
            parse_date(created_milestone["date"]),
            timedelta(hours=24),
            tender_data
        )
        self.assertEqual(created_milestone["dueDate"], expected_date.isoformat())

        # get milestone by its direct link
        response = self.app.get("/tenders/{}/{}s/{}/milestones/{}".format(
            self.tender_id, self.context_name, self.context_id, created_milestone["id"]
        ))
        direct_milestone = response.json["data"]
        self.assertEqual(created_milestone, direct_milestone)

        # can't post another
        response = self.app.post_json(
            "/tenders/{}/{}s/{}/milestones?acc_token={}".format(
                self.tender_id, self.context_name, self.context_id, self.tender_token
            ),
            {"data": request_data},
            status=422
        )
        self.assertEqual(
            response.json,
            {"status": "error", "errors": [{"description": [
                {"milestones": ["There can be only one '24h' milestone"]}],
                 "location": "body", "name": "{}s".format(self.context_name)}]}
        )

        # can't update status of context until dueDate
        activation_data = {"status": "active", "qualified": True, "eligible": True}
        response = self.app.patch_json(
            "/tenders/{}/{}s/{}?acc_token={}".format(
                self.tender_id, self.context_name, self.context_id, self.tender_token
            ),
            {"data": activation_data},
            status=403
        )
        self.assertEqual(
            response.json,
            {
                "status": "error", "errors": [
                    {
                        "description": "Can't change status to 'active' "
                                       "until milestone.dueDate: {}".format(created_milestone["dueDate"]),
                        "location": "body", "name": "data"
                    }]
            }
        )

        # try upload documents
        self.assert_upload_docs_status(bid_id, winner_token)

        # wait until milestone dueDate ends
        with patch("openprocurement.tender.core.validation.get_now", lambda: get_now() + timedelta(hours=24)):
            self.assert_upload_docs_status(bid_id, winner_token, success=upload_allowed_by_default)

            response = self.app.patch_json(
                "/tenders/{}/{}s/{}?acc_token={}".format(
                    self.tender_id, self.context_name, self.context_id, self.tender_token
                ),
                {"data": activation_data},
                status=200
            )
            self.assertEqual(response.json["data"]["status"], "active")

        # check appending milestone at active qualification status
        # remove milestone to skip "only one" validator
        tender = self.db.get(self.tender_id)
        context = tender["{}s".format(self.context_name)][0]
        context["milestones"] = []
        self.db.save(tender)

        response = self.app.post_json(
            "/tenders/{}/{}s/{}/milestones?acc_token={}".format(
                self.tender_id, self.context_name, self.context_id, self.tender_token
            ),
            {"data": request_data},
            status=403
        )
        self.assertEqual(
            response.json,
            {"status": "error", "errors": [
                {"description": "Not allowed in current 'active' {} status".format(self.context_name),
                 "location": "body", "name": "data"}]}
        )
def reset_auction_period(self):
    def check_chronograph(auction_period_data=None):
        if self.initial_lots:
            data = {
                "data": {
                    "lots": [{
                        "auctionPeriod": auction_period_data
                    }]
                }
            } if auction_period_data else None
            ch_response = self.check_chronograph(data)
            ch_response_item = ch_response.json["data"]["lots"][0]
        else:
            data = {
                "data": {
                    "auctionPeriod": auction_period_data
                }
            } if auction_period_data else None
            ch_response = self.check_chronograph(data)
            ch_response_item = ch_response.json["data"]
        return ch_response, ch_response_item

    self.set_status("active.tendering", {"status": "active.enquiries"})

    response, item = check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.tendering")
    self.assertIn("auctionPeriod", item)
    self.assertIn("shouldStartAfter", item["auctionPeriod"])
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertEqual(
        parse_date(response.json["data"]["next_check"]),
        parse_date(response.json["data"]["tenderPeriod"]["endDate"]))

    response, item = check_chronograph(
        auction_period_data={"startDate": "9999-01-01T00:00:00"})
    self.assertEqual(response.status, "200 OK")
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertIn("9999-01-01T00:00:00", item["auctionPeriod"]["startDate"])

    self.set_status("active.auction", {"status": "active.tendering"})
    response = self.check_chronograph()
    self.assertEqual(response.json["data"]["status"], "active.auction")
    item = response.json["data"]["lots"][
        0] if self.initial_lots else response.json["data"]
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])

    response, item = check_chronograph(
        auction_period_data={"startDate": "9999-01-01T00:00:00"})
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.json["data"]["status"], "active.auction")
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertIn("9999-01-01T00:00:00", item["auctionPeriod"]["startDate"])
    self.assertIn("9999-01-01T00:00:00", response.json["data"]["next_check"])

    now = get_now()
    response, item = check_chronograph(
        auction_period_data={"startDate": now.isoformat()})
    self.assertEqual(response.json["data"]["status"], "active.auction")
    item = response.json["data"]["lots"][
        0] if self.initial_lots else response.json["data"]
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertIn(now.isoformat(), item["auctionPeriod"]["startDate"])
    self.assertGreater(parse_date(response.json["data"]["next_check"]),
                       parse_date(item["auctionPeriod"]["startDate"]))
    self.assertEqual(response.json["data"]["next_check"],
                     self.db.get(self.tender_id)["next_check"])

    tender_period_end_date = response.json["data"]["tenderPeriod"]["endDate"]
    response, item = check_chronograph(
        auction_period_data={"startDate": tender_period_end_date})
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.json["data"]["status"], "active.auction")
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertIn(tender_period_end_date, item["auctionPeriod"]["startDate"])
    self.assertGreater(
        parse_date(response.json["data"]["next_check"]),
        parse_date(response.json["data"]["tenderPeriod"]["endDate"]))

    self.assertGreater(
        self.db.get(self.tender_id)["next_check"],
        response.json["data"]["tenderPeriod"]["endDate"])

    self.time_shift("active.auction", shift=-timedelta(days=2))

    response, item = check_chronograph()
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertNotIn("next_check", response.json["data"])
    self.assertNotIn("next_check", self.db.get(self.tender_id))
    shouldStartAfter = item["auctionPeriod"]["shouldStartAfter"]

    response, item = check_chronograph()
    self.assertEqual(item["auctionPeriod"]["shouldStartAfter"],
                     shouldStartAfter)
    self.assertNotIn("next_check", response.json["data"])

    response, item = check_chronograph(
        auction_period_data={"startDate": "9999-01-01T00:00:00"})
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.json["data"]["status"], "active.auction")
    self.assertGreaterEqual(item["auctionPeriod"]["shouldStartAfter"],
                            response.json["data"]["tenderPeriod"]["endDate"])
    self.assertIn("9999-01-01T00:00:00", item["auctionPeriod"]["startDate"])
    self.assertIn("9999-01-01T00:00:00", response.json["data"]["next_check"])
    def test_docs(self):
        self.app.authorization = ('Basic', ('broker', ''))
        # empty frameworks listing
        self.initial_data["qualificationPeriod"]["endDate"] = (
            get_now() + timedelta(days=60)).isoformat()
        response = self.app.get('/frameworks')
        self.assertEqual(response.json['data'], [])

        # create frameworks
        with open(TARGET_DIR + 'create-electroniccatalogue.http',
                  'w') as self.app.file_obj:
            response = self.app.post_json('/frameworks',
                                          {'data': self.initial_data})
            self.assertEqual(response.status, '201 Created')

        framework = response.json['data']
        self.framework_id = framework["id"]
        owner_token = response.json['access']['token']

        with open(TARGET_DIR + 'patch-electroniccatalogue-draft.http',
                  'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/frameworks/{}?acc_token={}'.format(framework['id'],
                                                     owner_token),
                {
                    'data': {
                        "procuringEntity": {
                            "contactPoint": {
                                "telephone": "+0440000001"
                            }
                        },
                        "title": "updated in draft status"
                    }
                })
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'upload-framework-document.http',
                  'w') as self.app.file_obj:
            response = self.app.post(
                '/frameworks/{}/documents?acc_token={}'.format(
                    framework['id'], owner_token),
                upload_files=[('file', 'framework.doc', b'content')])

        with open(TARGET_DIR + 'framework-documents.http',
                  'w') as self.app.file_obj:
            response = self.app.get(
                '/frameworks/{}/documents?acc_token={}'.format(
                    framework['id'], owner_token))

        with open(TARGET_DIR + 'upload-framework-document-2.http',
                  'w') as self.app.file_obj:
            response = self.app.post(
                '/frameworks/{}/documents?acc_token={}'.format(
                    framework['id'], owner_token),
                upload_files=[('file', 'framework_additional_docs.doc',
                               b'additional info')])

        doc_id = response.json['data']['id']

        with open(TARGET_DIR + 'upload-framework-document-3.http',
                  'w') as self.app.file_obj:
            response = self.app.put(
                '/frameworks/{}/documents/{}?acc_token={}'.format(
                    framework['id'], doc_id, owner_token),
                upload_files=[('file', 'framework_additional_docs.doc',
                               b'extended additional info')])

        with open(TARGET_DIR + 'get-framework-document-3.http',
                  'w') as self.app.file_obj:
            response = self.app.get(
                '/frameworks/{}/documents/{}?acc_token={}'.format(
                    framework['id'], doc_id, owner_token))

        with open(
                TARGET_DIR + 'patch-electroniccatalogue-draft-to-active.http',
                'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/frameworks/{}?acc_token={}'.format(framework['id'],
                                                     owner_token),
                {'data': {
                    "status": "active"
                }})
            self.assertEqual(response.status, '200 OK')

        # Submissions
        self.tick(delta=timedelta(days=16))
        with open(TARGET_DIR + 'register-submission.http',
                  'w') as self.app.file_obj:
            response = self.app.post_json(
                '/submissions', {
                    'data': {
                        "tenderers": [tenderer],
                        "frameworkID": self.framework_id,
                    }
                })
            self.assertEqual(response.status, '201 Created')

        self.submission_id = response.json["data"]["id"]
        self.submission_token = response.json["access"]["token"]

        with open(TARGET_DIR + 'upload-submission-document.http',
                  'w') as self.app.file_obj:
            response = self.app.post(
                '/submissions/{}/documents?acc_token={}'.format(
                    self.submission_id, self.submission_token),
                upload_files=[('file', 'submission_docs.doc',
                               b'additional info')])
            self.assertEqual(response.status, '201 Created')

        with open(TARGET_DIR + 'get-submission-documents.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/submissions/{}/documents'.format(
                self.submission_id))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'get-submission.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/submissions/{}'.format(
                self.submission_id))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'updating-submission.http',
                  'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/submissions/{}?acc_token={}'.format(self.submission_id,
                                                      self.submission_token),
                {'data': {
                    "tenderers": [{
                        "name": "НАЗВА"
                    }]
                }},
            )
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'deleting-submission.http',
                  'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/submissions/{}?acc_token={}'.format(self.submission_id,
                                                      self.submission_token),
                {'data': {
                    "status": "deleted"
                }},
            )
            self.assertEqual(response.status, '200 OK')

        response = self.app.post_json(
            '/submissions'.format(self.submission_id, self.submission_token), {
                'data': {
                    "tenderers": [tenderer],
                    "frameworkID": self.framework_id,
                }
            })
        self.submission_id = response.json["data"]["id"]
        self.submission_token = response.json["access"]["token"]

        with open(TARGET_DIR + 'activating-submission.http',
                  'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/submissions/{}?acc_token={}'.format(self.submission_id,
                                                      self.submission_token),
                {'data': {
                    "status": "active"
                }},
            )
            self.assertEqual(response.status, '200 OK')

        self.qualification_id = response.json["data"]["qualificationID"]

        with open(TARGET_DIR + 'submission-listing.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/submissions'.format(self.framework_id))
            self.assertEqual(response.status, '200 OK')

        # Qualification

        with open(TARGET_DIR + 'get-qualification.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/qualifications/{}'.format(
                self.qualification_id))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'upload-qualification-document.http',
                  'w') as self.app.file_obj:
            response = self.app.post(
                '/qualifications/{}/documents?acc_token={}'.format(
                    self.qualification_id, owner_token),
                upload_files=[('file', 'qualification.doc', b'content')])
            self.assertEqual(response.status, '201 Created')

        with open(TARGET_DIR + 'qualification-documents.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/qualifications/{}/documents'.format(
                self.qualification_id, owner_token))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'get-qualification-documents.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/qualifications/{}/documents'.format(
                self.qualification_id))
            self.assertEqual(response.status, '200 OK')

        # with open(TARGET_DIR + 'get-qualification.http', 'w') as self.app.file_obj:
        #     response = self.app.get('/qualifications/{}'.format(self.qualification_id))
        #     self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'unsuccessful-qualification.http',
                  'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/qualifications/{}?acc_token={}'.format(
                    self.qualification_id, owner_token),
                {'data': {
                    "status": "unsuccessful"
                }},
            )
            self.assertEqual(response.status, '200 OK')

        response = self.app.post_json(
            '/submissions'.format(self.submission_id, self.submission_token), {
                'data': {
                    "tenderers": [tenderer],
                    "frameworkID": self.framework_id,
                }
            })
        self.submission_id = response.json["data"]["id"]
        self.submission_token = response.json["access"]["token"]

        response = self.app.patch_json(
            '/submissions/{}?acc_token={}'.format(self.submission_id,
                                                  self.submission_token),
            {'data': {
                "status": "active"
            }},
        )
        self.qualification_id = response.json["data"]["qualificationID"]

        with open(TARGET_DIR + 'activation-qualification.http',
                  'w') as self.app.file_obj:
            response = self.app.patch_json(
                '/qualifications/{}?acc_token={}'.format(
                    self.qualification_id, owner_token),
                {'data': {
                    "status": "active"
                }},
            )
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'get-framework-with-agreement.http',
                  'w') as self.app.file_obj:
            response = self.app.get(f'/frameworks/{self.framework_id}')
            self.assertEqual(response.status, '200 OK')
            agreement_id = response.json["data"]["agreementID"]

        with open(TARGET_DIR + 'get-agreement.http', 'w') as self.app.file_obj:
            response = self.app.get(f'/agreements/{agreement_id}')
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'agreement-listing.http',
                  'w') as self.app.file_obj:
            response = self.app.get(f'/agreements')
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'get-submissions-by-framework-id.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/frameworks/{}/submissions'.format(
                self.framework_id, self.submission_id))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'get-qualifications-by-framework-id.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/frameworks/{}/qualifications'.format(
                self.framework_id))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'qualification-listing.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/qualifications'.format(
                self.framework_id))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'get-framework.http', 'w') as self.app.file_obj:
            response = self.app.get('/frameworks/{}'.format(framework['id']))
            self.assertEqual(response.status, '200 OK')

        with open(TARGET_DIR + 'framework-listing.http',
                  'w') as self.app.file_obj:
            response = self.app.get('/frameworks'.format(framework['id']))
            self.assertEqual(len(response.json['data']), 1)

        with open(TARGET_DIR + 'patch-electroniccatalogue-active.http',
                  'w') as self.app.file_obj:
            new_endDate = (
                parse_date(framework["qualificationPeriod"]["endDate"]) +
                timedelta(days=15)).isoformat()
            response = self.app.patch_json(
                '/frameworks/{}?acc_token={}'.format(framework['id'],
                                                     owner_token),
                {
                    'data': {
                        "procuringEntity": {
                            "contactPoint": {
                                "telephone": "+0440000002",
                                "name": "зміна",
                                "email": "*****@*****.**"
                            }
                        },
                        "description": "Назва предмета закупівлі1",
                        "qualificationPeriod": {
                            "endDate": new_endDate
                        }
                    }
                })
            self.assertEqual(response.status, '200 OK')
Example #25
0
def switch_bid_status_unsuccessul_to_active(self):
    bid_id, bid_token = self.initial_bids_tokens.items()[0]

    response = self.app.get("/tenders/{}/qualifications?acc_token={}".format(self.tender_id, self.tender_token))
    self.assertEqual(response.content_type, "application/json")
    qualifications = response.json["data"]
    self.assertEqual(len(qualifications), 3)
    qualification_id = ""
    for qualification in qualifications:
        status = "active"
        if qualification["bidID"] == bid_id:
            status = "unsuccessful"
            qualification_id = qualification["id"]
        response = self.app.patch_json(
            "/tenders/{}/qualifications/{}?acc_token={}".format(self.tender_id, qualification["id"], self.tender_token),
            {"data": {"status": status, "qualified": True, "eligible": True}},
        )
        self.assertEqual(response.status, "200 OK")
        self.assertEqual(response.json["data"]["status"], status)
    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(self.tender_id, self.tender_token),
        {"data": {"status": "active.pre-qualification.stand-still"}},
    )
    self.assertEqual(response.status, "200 OK")
    end_date = parse_date(response.json["data"]["qualificationPeriod"]["endDate"])
    date = parse_date(response.json["data"]["date"])
    duration = (end_date - date).total_seconds()
    if SANDBOX_MODE:
        duration = ceil(duration) * 1440
    duration = duration / 86400  # days float
    self.assertEqual(int(duration), 5)

    # create complaint
    response = self.app.post_json(
        "/tenders/{}/qualifications/{}/complaints?acc_token={}".format(self.tender_id, qualification_id, bid_token),
        {
            "data": test_complaint
        },
    )
    self.assertEqual(response.status, "201 Created")
    self.assertEqual(response.content_type, "application/json")
    complaint = response.json["data"]
    complaint_token = response.json["access"]["token"]

    if RELEASE_2020_04_19 < get_now():
        self.assertEqual(response.json["data"]["status"], "draft")
        with change_auth(self.app, ("Basic", ("bot", ""))):
            response = self.app.patch_json(
                 "/tenders/{}/qualifications/{}/complaints/{}".format(
                     self.tender_id, qualification_id, complaint["id"]),
                {"data": {"status": "pending"}},
            )
        self.assertEqual(response.status, "200 OK")
        self.assertEqual(response.content_type, "application/json")
        self.assertEqual(response.json["data"]["status"], "pending")

    self.app.authorization = ("Basic", ("reviewer", ""))
    now = get_now()
    data = {"status": "accepted"}
    if RELEASE_2020_04_19 < now:
        data.update({
            "reviewDate": now.isoformat(),
            "reviewPlace": "some",
        })
    response = self.app.patch_json(
        "/tenders/{}/qualifications/{}/complaints/{}".format(self.tender_id, qualification_id, complaint["id"]),
        {"data": data},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(response.json["data"]["status"], "accepted")
    if RELEASE_2020_04_19 < now:
        self.assertEqual(response.json["data"]["reviewPlace"], "some")
        self.assertEqual(response.json["data"]["reviewDate"], now.isoformat())

    response = self.app.patch_json(
        "/tenders/{}/qualifications/{}/complaints/{}".format(self.tender_id, qualification_id, complaint["id"]),
        {"data": {"status": "satisfied"}},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.content_type, "application/json")
    self.assertEqual(response.json["data"]["status"], "satisfied")

    # Cancell qualification
    self.app.authorization = ("Basic", ("broker", ""))
    response = self.app.patch_json(
        "/tenders/{}/qualifications/{}?acc_token={}".format(self.tender_id, qualification_id, self.tender_token),
        {"data": {"status": "cancelled"}},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.json["data"]["status"], "cancelled")

    new_qualification_id = response.headers["location"].split("/")[-1]
    response = self.app.patch_json(
        "/tenders/{}/qualifications/{}?acc_token={}".format(self.tender_id, new_qualification_id, self.tender_token),
        {"data": {"status": "active", "qualified": True, "eligible": True}},
    )
    self.assertEqual(response.status, "200 OK")
    self.assertEqual(response.json["data"]["status"], "active")

    response = self.app.get("/tenders/{}/bids".format(self.tender_id))
    for b in response.json["data"]:
        self.assertEqual(b["status"], "active")
Example #26
0
def switch_qualification_complaints_draft(self):
    # generate qualifications
    self.set_status("active.pre-qualification",
                    extra={"status": "active.tendering"})
    response = self.check_chronograph()
    qualifications = response.json["data"]["qualifications"]
    self.assertEqual(len(qualifications), 2)

    # activate qualifications
    for qualification in qualifications:
        response = self.app.patch_json(
            "/tenders/{}/qualifications/{}?acc_token={}".format(
                self.tender_id, qualification["id"], self.tender_token),
            {
                "data": {
                    "status": "active",
                    "qualified": True,
                    "eligible": True
                }
            },
        )
        self.assertEqual(response.status, "200 OK")
        self.assertEqual(response.json["data"]["status"], "active")
    response = self.app.patch_json(
        "/tenders/{}?acc_token={}".format(self.tender_id, self.tender_token),
        {"data": {
            "status": "active.pre-qualification.stand-still"
        }},
    )
    self.assertEqual(response.status, "200 OK")
    tender = response.json["data"]
    qualification = tender["qualifications"][0]

    # let's post a draft complaint
    token = list(self.initial_bids_tokens.values())[0]
    response = self.app.post_json(
        "/tenders/{}/qualifications/{}/complaints?acc_token={}".format(
            self.tender_id, qualification["id"], token),
        {"data": test_draft_complaint},
    )
    self.assertEqual(response.json["data"]["status"], "draft")

    # get tender and check next_check
    response = self.app.get("/tenders/{}".format(self.tender_id))
    self.assertEqual(parse_date(response.json["data"].get("next_check")),
                     parse_date(tender["qualificationPeriod"]["endDate"]))

    # and once the date passed
    tender = self.db.get(self.tender_id)
    tender["qualificationPeriod"] = dict(
        startDate=(get_now() - timedelta(days=20)).isoformat(),
        endDate=(get_now() - timedelta(days=10)).isoformat())
    self.db.save(tender)

    # switch
    response = self.check_chronograph()
    data = response.json["data"]
    complaint = data["qualifications"][0]["complaints"][0]
    self.assertEqual(complaint["status"], "mistaken")
    self.assertEqual(complaint["rejectReason"], "complaintPeriodEnded")
    self.assertNotEqual(data.get("next_check"),
                        tender["qualificationPeriod"]["endDate"])