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