def check_status(request): tender = request.validated["tender"] now = get_now() check_complaint_statuses_at_complaint_period_end(tender, now) check_cancellation_status(request, CancelTenderLot) if cancellation_block_tender(tender): return active_lots = [ lot.id for lot in tender.lots if lot.status == "active" ] if tender.lots else [None] if ( tender.status == "active.tendering" and tender.tenderPeriod.endDate <= now and not has_unanswered_complaints(tender) and not has_unanswered_questions(tender) ): for complaint in tender.complaints: check_complaint_status(request, complaint) LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.pre-qualification"), extra=context_unpack(request, {"MESSAGE_ID": "switched_tender_active.pre-qualification"}), ) tender.status = "active.pre-qualification" tender.qualificationPeriod = type(tender).qualificationPeriod({"startDate": now}) remove_draft_bids(request) check_initial_bids_count(request) prepare_qualifications(request) return elif ( tender.status == "active.pre-qualification.stand-still" and tender.qualificationPeriod and tender.qualificationPeriod.endDate <= now and not any( [ i.status in tender.block_complaint_status for q in tender.qualifications for i in q.complaints if q.lotID in active_lots ] ) ): LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.auction"), extra=context_unpack(request, {"MESSAGE_ID": "switched_tender_active.auction"}), ) tender.status = "active.auction" check_initial_bids_count(request) return elif tender.status == "active.qualification.stand-still": check_tender_status_on_active_qualification_stand_still(request)
def next_check(self): checks = [] extend_next_check_by_complaint_period_ends(self, checks) if cancellation_block_tender(self): return min(checks).isoformat() if checks else None # Add checks here if needed return min(checks).isoformat() if checks else None
def next_check(self): now = get_now() checks = [] extend_next_check_by_complaint_period_ends(self, checks) if cancellation_block_tender(self): return min(checks).isoformat() if checks else None if ( self.status == "active.tendering" and self.tenderPeriod.endDate and not has_unanswered_complaints(self) and not has_unanswered_questions(self) ): checks.append(self.tenderPeriod.endDate.astimezone(TZ)) elif ( self.status == "active.pre-qualification.stand-still" and self.qualificationPeriod and self.qualificationPeriod.endDate ): active_lots = [lot.id for lot in self.lots if lot.status == "active"] if self.lots else [None] if not any( [ i.status in self.block_complaint_status for q in self.qualifications for i in q.complaints if q.lotID in active_lots ] ): checks.append(self.qualificationPeriod.endDate.astimezone(TZ)) elif ( not self.lots and self.status == "active.auction" and self.auctionPeriod and self.auctionPeriod.startDate and not self.auctionPeriod.endDate ): if now < self.auctionPeriod.startDate: checks.append(self.auctionPeriod.startDate.astimezone(TZ)) else: auction_end_time = calc_auction_end_time( self.numberOfBids, self.auctionPeriod.startDate ).astimezone(TZ) if now < auction_end_time: checks.append(auction_end_time) elif self.lots and self.status == "active.auction": for lot in self.lots: if ( lot.status != "active" or not lot.auctionPeriod or not lot.auctionPeriod.startDate or lot.auctionPeriod.endDate ): continue if now < lot.auctionPeriod.startDate: checks.append(lot.auctionPeriod.startDate.astimezone(TZ)) else: auction_end_time = calc_auction_end_time( lot.numberOfBids, lot.auctionPeriod.startDate ).astimezone(TZ) if now < auction_end_time: checks.append(auction_end_time) elif ( not self.lots and self.status == "active.awarded" and not any([i.status in self.block_complaint_status for i in self.complaints]) and not any([i.status in self.block_complaint_status for a in self.awards for i in a.complaints]) ): standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in self.awards if a.complaintPeriod and a.complaintPeriod.endDate ] last_award_status = self.awards[-1].status if self.awards else "" if standStillEnds and last_award_status == "unsuccessful": checks.append(max(standStillEnds)) elif ( self.lots and self.status in ["active.qualification", "active.awarded"] and not any([i.status in self.block_complaint_status and i.relatedLot is None for i in self.complaints]) ): for lot in self.lots: if lot["status"] != "active": continue lot_awards = [i for i in self.awards if i.lotID == lot.id] pending_complaints = any( [i["status"] in self.block_complaint_status and i.relatedLot == lot.id for i in self.complaints] ) pending_awards_complaints = any( [i.status in self.block_complaint_status for a in lot_awards for i in a.complaints] ) standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in lot_awards if a.complaintPeriod and a.complaintPeriod.endDate ] last_award_status = lot_awards[-1].status if lot_awards else "" if ( not pending_complaints and not pending_awards_complaints and standStillEnds and last_award_status == "unsuccessful" ): checks.append(max(standStillEnds)) if self.status.startswith("active"): for award in self.awards: if award.status == "active" and not any([i.awardID == award.id for i in self.contracts]): checks.append(award.date) return min(checks).isoformat() if checks else None
def check_status(request): tender = request.validated["tender"] now = get_now() check_complaint_statuses_at_complaint_period_end(tender, now) check_cancellation_status(request) if cancellation_block_tender(tender): return for award in tender.awards: if award.status == "active" and not any( [i.awardID == award.id for i in tender.contracts]): add_contract(request, award, now) add_next_award(request) if (not tender.lots and tender.status == "active.tendering" and tender.tenderPeriod.endDate <= now and not has_unanswered_complaints(tender) and not has_unanswered_questions(tender)): for complaint in tender.complaints: check_complaint_status(request, complaint) LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.auction"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_active.auction"}), ) tender.status = "active.auction" check_bids(request) if tender.numberOfBids < 2 and tender.auctionPeriod: tender.auctionPeriod.startDate = None return elif (tender.lots and tender.status == "active.tendering" and tender.tenderPeriod.endDate <= now and not has_unanswered_complaints(tender) and not has_unanswered_questions(tender)): for complaint in tender.complaints: check_complaint_status(request, complaint) LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.auction"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_active.auction"}), ) tender.status = "active.auction" check_bids(request) [ setattr(i.auctionPeriod, "startDate", None) for i in tender.lots if i.numberOfBids < 2 and i.auctionPeriod ] return elif not tender.lots and tender.status == "active.awarded": standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in tender.awards if a.complaintPeriod and a.complaintPeriod.endDate ] if not standStillEnds: return standStillEnd = max(standStillEnds) if standStillEnd <= now: 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 ]) awarded = any([i["status"] == "active" for i in tender.awards]) if not pending_complaints and not pending_awards_complaints and not awarded: LOGGER.info( "Switched tender {} to {}".format(tender.id, "unsuccessful"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_unsuccessful"}), ) check_tender_status(request) return elif tender.lots and tender.status in [ "active.qualification", "active.awarded" ]: 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] standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in lot_awards if a.complaintPeriod and a.complaintPeriod.endDate ] if not standStillEnds: continue standStillEnd = max(standStillEnds) if standStillEnd <= now: 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 ]) awarded = any([i["status"] == "active" for i in lot_awards]) if not pending_complaints and not pending_awards_complaints and not awarded: 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"]}), ) check_tender_status(request)
def __call__(self, obj): now = get_now() checks = [] extend_next_check_by_complaint_period_ends(obj, checks) if cancellation_block_tender(obj): return min(checks).isoformat() if checks else None configurator = getAdapter(obj, IContentConfigurator) if (obj.status == "active.tendering" and obj.tenderPeriod.endDate and not has_unanswered_complaints(obj) and not has_unanswered_questions(obj)): checks.append(obj.tenderPeriod.endDate.astimezone(configurator.tz)) elif (obj.status == "active.pre-qualification.stand-still" and obj.qualificationPeriod and obj.qualificationPeriod.endDate): active_lots = [ lot.id for lot in obj.lots if lot.status == "active" ] if obj.lots else [None] if not any([ i.status in obj.block_complaint_status for q in obj.qualifications for i in q.complaints if q.lotID in active_lots ]): checks.append( obj.qualificationPeriod.endDate.astimezone( configurator.tz)) elif (not obj.lots and obj.status == "active.auction" and obj.auctionPeriod and obj.auctionPeriod.startDate and not obj.auctionPeriod.endDate): if now < obj.auctionPeriod.startDate: checks.append( obj.auctionPeriod.startDate.astimezone(configurator.tz)) else: auction_end_time = calc_auction_end_time( obj.numberOfBids, obj.auctionPeriod.startDate).astimezone(configurator.tz) if now < auction_end_time: checks.append(auction_end_time) elif obj.lots and obj.status == "active.auction": for lot in obj.lots: if (lot.status != "active" or not lot.auctionPeriod or not lot.auctionPeriod.startDate or lot.auctionPeriod.endDate): continue if now < lot.auctionPeriod.startDate: checks.append( lot.auctionPeriod.startDate.astimezone( configurator.tz)) else: auction_end_time = calc_auction_end_time( lot.numberOfBids, lot.auctionPeriod.startDate).astimezone( configurator.tz) if now < auction_end_time: checks.append(auction_end_time) elif obj.status == "active.qualification.stand-still" and obj.awardPeriod and obj.awardPeriod.endDate: active_lots = [ lot.id for lot in obj.lots if lot.status == "active" ] if obj.lots else [None] if not any([ i.status in obj.block_complaint_status for q in obj.qualifications for i in q.complaints if q.lotID in active_lots ]): checks.append( obj.awardPeriod.endDate.astimezone(configurator.tz)) return min(checks).isoformat() if checks else None
def check_status(request): tender = request.validated["tender"] now = get_now() configurator = request.content_configurator check_complaint_statuses_at_complaint_period_end(tender, now) check_cancellation_status(request, CancelTenderLot) for award in tender.awards: if award.status == "active" and not any( [i.awardID == award.id for i in tender.contracts]): add_contract(request, award, now) add_next_award( request, reverse=configurator.reverse_awarding_criteria, awarding_criteria_key=configurator.awarding_criteria_key, ) if cancellation_block_tender(tender): return active_lots = [lot.id for lot in tender.lots if lot.status == "active"] if tender.lots else [None] if (tender.status == "active.tendering" and tender.tenderPeriod.endDate <= now and not has_unanswered_complaints(tender) and not has_unanswered_questions(tender)): for complaint in tender.complaints: check_complaint_status(request, complaint) LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.pre-qualification"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_active.pre-qualification"}), ) tender.status = "active.pre-qualification" tender.qualificationPeriod = type(tender).qualificationPeriod( {"startDate": now}) remove_draft_bids(request) check_initial_bids_count(request) prepare_qualifications(request) elif (tender.status == "active.pre-qualification.stand-still" and tender.qualificationPeriod and tender.qualificationPeriod.endDate <= now and not any([ i.status in tender.block_complaint_status for q in tender.qualifications for i in q.complaints if q.lotID in active_lots ])): LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.auction"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_active.auction"}), ) tender.status = "active.auction" check_initial_bids_count(request) elif not tender.lots and tender.status == "active.awarded": standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in tender.awards if a.complaintPeriod and a.complaintPeriod.endDate ] if standStillEnds: standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) elif tender.lots and tender.status in [ "active.qualification", "active.awarded" ]: for lot in tender.lots: if lot["status"] != "active": continue lot_awards = [i for i in tender.awards if i.lotID == lot.id] standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in lot_awards if a.complaintPeriod and a.complaintPeriod.endDate ] if not standStillEnds: continue standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) break
def check_status(request): tender = request.validated["tender"] now = get_now() check_complaint_statuses_at_complaint_period_end(tender, now) check_cancellation_status(request, cancel_class=CancelTenderLot) for award in tender.awards: if award.status == "active" and not any( [i.awardID == award.id for i in tender.contracts]): add_contracts(request, award, now) add_next_award(request) if cancellation_block_tender(tender): return if (not tender.lots and tender.status == "active.tendering" and tender.tenderPeriod.endDate <= now and not has_unanswered_complaints(tender) and not has_unanswered_questions(tender)): for complaint in tender.complaints: check_complaint_status(request, complaint) LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.auction"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_active.auction"}), ) tender.status = "active.auction" remove_draft_bids(request) check_bids(request) if tender.numberOfBids < 2 and tender.auctionPeriod: tender.auctionPeriod.startDate = None elif (tender.lots and tender.status == "active.tendering" and tender.tenderPeriod.endDate <= now and not has_unanswered_complaints(tender) and not has_unanswered_questions(tender)): for complaint in tender.complaints: check_complaint_status(request, complaint) LOGGER.info( "Switched tender {} to {}".format(tender["id"], "active.auction"), extra=context_unpack( request, {"MESSAGE_ID": "switched_tender_active.auction"}), ) tender.status = "active.auction" remove_draft_bids(request) check_bids(request) [ setattr(i.auctionPeriod, "startDate", None) for i in tender.lots if i.numberOfBids < 2 and i.auctionPeriod ] elif not tender.lots and tender.status == "active.awarded": standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in tender.awards if a.complaintPeriod and a.complaintPeriod.endDate ] if standStillEnds: standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) elif tender.lots and tender.status in [ "active.qualification", "active.awarded" ]: for lot in tender.lots: if lot["status"] != "active": continue lot_awards = [i for i in tender.awards if i.lotID == lot.id] standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in lot_awards if a.complaintPeriod and a.complaintPeriod.endDate ] if not standStillEnds: continue standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) break