コード例 #1
0
ファイル: complaint.py プロジェクト: lttga/op
class CompetitiveDialogueStage2UAComplaintResource(TenderUaComplaintResource):
    @json_view(
        content_type="application/json",
        validators=(
            validate_complaint_data_stage2,
            validate_complaint_operation_not_in_active_tendering,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending("complaint")
        ),
        permission="create_complaint",
    )
    def collection_post(self):
        return super(CompetitiveDialogueStage2UAComplaintResource, self).collection_post()

    @json_view(
        content_type="application/json",
        validators=(
            validate_patch_complaint_data_stage2,
            validate_complaint_update_with_cancellation_lot_pending,
            validate_complaint_operation_not_in_active_tendering,
            validate_update_complaint_not_in_allowed_complaint_status,
        ),
        permission="edit_complaint",
    )
    def patch(self):
        return super(CompetitiveDialogueStage2UAComplaintResource, self).patch()
コード例 #2
0
class TenderUaAwardComplaintResource(BaseTenderAwardComplaintResource):
    @json_view(
        content_type="application/json",
        permission="create_award_complaint",
        validators=(
            validate_complaint_data,
            validate_only_complaint_allowed,
            validate_award_complaint_operation_not_in_allowed_status,
            validate_award_complaint_add_only_for_active_lots,
            validate_add_complaint_not_in_complaint_period,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending("award"),
        ),
    )
    def collection_post(self):
        """Post a complaint for award
        """
        return super(TenderUaAwardComplaintResource, self).collection_post()
コード例 #3
0
class BaseTenderComplaintResource(ComplaintBotPatchMixin,
                                  ComplaintAdminPatchMixin, APIResource):
    patch_check_tender_excluded_statuses = (
        "draft",
        "claim",
        "answered",
        "pending",
        "accepted",
        "satisfied",
        "stopping",
    )

    patch_check_tender_statuses = ("active.qualification", "active.awarded")

    @staticmethod
    def validate_submit_claim_time_method(request):
        raise NotImplementedError

    @staticmethod
    def validate_update_claim_time_method(request):
        raise NotImplementedError

    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()
        if complaint.status == "claim" and complaint.type == "claim":
            self.validate_submit_claim_time_method(self.request)
            complaint.dateSubmitted = get_now()
        elif old_rules and complaint.status == "pending":
            validate_submit_complaint_time(self.request)
            complaint.dateSubmitted = get_now()
            complaint.type = "complaint"
        else:
            complaint.status = "draft"
        return complaint

    @json_view(permission="view_tender")
    def collection_get(self):
        """List complaints
        """
        return {"data": [i.serialize("view") for i in self.context.complaints]}

    @json_view(permission="view_tender")
    def get(self):
        """Retrieving the complaint
        """
        return {"data": self.context.serialize("view")}

    @json_view(
        content_type="application/json",
        validators=(
            validate_complaint_data,
            validate_complaint_operation_not_in_active_tendering,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending(
                "complaint"),
        ),
        permission="create_complaint",
    )
    def collection_post(self):
        """Post a complaint for award
        """
        tender = self.request.validated["tender"]

        complaint = self.pre_create()

        complaint.complaintID = "{}.{}{}".format(
            tender.tenderID, self.server_id,
            calculate_total_complaints(tender) + 1)
        access = set_ownership(complaint, self.request)
        self.context.complaints.append(complaint)
        if save_tender(self.request):
            self.LOGGER.info(
                "Created tender award complaint {}".format(complaint.id),
                extra=context_unpack(self.request,
                                     {"MESSAGE_ID": "tender_complaint_create"},
                                     {"complaint_id": complaint.id}),
            )
            self.request.response.status = 201
            self.request.response.headers["Location"] = self.request.route_url(
                "{}:Tender Complaints".format(tender.procurementMethodType),
                tender_id=tender.id,
                complaint_id=complaint.id,
            )
            return {
                "data": complaint.serialize(tender.status),
                "access": access
            }

    @json_view(
        content_type="application/json",
        permission="edit_complaint",
        validators=(
            validate_patch_complaint_data,
            validate_complaint_update_with_cancellation_lot_pending,
            validate_complaint_operation_not_in_active_tendering,
            validate_update_complaint_not_in_allowed_complaint_status,
            validate_operation_with_lot_cancellation_in_pending("complaint"),
        ),
    )
    def patch(self):
        role_method_name = "patch_as_{role}".format(
            role=self.request.authenticated_role.lower())
        try:
            role_method = getattr(self, role_method_name)
        except AttributeError:
            raise_operation_error(
                self.request, "Can't update complaint as {}".format(
                    self.request.authenticated_role))
        else:
            role_method(self.request.validated["data"])

        if self.context.tendererAction and not self.context.tendererActionDate:
            self.context.tendererActionDate = get_now()
        if (self.patch_check_tender_excluded_statuses != "__all__"
                and self.context.status
                not in self.patch_check_tender_excluded_statuses
                and self.request.validated["tender"].status
                in self.patch_check_tender_statuses):
            check_tender_status(self.request)

        if save_tender(self.request):
            self.LOGGER.info(
                "Updated tender award complaint {}".format(self.context.id),
                extra=context_unpack(
                    self.request,
                    {"MESSAGE_ID": "tender_award_complaint_patch"}),
            )
            return {"data": self.context.serialize("view")}

    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"]
        apply_rules_2020_04_19 = get_first_revision_date(
            tender) > RELEASE_2020_04_19

        if (new_status == "cancelled"
                and status in ["draft", "claim", "answered"] and context.type
                == "claim") or (new_status == "cancelled" and status == "draft"
                                and context.type == "complaint"
                                and not apply_rules_2020_04_19):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateCanceled = get_now()

        elif (apply_rules_2020_04_19 and status == "draft"
              and context.type == "complaint" and new_status == "mistaken"):
            context.rejectReason = "cancelledByComplainant"
            apply_patch(self.request, save=False, src=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=context.serialize())
            context.dateCanceled = get_now()
        elif (tender.status == "active.tendering" and status == "draft"
              and new_status == status):
            apply_patch(self.request, save=False, src=context.serialize())
        elif (tender.status == "active.tendering" and context.type == "claim"
              and status == "draft" and new_status == "claim"):
            self.validate_submit_claim_time_method(self.request)
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateSubmitted = get_now()
        elif (tender.status == "active.tendering"
              and status in ["draft", "claim"] and new_status == "pending"
              and not apply_rules_2020_04_19):
            validate_submit_complaint_time(self.request)
            validate_complaint_type_change(self.request)
            apply_patch(self.request, save=False, src=context.serialize())
            context.type = "complaint"
            context.dateSubmitted = get_now()

        elif status == "answered" and new_status == status:
            apply_patch(self.request, save=False, src=context.serialize())
        elif (status == "answered"
              and data.get("satisfied", context.satisfied) is True
              and new_status == "resolved"):
            apply_patch(self.request, save=False, src=context.serialize())
        elif (status == "answered"
              and data.get("satisfied", context.satisfied) is False
              and new_status == "pending"):
            validate_submit_complaint_time(self.request)
            validate_complaint_type_change(self.request)
            apply_patch(self.request, save=False, src=context.serialize())
            context.type = "complaint"
            context.dateEscalated = get_now()
        else:
            raise_operation_error(
                self.request,
                "Can't update complaint from {} to {} status".format(
                    status, new_status))

    def patch_as_tender_owner(self, data):
        context = self.context
        status = context.status
        new_status = data.get("status", status)

        if status == "claim" and new_status == status:
            self.validate_update_claim_time_method(self.request)
            apply_patch(self.request, save=False, src=context.serialize())

        elif status == "satisfied" and new_status == status:
            apply_patch(self.request, save=False, src=context.serialize())

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

    def patch_as_abovethresholdreviewers(self, data):
        context = self.context
        status = context.status
        new_status = data.get("status", status)

        tender = self.request.validated["tender"]
        old_rules = 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=context.serialize())
        elif (status in ["pending", "stopping"]
              and ((old_rules and new_status in ["invalid", "mistaken"]) or
                   (new_status == "invalid"))):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateDecision = get_now()
            context.acceptance = False
        elif status == "pending" and new_status == "accepted":
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateAccepted = get_now()
            context.acceptance = True
        elif (status in ["accepted", "stopping"]
              and new_status in ["declined", "satisfied"]):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateDecision = get_now()
        elif ((old_rules and status in ["pending", "accepted", "stopping"])
              or (not old_rules and status == "accepted")
              and new_status == "stopped"):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateDecision = get_now()
            context.dateCanceled = context.dateCanceled or get_now()
        else:
            raise_operation_error(
                self.request,
                "Can't update complaint from {} to {} status".format(
                    status, new_status))
コード例 #4
0
class TenderNegotiationAwardComplaintResource(BaseTenderAwardComplaintResource
                                              ):

    patch_check_tender_excluded_statuses = "__all__"

    def complaints_len(self, tender):
        return sum([len(i.complaints) for i in tender.awards])

    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()
        if old_rules and complaint.status == "pending":
            complaint.dateSubmitted = get_now()
        else:
            complaint.status = "draft"

        return complaint

    @json_view(
        content_type="application/json",
        permission="create_award_complaint",
        validators=(
            validate_complaint_data,
            validate_award_complaint_operation_not_in_active,
            validate_add_complaint_not_in_complaint_period,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending("award"),
        ),
    )
    def collection_post(self):
        """Post a complaint for award
        """
        return super(TenderNegotiationAwardComplaintResource,
                     self).collection_post()

    @json_view(
        content_type="application/json",
        permission="edit_complaint",
        validators=(
            validate_patch_complaint_data,
            validate_award_complaint_operation_not_in_active,
            validate_update_complaint_not_in_allowed_complaint_status,
        ),
    )
    def patch(self):
        return super(TenderNegotiationAwardComplaintResource, self).patch()

    def patch_as_complaint_owner(self, data):
        complaint_period = self.request.validated["award"].complaintPeriod
        is_complaint_period = (
            complaint_period.startDate <= get_now() <= complaint_period.endDate
            if complaint_period.endDate else
            complaint_period.startDate <= get_now())
        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 status in ["draft", "claim", "answered"
                      ] and new_status == "cancelled":
            # claim ? There is no way to post claim, so this must be a backward-compatibility option
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif status in ["pending", "accepted"] and new_status == "stopping":
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif status == "draft":
            if not is_complaint_period:
                raise_operation_error(
                    self.request,
                    "Can't update draft complaint not in complaintPeriod")
            if new_status == status:
                apply_patch(self.request,
                            save=False,
                            src=self.context.serialize())
            elif (new_rules and self.context.type == "complaint"
                  and new_status == "mistaken"):
                self.context.rejectReason = "cancelledByComplainant"
                apply_patch(self.request,
                            save=False,
                            src=self.context.serialize())
            elif new_status == "pending" and not new_rules:
                apply_patch(self.request,
                            save=False,
                            src=self.context.serialize())
                self.context.type = "complaint"
                self.context.dateSubmitted = get_now()
            else:
                raise_operation_error(
                    self.request,
                    "Can't update draft complaint to {} status".format(
                        new_status))
        else:
            raise_operation_error(
                self.request, "Can't update complaint from {} to {}".format(
                    status, new_status))

    def patch_as_tender_owner(self, data):
        status = self.context.status
        new_status = data.get("status", status)
        if status in ["pending", "accepted"]:
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif status == "satisfied" and new_status == status:
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif status == "satisfied" and new_status == "resolved":
            if not data.get("tendererAction", self.context.tendererAction):
                raise_operation_error(
                    self.request,
                    "Can't update complaint: tendererAction required")
            apply_patch(self.request, save=False, src=self.context.serialize())
        else:
            raise_operation_error(
                self.request, "Can't update complaint from {} to {}".format(
                    status, new_status))

    def patch_as_abovethresholdreviewers(self, data):
        status = self.context.status
        new_status = data.get("status", status)

        tender = self.request.validated["tender"]
        old_rules = 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 ((old_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 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 in ["declined", "satisfied"]:
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateDecision = get_now()

        elif ((old_rules and status in ["pending", "accepted", "stopping"])
              or (not old_rules and status in ["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 from {} to {}".format(
                    status, new_status))
コード例 #5
0
class BaseTenderAwardComplaintResource(BaseTenderComplaintResource):
    patch_check_tender_excluded_statuses = (
        "draft", "claim", "answered", "pending", "accepted", "satisfied", "stopping",
    )

    @staticmethod
    def check_tender_status_method(request):
        return check_tender_status(request)

    def validate_posting_complaint(self):
        tender = self.request.validated["tender"]

        rules_2020_04_19 = get_first_revision_date(tender, get_now()) > RELEASE_2020_04_19

        context_award = self.request.validated["award"]

        if not rules_2020_04_19:

            if not any(
                award.status == "active"
                for award in tender.awards
                if award.lotID == context_award.lotID
            ):
                raise_operation_error(self.request, "Complaint submission is allowed only after award activation.")
        else:

            if context_award.status not in ("active", "unsuccessful"):
                raise_operation_error(
                    self.request,
                    "Complaint submission is allowed only after award activation or unsuccessful award.",
                )

    def validate_posting_claim(self):
        complaint = self.request.validated["complaint"]
        award = self.request.validated["award"]
        if award.status == "unsuccessful" and award.bid_id != complaint.bid_id:
            raise_operation_error(self.request, "Can add claim only on unsuccessful award of your bid")
        if award.status == "pending":
            raise_operation_error(self.request, "Claim submission is not allowed on pending award")

    def pre_create(self):
        tender = self.request.validated["tender"]
        rules_2020_04_19 = 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" and complaint.type == "claim":   # claim
            self.validate_posting_claim()
            complaint.dateSubmitted = get_now()
        elif not rules_2020_04_19 and complaint.status == "pending":  # complaint
            self.validate_posting_complaint()
            complaint.type = "complaint"
            complaint.dateSubmitted = get_now()
        else:  # draft is neither claim nor complaint yet
            complaint.status = "draft"
        
        return complaint
    
    @json_view(
        content_type="application/json",
        permission="create_award_complaint",
        validators=(
            validate_complaint_data,
            validate_award_complaint_operation_not_in_allowed_status,
            validate_award_complaint_add_only_for_active_lots,
            validate_add_complaint_not_in_complaint_period,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending("award"),
        ),
    )
    def collection_post(self):
        """Post a complaint for award
        """
        tender = self.request.validated["tender"]
        
        complaint = self.pre_create()
        
        complaint.complaintID = "{}.{}{}".format(
            tender.tenderID,
            self.server_id,
            calculate_total_complaints(tender) + 1,
        )
        access = set_ownership(complaint, self.request)
        self.context.complaints.append(complaint)
        if save_tender(self.request):
            self.LOGGER.info(
                "Created tender award complaint {}".format(complaint.id),
                extra=context_unpack(
                    self.request, {"MESSAGE_ID": "tender_award_complaint_create"}, {"complaint_id": complaint.id}
                ),
            )
            self.request.response.status = 201
            self.request.response.headers["Location"] = self.request.route_url(
                "{}:Tender Award Complaints".format(tender.procurementMethodType),
                tender_id=tender.id,
                award_id=self.request.validated["award_id"],
                complaint_id=complaint["id"],
            )
            return {"data": complaint.serialize("view"), "access": access}

    @json_view(
        content_type="application/json",
        permission="edit_complaint",
        validators=(
            validate_patch_complaint_data,
            validate_update_award_with_cancellation_lot_pending,
            validate_award_complaint_operation_not_in_allowed_status,
            validate_award_complaint_update_only_for_active_lots,
            validate_update_complaint_not_in_allowed_complaint_status,
        ),
    )
    def patch(self):
        role_method_name = "patch_as_{role}".format(role=self.request.authenticated_role.lower())
        try:
            role_method = getattr(self, role_method_name)
        except AttributeError:
            raise_operation_error(self.request, "Can't update complaint as {}".format(self.request.authenticated_role))
        else:
            role_method(self.request.validated["data"])

        if self.context.tendererAction and not self.context.tendererActionDate:
            self.context.tendererActionDate = get_now()

        if (
            self.context.status not in self.patch_check_tender_excluded_statuses
            and self.request.validated["tender"].status in self.patch_check_tender_statuses
        ):
            self.check_tender_status_method(self.request)

        if save_tender(self.request):
            self.LOGGER.info(
                "Updated tender award complaint {}".format(self.context.id),
                extra=context_unpack(self.request, {"MESSAGE_ID": "tender_award_complaint_patch"}),
            )
            return {"data": self.context.serialize("view")}

    def patch_as_complaint_owner(self, data):
        status = self.context.status
        new_status = data.get("status", status)
        tender = self.request.validated["tender"]
        rules_2020_04_19 = get_first_revision_date(tender, get_now()) > RELEASE_2020_04_19
        if (
            new_status == "cancelled"
            and status in ["draft", "claim", "answered"]
            and self.context.type == "claim"
        ) or (
            new_status == "cancelled"
            and status == "draft"
            and self.context.type == "complaint"
            and not rules_2020_04_19
        ) or (
            new_status == "stopping"
            and status in ["pending", "accepted"]
            and not rules_2020_04_19
        ):
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateCanceled = get_now()
        elif status == "draft":
            self.patch_draft_as_complaint_owner(data)

        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)
            )

    def patch_draft_as_complaint_owner(self, data):
        tender = self.request.validated["tender"]
        rules_2020_04_19 = get_first_revision_date(tender) > RELEASE_2020_04_19

        complaint_period = self.request.validated["award"].complaintPeriod
        is_complaint_period = (
            complaint_period.startDate <= get_now() <= complaint_period.endDate
            if complaint_period.endDate
            else complaint_period.startDate <= get_now()
        )
        if not is_complaint_period:
            raise_operation_error(self.request, "Can't update draft complaint not in complaintPeriod")

        new_status = data.get("status", self.context.status)
        if new_status == self.context.status:
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif (
            rules_2020_04_19
            and self.context.type == "complaint"
            and new_status == "mistaken"
        ):
            self.context.rejectReason = "cancelledByComplainant"
            apply_patch(self.request, save=False, src=self.context.serialize())
        elif self.context.type == "claim" and new_status == "claim":
            self.validate_posting_claim()
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.dateSubmitted = get_now()

        elif new_status == "pending" and not rules_2020_04_19:
            apply_patch(self.request, save=False, src=self.context.serialize())
            self.context.type = "complaint"
            self.context.dateSubmitted = get_now()
        else:
            raise_operation_error(self.request, "Can't update draft complaint into {} status".format(new_status))

    def patch_as_tender_owner(self, data):
        context = self.context
        status = context.status
        new_status = data.get("status", status)

        if status in ["pending", "accepted"] or new_status == status and status in ["claim", "satisfied"]:
            apply_patch(self.request, save=False, src=context.serialize())

        elif status == "claim" and new_status == "answered":
            if not data.get("resolution", context.resolution) or not data.get("resolutionType", context.resolutionType):
                raise_operation_error(self.request, "Can't update complaint: resolution and resolutionType required")

            if len(data.get("resolution", context.resolution)) < 20:
                raise_operation_error(self.request, "Can't update complaint: resolution too short")
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateAnswered = get_now()

        elif status == "satisfied" and new_status == "resolved":
            if not data.get("tendererAction", context.tendererAction):
                raise_operation_error(self.request, "Can't update complaint: tendererAction required")

            apply_patch(self.request, save=False, src=context.serialize())
        else:
            raise_operation_error(self.request,
                                  "Can't update complaint from {} to {} status".format(status, new_status))

    def patch_as_abovethresholdreviewers(self, data):
        context = self.context
        status = context.status
        new_status = data.get("status", status)

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

        rules_2020_04_19 = get_first_revision_date(tender, get_now()) > RELEASE_2020_04_19

        if new_status == status and status in ["pending", "accepted", "stopping"]:
            apply_patch(self.request, save=False, src=context.serialize())

        elif (
            status in ["pending", "stopping"]
            and (
                (not rules_2020_04_19 and new_status in ["invalid", "mistaken"])
                or (new_status == "invalid")
            )
        ):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateDecision = get_now()
            context.acceptance = False

        elif status == "pending" and new_status == "accepted":
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateAccepted = get_now()
            context.acceptance = True

        elif status in ["accepted", "stopping"] and new_status in ["declined", "satisfied"]:
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateDecision = get_now()
            if new_status == "satisfied":
                self.on_satisfy_complaint_by_reviewer()

        elif (
            (not rules_2020_04_19 and status in ["pending", "accepted", "stopping"])
            or (rules_2020_04_19 and status == "accepted")
            and new_status == "stopped"
        ):
            apply_patch(self.request, save=False, src=context.serialize())
            context.dateDecision = get_now()
            context.dateCanceled = context.dateCanceled or get_now()
        else:
            raise_operation_error(self.request,
                                  "Can't update complaint from {} to {} status".format(status, new_status))

    def on_satisfy_complaint_by_reviewer(self):
        pass
コード例 #6
0
class TenderEUQualificationComplaintResource(TenderEUAwardComplaintResource):
    def complaints_len(self, tender):
        return sum(
            [len(i.complaints) for i in tender.awards],
            sum([len(i.complaints) for i in tender.qualifications],
                len(tender.complaints)),
        )

    @json_view(
        content_type="application/json",
        permission="create_qualification_complaint",
        validators=(
            validate_complaint_data,
            validate_add_complaint_not_in_pre_qualification,
            validate_award_complaint_add_only_for_active_lots,
            validate_add_complaint_not_in_qualification_period,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending(
                "qualification"),
        ),
    )
    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}

    @json_view(
        content_type="application/json",
        permission="edit_complaint",
        validators=(
            validate_patch_complaint_data,
            validate_qualification_update_with_cancellation_lot_pending,
            validate_update_complaint_not_in_pre_qualification,
            validate_update_qualification_complaint_only_for_active_lots,
            validate_update_complaint_not_in_allowed_complaint_status,
        ),
    )
    def patch(self):
        role_method_name = "patch_as_{role}".format(
            role=self.request.authenticated_role.lower())
        try:
            role_method = getattr(self, role_method_name)
        except AttributeError:
            raise_operation_error(
                self.request, "Can't update complaint as {}".format(
                    self.request.authenticated_role))
        else:
            role_method(self.request.validated["data"])

        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")}

    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())

        new_rules = 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 (new_rules 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"):
            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 new_rules):
            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))

    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))

    def patch_as_abovethresholdreviewers(self, data):
        context = self.context
        status = 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 (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 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 (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 new_rules and status in ["pending", "accepted", "stopping"])
             or (new_rules and status in ["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 from {} to {} status".format(
                    status, new_status))
コード例 #7
0
class TenderEUAwardComplaintResource(BaseTenderAwardComplaintResource):
    patch_check_tender_statuses = ("active.qualification.stand-still",)

    def check_tender_status_method(self, request):
        return check_tender_status_on_active_qualification_stand_still(request)
    
    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" and complaint.type == "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

    @json_view(
        content_type="application/json",
        permission="create_award_complaint",
        validators=(
            validate_complaint_data,
            validate_add_complaint_not_in_qualification_stand_still,
            validate_award_complaint_add_only_for_active_lots,
            validate_add_complaint_not_in_complaint_period,
            validate_add_complaint_with_tender_cancellation_in_pending,
            validate_add_complaint_with_lot_cancellation_in_pending("award"),
        ),
    )
    def collection_post(self):
        return super(TenderEUAwardComplaintResource, self).collection_post()

    @json_view(
        content_type="application/json",
        permission="edit_complaint",
        validators=(
            validate_patch_complaint_data,
            validate_update_complaint_not_in_qualification,
            validate_award_complaint_update_only_for_active_lots,
            validate_update_complaint_not_in_allowed_complaint_status,
        ),
    )
    def patch(self):
        return super(TenderEUAwardComplaintResource, self).patch()

    def validate_posting_complaint(self):
        """
        we overwrite checking an active award
        as long as we have "validate_add_complaint_not_in_qualification_stand_still"
        in qualification.stand-still we always have an active award
        """

    def on_satisfy_complaint_by_reviewer(self):
        tender = self.request.validated["tender"]
        tender.status = "active.qualification"
        if tender.awardPeriod.endDate:
            tender.awardPeriod.endDate = None