예제 #1
0
    def patch_as_tender_owner(self, data):
        data = self.request.validated["data"]
        status = self.context.status
        new_status = data.get("status", status)

        tender = self.request.validated["tender"]

        new_rules = get_first_revision_date(tender) > RELEASE_2020_04_19

        if self.request.authenticated_role == "tender_owner" and status in [
                "pending", "accepted"
        ]:
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (status in ["claim", "satisfied"] and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (status == "claim"
              and data.get("resolution", self.context.resolution)
              and data.get("resolutionType", self.context.resolutionType)
              and new_status == "answered"):
            if len(data.get("resolution", self.context.resolution)) < 20:
                raise_operation_error(
                    self.request,
                    "Can't update complaint: resolution too short")
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateAnswered = get_now()
        elif (status == "satisfied"
              and data.get("tendererAction", self.context.tendererAction)
              and new_status == "resolved"):
            apply_patch(self.request, save=False, src=self.context.serialize())
        else:
            raise_operation_error(
                self.request,
                "Can't update complaint from {} to {} status".format(
                    status, new_status))
예제 #2
0
    def patch_as_complaint_owner(self, data):
        context = self.context
        status = self.context.status
        new_status = data.get("status", status)

        tender = self.request.validated["tender"]

        if status in ["draft", "claim", "answered"
                      ] and new_status == "cancelled":
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateCanceled = get_now()
        elif (get_first_revision_date(tender, get_now()) > RELEASE_2020_04_19
              and new_status == "mistaken"):
            context.rejectReason = "cancelledByComplainant"
            apply_patch(self.request, save=False, src=context.serialize())
        elif (tender.status in ["active.enquiries", "active.tendering"]
              and status == "draft" and new_status == status):
            apply_patch(self.request, save=False, src=context.serialize())
        elif (tender.status in ["active.enquiries", "active.tendering"]
              and status == "draft" and new_status == "claim"):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateSubmitted = get_now()
        elif status == "answered" and new_status == status:
            apply_patch(self.request, save=False, src=context.serialize())
        elif (status == "answered"
              and isinstance(data.get("satisfied", context.satisfied), bool)
              and new_status == "resolved"):
            apply_patch(self.request, save=False, src=context.serialize())
예제 #3
0
파일: utils.py 프로젝트: lttga/op2
def check_bids(request):
    tender = request.validated["tender"]
    new_rules = get_first_revision_date(tender,
                                        default=get_now()) > RELEASE_2020_04_19

    if tender.lots:
        [
            setattr(i.auctionPeriod, "startDate", None) for i in tender.lots
            if i.numberOfBids < 2 and i.auctionPeriod
            and i.auctionPeriod.startDate
        ]
        [
            setattr(i, "status", "unsuccessful") for i in tender.lots
            if i.numberOfBids == 0 and i.status == "active"
        ]
        cleanup_bids_for_cancelled_lots(tender)
        if not set([i.status for i in tender.lots]).difference(
                set(["unsuccessful", "cancelled"])):
            tender.status = "unsuccessful"
        elif max([i.numberOfBids
                  for i in tender.lots if i.status == "active"]) < 2:
            add_next_award(request)
    else:
        if new_rules and any([
                i.status not in ["active", "unsuccessful"]
                for i in tender.cancellations
        ]):
            return
        if tender.numberOfBids < 2 and tender.auctionPeriod and tender.auctionPeriod.startDate:
            tender.auctionPeriod.startDate = None
        if tender.numberOfBids == 0:
            tender.status = "unsuccessful"
        if tender.numberOfBids == 1:
            add_next_award(request)
예제 #4
0
    def patch_as_abovethresholdreviewers(self, data):
        context = self.context
        status = context.status
        new_status = data.get("status", status)

        tender = self.request.validated["tender"]
        apply_rules_2020_04_19 = get_first_revision_date(tender) > RELEASE_2020_04_19

        if (
            status in ["pending", "accepted", "stopping"]
            and new_status == status
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (
            status in ["pending", "stopping"]
            and (
                (not apply_rules_2020_04_19 and new_status in ["invalid", "mistaken"])
                or (new_status == "invalid")
            )
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
            self.context.acceptance = False
        elif (
            status == "pending"
            and new_status == "accepted"
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateAccepted = get_now()
            self.context.acceptance = True
        elif (
            status in ["accepted", "stopping"]
            and new_status == "declined"
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
        elif (
            status in ["accepted", "stopping"]
            and new_status == "satisfied"
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
            tender.status = "active.pre-qualification"
            if tender.qualificationPeriod.endDate:
                tender.qualificationPeriod.endDate = None
        elif (
            ((not apply_rules_2020_04_19 and status in ["pending", "accepted", "stopping"])
             or (apply_rules_2020_04_19 and status == "accepted"))
            and new_status == "stopped"
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
            self.context.dateCanceled = self.context.dateCanceled or get_now()
        else:
            raise_operation_error(
                self.request,
                "Can't update complaint from {} to {} status".format(status, new_status)
            )
예제 #5
0
    def patch_as_complaint_owner(self, data):
        data = self.request.validated["data"]
        status = self.context.status
        new_status = data.get("status", status)

        tender = self.request.validated["tender"]

        is_qualificationPeriod = tender.qualificationPeriod.startDate < get_now(
        ) and (not tender.qualificationPeriod.endDate
               or tender.qualificationPeriod.endDate > get_now())

        apply_rules_2020_04_19 = get_first_revision_date(
            tender) > RELEASE_2020_04_19

        if (status in ["draft", "claim", "answered"]
                and new_status == "cancelled"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif (apply_rules_2020_04_19 and status == "draft"
              and self.context.type == "complaint"
              and new_status == "mistaken"):
            self.context.rejectReason = "cancelledByComplainant"
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (status in ["pending", "accepted"] and new_status == "stopping"
              and not apply_rules_2020_04_19):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif (is_qualificationPeriod and status == "draft"
              and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (is_qualificationPeriod and status == "draft"
              and new_status == "claim"):
            if (self.request.validated["qualification"].status
                    == "unsuccessful"
                    and self.request.validated["qualification"].bidID !=
                    self.context.bid_id):
                raise_operation_error(
                    self.request,
                    "Can add claim only on unsuccessful qualification of your bid"
                )
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateSubmitted = get_now()
        elif (is_qualificationPeriod and status == "draft"
              and new_status == "pending" and not apply_rules_2020_04_19):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.type = "complaint"
            self.context.dateSubmitted = get_now()
        elif (status == "answered" and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        else:
            raise_operation_error(
                self.request,
                "Can't update complaint from {} to {} status".format(
                    status, new_status))
예제 #6
0
    def collection_post(self):
        """Post a complaint
        """
        tender = self.request.validated["tender"]
        complaint = self.request.validated["complaint"]
        complaint.relatedLot = self.context.lotID
        complaint.date = get_now()
        complaint.bid_id = get_bid_id(self.request)

        old_rules = get_first_revision_date(tender) < RELEASE_2020_04_19

        if complaint.status == "claim":
            complaint.dateSubmitted = get_now()
        elif old_rules and complaint.status == "pending":
            complaint.type = "complaint"
            complaint.dateSubmitted = get_now()
        else:
            complaint.status = "draft"
        if (self.context.status == "unsuccessful"
                and complaint.status == "claim"
                and self.context.bidID != complaint.bid_id):
            raise_operation_error(
                self.request,
                "Can add claim only on unsuccessful qualification of your bid")
        complaint.complaintID = "{}.{}{}".format(
            tender.tenderID, self.server_id,
            self.complaints_len(tender) + 1)
        access = set_ownership(complaint, self.request)
        self.context.complaints.append(complaint)
        if save_tender(self.request):
            self.LOGGER.info(
                "Created tender qualification complaint {}".format(
                    complaint.id),
                extra=context_unpack(
                    self.request,
                    {"MESSAGE_ID": "tender_qualification_complaint_create"},
                    {"complaint_id": complaint.id},
                ),
            )
            self.request.response.status = 201
            self.request.response.headers["Location"] = self.request.route_url(
                "{}:Tender Qualification Complaints".format(
                    tender.procurementMethodType),
                tender_id=tender.id,
                qualification_id=self.request.validated["qualification_id"],
                complaint_id=complaint["id"],
            )
            return {"data": complaint.serialize("view"), "access": access}
예제 #7
0
    def pre_create(self):
        tender = self.request.validated["tender"]
        old_rules = get_first_revision_date(tender) < RELEASE_2020_04_19

        complaint = self.request.validated["complaint"]
        complaint.date = get_now()
        complaint.relatedLot = self.context.lotID
        complaint.bid_id = get_bid_id(self.request)

        if complaint.status == "claim":
            self.validate_posting_claim()
            complaint.dateSubmitted = get_now()
        elif old_rules and complaint.status == "pending":
            complaint.type = "complaint"
            complaint.dateSubmitted = get_now()
        else:
            complaint.status = "draft"

        return complaint
예제 #8
0
    def patch(self):
        """Update of lot
        """
        tender = self.request.validated["tender"]
        lot = self.request.context
        old_rules = get_first_revision_date(
            tender, default=get_now()) < RELEASE_2020_04_19

        if old_rules and [
                cancellation for cancellation in tender.get("cancellations")
                if cancellation.get("relatedLot") == lot["id"]
        ]:
            raise_operation_error(
                self.request, "Can't update lot that have active cancellation")
        if apply_patch(self.request, src=self.request.context.serialize()):
            self.LOGGER.info(
                "Updated tender lot {}".format(self.request.context.id),
                extra=context_unpack(self.request,
                                     {"MESSAGE_ID": "tender_lot_patch"}),
            )
            return {"data": self.request.context.serialize("view")}
예제 #9
0
def check_tender_status(request):
    tender = request.validated["tender"]
    now = get_now()

    if tender.lots:
        if any([
                i.status in tender.block_complaint_status
                and i.relatedLot is None for i in tender.complaints
        ]):
            return
        for lot in tender.lots:
            if lot.status != "active":
                continue
            lot_awards = [i for i in tender.awards if i.lotID == lot.id]
            if not lot_awards:
                continue
            last_award = lot_awards[-1]
            pending_complaints = any([
                i["status"] in tender.block_complaint_status
                and i.relatedLot == lot.id for i in tender.complaints
            ])
            pending_awards_complaints = any([
                i.status in tender.block_complaint_status for a in lot_awards
                for i in a.complaints
            ])
            first_revision_date = get_first_revision_date(tender)
            new_defence_complaints = NEW_DEFENSE_COMPLAINTS_FROM < first_revision_date < NEW_DEFENSE_COMPLAINTS_TO
            stand_still_ends = [
                a.complaintPeriod.endDate for a in lot_awards
                if (a.complaintPeriod and a.complaintPeriod.endDate and (
                    a.status != "cancelled" if new_defence_complaints else True
                ))
            ]
            stand_still_end = max(
                stand_still_ends) if stand_still_ends else now
            in_stand_still = now < stand_still_end
            skip_award_complaint_period = check_skip_award_complaint_period(
                tender)
            if (pending_complaints or pending_awards_complaints
                    or (in_stand_still and not skip_award_complaint_period)):
                continue
            elif last_award.status == "unsuccessful":
                LOGGER.info(
                    "Switched lot {} of tender {} to {}".format(
                        lot.id, tender.id, "unsuccessful"),
                    extra=context_unpack(
                        request, {"MESSAGE_ID": "switched_lot_unsuccessful"},
                        {"LOT_ID": lot.id}),
                )
                lot.status = "unsuccessful"
                continue
            elif last_award.status == "active":
                active_contracts = ([
                    a.status == "active" for a in tender.agreements
                ] if "agreements" in tender else [
                    i.status == "active" and i.awardID == last_award.id
                    for i in tender.contracts
                ])

                if any(active_contracts):
                    LOGGER.info(
                        "Switched lot {} of tender {} to {}".format(
                            lot.id, tender.id, "complete"),
                        extra=context_unpack(
                            request, {"MESSAGE_ID": "switched_lot_complete"},
                            {"LOT_ID": lot.id}),
                    )
                    lot.status = "complete"

        statuses = set([lot.status for lot in tender.lots])
        if statuses == set(["cancelled"]):
            LOGGER.info(
                "Switched tender {} to {}".format(tender.id, "cancelled"),
                extra=context_unpack(
                    request, {"MESSAGE_ID": "switched_tender_cancelled"}),
            )
            tender.status = "cancelled"
        elif not statuses.difference(set(["unsuccessful", "cancelled"])):
            LOGGER.info(
                "Switched tender {} to {}".format(tender.id, "unsuccessful"),
                extra=context_unpack(
                    request, {"MESSAGE_ID": "switched_tender_unsuccessful"}),
            )
            tender.status = "unsuccessful"
        elif not statuses.difference(
                set(["complete", "unsuccessful", "cancelled"])):
            LOGGER.info(
                "Switched tender {} to {}".format(tender.id, "complete"),
                extra=context_unpack(
                    request, {"MESSAGE_ID": "switched_tender_complete"}),
            )
            tender.status = "complete"
    else:
        pending_complaints = any([
            i.status in tender.block_complaint_status
            for i in tender.complaints
        ])
        pending_awards_complaints = any([
            i.status in tender.block_complaint_status for a in tender.awards
            for i in a.complaints
        ])
        first_revision_date = get_first_revision_date(tender)
        new_defence_complaints = NEW_DEFENSE_COMPLAINTS_FROM < first_revision_date < NEW_DEFENSE_COMPLAINTS_TO
        stand_still_ends = [
            a.complaintPeriod.endDate for a in tender.awards
            if (a.complaintPeriod and a.complaintPeriod.endDate and (
                a.status != "cancelled" if new_defence_complaints else True))
        ]
        stand_still_end = max(stand_still_ends) if stand_still_ends else now
        stand_still_time_expired = stand_still_end < now
        last_award_status = tender.awards[-1].status if tender.awards else ""
        if (not pending_complaints and not pending_awards_complaints
                and stand_still_time_expired
                and last_award_status == "unsuccessful"):
            LOGGER.info(
                "Switched tender {} to {}".format(tender.id, "unsuccessful"),
                extra=context_unpack(
                    request, {"MESSAGE_ID": "switched_tender_unsuccessful"}),
            )
            tender.status = "unsuccessful"

        contracts = (tender.agreements[-1].get("contracts") if
                     tender.get("agreements") else tender.get("contracts", []))
        if (contracts and any(
            [contract.status == "active" for contract in contracts])
                and not any(
                    [contract.status == "pending" for contract in contracts])):
            tender.status = "complete"

    if tender.procurementMethodType == "belowThreshold":
        check_ignored_claim(tender)
예제 #10
0
    def patch(self):
        """Patch the complaint
        """
        tender = self.request.validated["tender"]
        data = self.request.validated["data"]
        status = self.context.status
        new_status = data.get("status", status)

        is_qualificationPeriod = tender.qualificationPeriod.startDate < get_now(
        ) and (not tender.qualificationPeriod.endDate
               or tender.qualificationPeriod.endDate > get_now())

        new_rules = get_first_revision_date(tender) > RELEASE_2020_04_19
        # complaint_owner
        if (self.request.authenticated_role == "complaint_owner"
                and status in ["draft", "claim", "answered"]
                and new_status == "cancelled"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif (self.request.authenticated_role == "complaint_owner"
              and new_rules and status == "draft"
              and new_status == "mistaken"):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (self.request.authenticated_role == "complaint_owner"
              and status in ["pending", "accepted"]
              and new_status == "stopping"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif (self.request.authenticated_role == "complaint_owner"
              and is_qualificationPeriod and status == "draft"
              and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (self.request.authenticated_role == "complaint_owner"
              and is_qualificationPeriod and status == "draft"
              and new_status == "claim"):
            if (self.request.validated["qualification"].status
                    == "unsuccessful"
                    and self.request.validated["qualification"].bidID !=
                    self.context.bid_id):
                raise_operation_error(
                    self.request,
                    "Can add claim only on unsuccessful qualification of your bid"
                )
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateSubmitted = get_now()
        elif (self.request.authenticated_role == "complaint_owner"
              and is_qualificationPeriod and status == "draft"
              and new_status == "pending"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.type = "complaint"
            self.context.dateSubmitted = get_now()
        elif (self.request.authenticated_role == "complaint_owner"
              and status == "answered" and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        # tender_owner
        elif self.request.authenticated_role == "tender_owner" and status in [
                "pending", "accepted"
        ]:
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (self.request.authenticated_role == "tender_owner"
              and status in ["claim", "satisfied"] and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (self.request.authenticated_role == "tender_owner"
              and status == "claim"
              and data.get("resolution", self.context.resolution)
              and data.get("resolutionType", self.context.resolutionType)
              and new_status == "answered"):
            if len(data.get("resolution", self.context.resolution)) < 20:
                raise_operation_error(
                    self.request,
                    "Can't update complaint: resolution too short")
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateAnswered = get_now()
        elif (self.request.authenticated_role == "tender_owner"
              and status == "satisfied"
              and data.get("tendererAction", self.context.tendererAction)
              and new_status == "resolved"):
            apply_patch(self.request, save=False, src=self.context.serialize())
        # aboveThresholdReviewers
        elif (self.request.authenticated_role == "aboveThresholdReviewers"
              and status in ["pending", "accepted", "stopping"]
              and new_status == status):
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (self.request.authenticated_role == "aboveThresholdReviewers"
              and status in ["pending", "stopping"]
              and ((not new_rules and new_status in ["invalid", "mistaken"]) or
                   (new_status == "invalid"))):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
            self.context.acceptance = False
        elif (self.request.authenticated_role == "aboveThresholdReviewers"
              and status == "pending" and new_status == "accepted"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateAccepted = get_now()
            self.context.acceptance = True
        elif (self.request.authenticated_role == "aboveThresholdReviewers"
              and status in ["accepted", "stopping"]
              and new_status == "declined"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
        elif (self.request.authenticated_role == "aboveThresholdReviewers"
              and status in ["accepted", "stopping"]
              and new_status == "satisfied"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
            tender.status = "active.pre-qualification"
            if tender.qualificationPeriod.endDate:
                tender.qualificationPeriod.endDate = None
        elif (self.request.authenticated_role == "aboveThresholdReviewers"
              and status in ["pending", "accepted", "stopping"]
              and new_status == "stopped"):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()
            self.context.dateCanceled = self.context.dateCanceled or get_now()
        else:
            raise_operation_error(self.request, "Can't update complaint")
        if self.context.tendererAction and not self.context.tendererActionDate:
            self.context.tendererActionDate = get_now()
        if save_tender(self.request):
            self.LOGGER.info(
                "Updated tender qualification complaint {}".format(
                    self.context.id),
                extra=context_unpack(
                    self.request,
                    {"MESSAGE_ID": "tender_qualification_complaint_patch"}),
            )
            return {"data": self.context.serialize("view")}