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() self.context.status = "resolved" self.recalculate_tender_periods() if (self.context.status not in self.patch_check_tender_excluded_statuses and self.request.validated["tender"].status in ("active.qualification", "active.awarded")): check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( "Updated tender cancellation complaint {}".format( self.context.id), extra=context_unpack( self.request, {"MESSAGE_ID": "tender_cancellation_complaint_patch"}), ) return {"data": self.context.serialize("view")}
def patch(self): """Update of contract """ tender = self.request.validated['tender'] data = self.request.validated['data'] if self.request.context.status != 'active' and 'status' in data and data[ 'status'] == 'active': award = [ a for a in tender.awards if a.id == self.request.context.awardID ][0] stand_still_end = award.complaintPeriod.endDate if stand_still_end > get_now(): self.request.errors.add( 'body', 'data', 'Can\'t sign contract before stand-still period end ({})'. format(stand_still_end.isoformat())) self.request.errors.status = 403 raise error_handler(self.request.errors) pending_complaints = [ i for i in tender.complaints if i.status in ['claim', 'answered', 'pending'] and i.relatedLot in [None, award.lotID] ] pending_awards_complaints = [ i for a in tender.awards for i in a.complaints if i.status in ['claim', 'answered', 'pending'] and a.lotID == award.lotID ] if pending_complaints or pending_awards_complaints: self.request.errors.add( 'body', 'data', 'Can\'t sign contract before reviewing all complaints') self.request.errors.status = 403 raise error_handler(self.request.errors) contract_status = self.request.context.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if contract_status != self.request.context.status and ( contract_status != 'pending' or self.request.context.status != 'active'): self.request.errors.add('body', 'data', 'Can\'t update contract status') self.request.errors.status = 403 raise error_handler(self.request.errors) if self.request.context.status == 'active' and not self.request.context.dateSigned: self.request.context.dateSigned = get_now() check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( 'Updated tender contract {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_contract_patch'})) return {'data': self.request.context.serialize()}
def patch(self): """Update of contract """ contract_status = self.request.context.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if contract_status != self.request.context.status and \ (contract_status not in ("pending", "pending.winner-signing",) or \ self.request.context.status not in ("active", "pending", "pending.winner-signing",)): raise_operation_error(self.request, "Can't update contract status") if self.request.context.status == "active" and not self.request.context.dateSigned: self.request.context.dateSigned = get_now() check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( "Updated tender contract {}".format(self.request.context.id), extra=context_unpack(self.request, {"MESSAGE_ID": "tender_contract_patch"}), ) return {"data": self.request.context.serialize()}
def patch(self): """Update of contract """ contract_status = self.request.context.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if contract_status != self.request.context.status and ( contract_status != 'pending' or self.request.context.status != 'active'): raise_operation_error(self.request, 'Can\'t update contract status') if self.request.context.status == 'active' and not self.request.context.dateSigned: self.request.context.dateSigned = get_now() check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( 'Updated tender contract {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_contract_patch'})) return {'data': self.request.context.serialize()}
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: # not sure we need this self.context.tendererActionDate = get_now() if ( self.context.status not in ["draft", "claim", "answered"] and self.request.validated["tender"].status in ["active.qualification", "active.awarded"] ): 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(self): """Post a complaint resolution for award """ tender = self.request.validated['tender'] data = self.request.validated['data'] complaintPeriod = self.request.validated['award'].complaintPeriod is_complaintPeriod = complaintPeriod.startDate < get_now( ) and complaintPeriod.endDate > get_now( ) if complaintPeriod.endDate else complaintPeriod.startDate < get_now( ) # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in [ 'draft', 'claim', 'answered', 'pending' ] and data.get('status', self.context.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 is_complaintPeriod and self.context.status == 'draft' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and is_complaintPeriod and self.context.status == 'draft' and data.get( 'status', self.context.status) == 'claim': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'satisfied', self.context.satisfied) is True and data.get( 'status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'satisfied', self.context.satisfied) is False and data.get( 'status', self.context.status) == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() # tender_owner elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'resolution', self.context.resolution) and len( data.get('resolution', self.context.resolution or "")) >= 20 and data.get( 'resolutionType', self.context.resolutionType) and data.get( 'status', self.context.status) == 'answered': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAnswered = get_now() elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) # reviewers elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get( 'status', self.context.status) in ['resolved', 'invalid', 'declined']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() else: self.request.errors.add('body', 'data', 'Can\'t update complaint') self.request.errors.status = 403 raise error_handler(self.request.errors) if self.context.tendererAction and not self.context.tendererActionDate: self.context.tendererActionDate = get_now() if self.context.status not in [ 'draft', 'claim', 'answered', 'pending' ] and tender.status in ['active.qualification', 'active.awarded']: 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 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) active_lots = [lot.id for lot in tender.lots if lot.status == "active"] if tender.lots else [None] 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 block_tender(request): return 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_tender_status_method(request): return check_tender_status(request)
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 check_status(request): tender = request.validated['tender'] now = get_now() active_lots = [lot.id for lot in tender.lots if lot.status == 'active'] if tender.lots else [None] configurator = request.content_configurator for award in tender.awards: if award.status == 'active' and not any( [i.awardID == award.id for i in tender.contracts]): tender.contracts.append( type(tender).contracts.model_class({ 'awardID': award.id, 'suppliers': award.suppliers, 'value': award.value, 'date': now, 'items': [i for i in tender.items if i.relatedLot == award.lotID], 'contractID': '{}-{}{}'.format(tender.tenderID, request.registry.server_id, len(tender.contracts) + 1) })) add_next_award( request, reverse=configurator.reverse_awarding_criteria, awarding_criteria_key=configurator.awarding_criteria_key) 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 not tender.lots and tender.status == 'active.awarded': standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in tender.awards if a.complaintPeriod.endDate ] if not standStillEnds: return standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) 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.endDate ] if not standStillEnds: continue standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) return
def patch(self): """Post a complaint resolution """ tender = self.request.validated['tender'] data = self.request.validated['data'] # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in [ 'draft', 'claim', 'answered' ] and data.get('status', self.context.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 self.context.status in [ 'pending', 'accepted' ] and data.get('status', self.context.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 tender.status == 'active.tendering' and self.context.status == 'draft' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status == 'draft' and data.get( 'status', self.context.status) == 'claim': if get_now() > calculate_business_date(tender.tenderPeriod.endDate, -CLAIM_SUBMIT_TIME, tender, True): raise_operation_error( self.request, 'Can submit claim not later than {0.days} days before tenderPeriod end' .format(CLAIM_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status in [ 'draft', 'claim' ] and data.get('status', self.context.status) == 'pending': if get_now() > tender.complaintPeriod.endDate: raise_operation_error( self.request, 'Can submit complaint not later than {0.days} days before tenderPeriod end' .format(COMPLAINT_SUBMIT_TIME)) 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 self.context.status == 'answered' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'satisfied', self.context.satisfied) is True and data.get( 'status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'satisfied', self.context.satisfied) is False and data.get( 'status', self.context.status) == 'pending': if get_now() > tender.complaintPeriod.endDate: raise_operation_error( self.request, 'Can submit complaint not later than {0.days} days before tenderPeriod end' .format(COMPLAINT_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() # tender_owner elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'status', self.context.status) == self.context.status: now = get_now() if now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error( self.request, 'Can update claim only before enquiryPeriod.clarificationsUntil' ) apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'satisfied' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'resolution', self.context.resolution) and data.get( 'resolutionType', self.context.resolutionType) and data.get( 'status', self.context.status) == 'answered': now = get_now() if now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error( self.request, 'Can update claim only before enquiryPeriod.clarificationsUntil' ) 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 self.context.status in [ 'pending', 'accepted' ]: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'satisfied' and data.get( 'tendererAction', self.context.tendererAction) and data.get( 'status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) # aboveThresholdReviewers elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in [ 'pending', 'accepted', 'stopping' ] and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in [ 'pending', 'stopping' ] and data.get('status', self.context.status) in ['invalid', 'mistaken']: 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 self.context.status == 'pending' and data.get( 'status', self.context.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 self.context.status == 'accepted' and data.get( 'status', self.context.status) in ['declined', 'satisfied']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status == 'stopping' and data.get( 'status', self.context.status) == 'declined': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in [ 'accepted', 'stopping' ] and data.get('status', self.context.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 self.context.status not in [ 'draft', 'claim', 'answered', 'pending', 'accepted', 'stopping' ] and tender.status in ['active.qualification', 'active.awarded']: check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( 'Updated tender complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_complaint_patch'})) return {'data': self.context.serialize("view")}
def check_status(request): tender = request.validated['tender'] now = get_now() for award in tender.awards: if award.status == 'active' and not any( [i.awardID == award.id for i in tender.contracts]): tender.contracts.append( type(tender).contracts.model_class({ 'awardID': award.id, 'suppliers': award.suppliers, 'value': award.value, 'date': now, 'items': [i for i in tender.items if i.relatedLot == award.lotID], 'contractID': '{}-{}{}'.format(tender.tenderID, request.registry.server_id, len(tender.contracts) + 1) })) 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.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.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 patch(self): """Post a complaint resolution """ tender = self.request.validated['tender'] data = self.request.validated['data'] # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in ['draft', 'claim', 'answered'] and data.get('status', self.context.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 self.context.status in ['pending', 'accepted'] and data.get('status', self.context.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 tender.status == 'active.tendering' and self.context.status == 'draft' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status == 'draft' and data.get('status', self.context.status) == 'claim': if get_now() > calculate_business_date(tender.tenderPeriod.endDate, -CLAIM_SUBMIT_TIME, tender, True): raise_operation_error(self.request, 'Can submit claim not later than {0.days} days before tenderPeriod end'.format(CLAIM_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and tender.status == 'active.tendering' and self.context.status in ['draft', 'claim'] and data.get('status', self.context.status) == 'pending': if get_now() > tender.complaintPeriod.endDate: raise_operation_error(self.request, 'Can submit complaint not later than {0.days} days before tenderPeriod end'.format(COMPLAINT_SUBMIT_TIME)) 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 self.context.status == 'answered' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is True and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is False and data.get('status', self.context.status) == 'pending': if get_now() > tender.complaintPeriod.endDate: raise_operation_error(self.request, 'Can submit complaint not later than {0.days} days before tenderPeriod end'.format(COMPLAINT_SUBMIT_TIME)) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() # tender_owner elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get('status', self.context.status) == self.context.status: now = get_now() if now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error(self.request, 'Can update claim only before enquiryPeriod.clarificationsUntil') apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'satisfied' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get('resolution', self.context.resolution) and data.get('resolutionType', self.context.resolutionType) and data.get('status', self.context.status) == 'answered': now = get_now() if now > tender.enquiryPeriod.clarificationsUntil: raise_operation_error(self.request, 'Can update claim only before enquiryPeriod.clarificationsUntil') 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 self.context.status in ['pending', 'accepted']: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'satisfied' and data.get('tendererAction', self.context.tendererAction) and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) # aboveThresholdReviewers elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['pending', 'accepted', 'stopping'] and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['pending', 'stopping'] and data.get('status', self.context.status) in ['invalid', 'mistaken']: 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 self.context.status == 'pending' and data.get('status', self.context.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 self.context.status in ['accepted', 'stopping'] and data.get('status', self.context.status) in ['declined', 'satisfied']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in ['pending', 'accepted', 'stopping'] and data.get('status', self.context.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 self.context.status not in ['draft', 'claim', 'answered', 'pending', 'accepted', 'stopping'] and tender.status in ['active.qualification', 'active.awarded']: check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info('Updated tender complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_complaint_patch'})) return {'data': self.context.serialize("view")}
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
def check_status(request): tender = request.validated['tender'] now = get_now() for award in tender.awards: if award.status == 'active' and not any([i.awardID == award.id for i in tender.contracts]): tender.contracts.append(type(tender).contracts.model_class({ 'awardID': award.id, 'suppliers': award.suppliers, 'value': award.value, 'date': now, 'items': [i for i in tender.items if i.relatedLot == award.lotID], 'contractID': '{}-{}{}'.format(tender.tenderID, request.registry.server_id, len(tender.contracts) + 1)})) 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.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.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 patch(self): """Post a complaint resolution """ tender = self.request.validated["tender"] data = self.request.validated["data"] # complaint_owner if (self.request.authenticated_role == "complaint_owner" and self.context.status in ["draft", "claim", "answered"] and data.get("status", self.context.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 self.context.status in ["pending", "accepted"] and data.get("status", self.context.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 tender.status == "active.tendering" and self.context.status == "draft" and data.get( "status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "complaint_owner" and tender.status == "active.tendering" and self.context.status == "draft" and data.get("status", self.context.status) == "claim"): validate_submit_claim_time(self.request) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif (self.request.authenticated_role == "complaint_owner" and tender.status == "active.tendering" and self.context.status in ["draft", "claim"] and data.get("status", self.context.status) == "pending"): validate_submit_complaint_time(self.request) 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 self.context.status == "answered" and data.get( "status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "complaint_owner" and self.context.status == "answered" and data.get("satisfied", self.context.satisfied) is True and data.get("status", self.context.status) == "resolved"): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "complaint_owner" and self.context.status == "answered" and data.get("satisfied", self.context.satisfied) is False and data.get("status", self.context.status) == "pending"): validate_submit_complaint_time(self.request) apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = "complaint" self.context.dateEscalated = get_now() # tender_owner elif (self.request.authenticated_role == "tender_owner" and self.context.status == "claim" and data.get( "status", self.context.status) == self.context.status): validate_update_claim_time(self.request) apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "tender_owner" and self.context.status == "satisfied" and data.get( "status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "tender_owner" and self.context.status == "claim" and data.get("resolution", self.context.resolution) and data.get("resolutionType", self.context.resolutionType) and data.get("status", self.context.status) == "answered"): validate_update_claim_time(self.request) 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 self.context.status in [ "pending", "accepted" ]: apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "tender_owner" and self.context.status == "satisfied" and data.get("tendererAction", self.context.tendererAction) and data.get("status", self.context.status) == "resolved"): apply_patch(self.request, save=False, src=self.context.serialize()) # aboveThresholdReviewers elif (self.request.authenticated_role == "aboveThresholdReviewers" and self.context.status in ["pending", "accepted", "stopping"] and data.get("status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "aboveThresholdReviewers" and self.context.status in ["pending", "stopping"] and data.get( "status", self.context.status) in ["invalid", "mistaken"]): 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 self.context.status == "pending" and data.get("status", self.context.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 self.context.status in ["accepted", "stopping"] and data.get( "status", self.context.status) in ["declined", "satisfied"]): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif (self.request.authenticated_role == "aboveThresholdReviewers" and self.context.status in ["pending", "accepted", "stopping"] and data.get("status", self.context.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 self.context.status not in [ "draft", "claim", "answered", "pending", "accepted", "stopping", ] and tender.status in ["active.qualification", "active.awarded"]: check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( "Updated tender complaint {}".format(self.context.id), extra=context_unpack(self.request, {"MESSAGE_ID": "tender_complaint_patch"}), ) return {"data": self.context.serialize("view")}
def patch(self): """Post a complaint resolution """ tender = self.request.validated["tender"] data = self.request.validated["data"] # complaint_owner if (self.request.authenticated_role == "complaint_owner" and self.context.status in ["draft", "claim", "answered"] and data.get("status", self.context.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 tender.status in ["active.enquiries", "active.tendering"] and self.context.status == "draft" and data.get( "status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "complaint_owner" and tender.status in ["active.enquiries", "active.tendering"] and self.context.status == "draft" and data.get("status", self.context.status) == "claim"): apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif (self.request.authenticated_role == "complaint_owner" and self.context.status == "answered" and data.get( "status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "complaint_owner" and self.context.status == "answered" and isinstance( data.get("satisfied", self.context.satisfied), bool) and data.get("status", self.context.status) == "resolved"): apply_patch(self.request, save=False, src=self.context.serialize()) # tender_owner elif (self.request.authenticated_role == "tender_owner" and self.context.status == "claim" and data.get( "status", self.context.status) == self.context.status): apply_patch(self.request, save=False, src=self.context.serialize()) elif (self.request.authenticated_role == "tender_owner" and self.context.status == "claim" and data.get("resolution", self.context.resolution) and data.get("resolutionType", self.context.resolutionType) and data.get("status", self.context.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() 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 self.context.status not in ["draft", "claim", "answered" ] and tender.status in [ "active.qualification", "active.awarded", ]: check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( "Updated tender complaint {}".format(self.context.id), extra=context_unpack(self.request, {"MESSAGE_ID": "tender_complaint_patch"}), ) return {"data": self.context.serialize("view")}
def patch(self): """Post a complaint resolution for award """ tender = self.request.validated['tender'] data = self.request.validated['data'] complaintPeriod = self.request.validated['award'].complaintPeriod is_complaintPeriod = complaintPeriod.startDate < get_now( ) and complaintPeriod.endDate > get_now( ) if complaintPeriod.endDate else complaintPeriod.startDate < get_now( ) # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in [ 'draft', 'claim', 'answered' ] and data.get('status', self.context.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 self.context.status in [ 'pending', 'accepted' ] and data.get('status', self.context.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_complaintPeriod and self.context.status == 'draft' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and is_complaintPeriod and self.context.status == 'draft' and data.get( 'status', self.context.status) == 'claim': if self.request.validated[ 'award'].status == 'unsuccessful' and self.request.validated[ 'award'].bid_id != self.context.bid_id: raise_operation_error( self.request, 'Can add claim only on unsuccessful award 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_complaintPeriod and self.context.status == 'draft' and data.get( 'status', self.context.status) == 'pending': if not any([ i.status == 'active' for i in tender.awards if i.lotID == self.request.validated['award'].lotID ]): raise_operation_error( self.request, 'Complaint submission is allowed only after award activation.' ) 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 self.context.status == 'answered' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) # tender_owner elif self.request.authenticated_role == 'tender_owner' and self.context.status in [ 'pending', 'accepted' ]: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status in [ 'claim', 'satisfied' ] and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'resolution', self.context.resolution) and data.get( 'resolutionType', self.context.resolutionType) and data.get( 'status', self.context.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 self.context.status == 'satisfied' and data.get( 'tendererAction', self.context.tendererAction) and data.get( 'status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) # aboveThresholdReviewers elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in [ 'pending', 'accepted', 'stopping' ] and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in [ 'pending', 'stopping' ] and data.get('status', self.context.status) in ['invalid', 'mistaken']: 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 self.context.status == 'pending' and data.get( 'status', self.context.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 self.context.status in [ 'accepted', 'stopping' ] and data.get('status', self.context.status) in ['declined', 'satisfied']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() elif self.request.authenticated_role == 'aboveThresholdReviewers' and self.context.status in [ 'pending', 'accepted', 'stopping' ] and data.get('status', self.context.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 self.context.status not in [ 'draft', 'claim', 'answered', 'pending', 'accepted', 'satisfied', 'stopping' ] and tender.status in ['active.qualification', 'active.awarded']: 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 check_status(request): tender = request.validated["tender"] now = get_now() configurator = request.content_configurator 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 ( 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 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" remove_draft_bids(request) 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.endDate] if not standStillEnds: return standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) 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.endDate] if not standStillEnds: continue standStillEnd = max(standStillEnds) if standStillEnd <= now: check_tender_status(request) return
def patch(self): """Post a complaint resolution """ tender = self.request.validated['tender'] data = self.request.validated['data'] # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in [ 'draft', 'claim', 'answered' ] and data.get('status', self.context.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 tender.status in [ 'active.enquiries', 'active.tendering' ] and self.context.status == 'draft' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and tender.status in [ 'active.enquiries', 'active.tendering' ] and self.context.status == 'draft' and data.get( 'status', self.context.status) == 'claim': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and isinstance( data.get('satisfied', self.context.satisfied), bool) and data.get( 'status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) # elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is False and data.get('status', self.context.status) == 'pending': # apply_patch(self.request, save=False, src=self.context.serialize()) # self.context.type = 'complaint' # self.context.dateEscalated = get_now() # tender_owner elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'tender_owner' and self.context.status == 'claim' and data.get( 'resolution', self.context.resolution) and data.get( 'resolutionType', self.context.resolutionType) and data.get( 'status', self.context.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 self.context.status == 'pending': # apply_patch(self.request, save=False, src=self.context.serialize()) # reviewers # elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) == self.context.status: # apply_patch(self.request, save=False, src=self.context.serialize()) # elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) in ['resolved', 'invalid', 'declined']: # apply_patch(self.request, save=False, src=self.context.serialize()) # self.context.dateDecision = 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 self.context.status not in [ 'draft', 'claim', 'answered' ] and tender.status in ['active.qualification', 'active.awarded']: check_tender_status(self.request) if save_tender(self.request): self.LOGGER.info( 'Updated tender complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_complaint_patch'})) return {'data': self.context.serialize("view")}