예제 #1
0
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)
예제 #2
0
def process_new_defense_complaints(request):
    tender = request.validated["tender"]
    first_revision_date = get_first_revision_date(tender)
    new_defence_complaints = NEW_DEFENSE_COMPLAINTS_FROM < first_revision_date < NEW_DEFENSE_COMPLAINTS_TO
    if not new_defence_complaints:
        return

    if tender.lots:
        statuses = set()
        for lot in tender.lots:
            if lot.status != "active":
                continue
            lot_awards = [i for i in tender.awards if i.lotID == lot.id]
            statuses.add(
                lot_awards[-1].status if lot_awards else "unsuccessful")

        if statuses == set(["unsuccessful"]):
            for lot in tender.lots:
                if lot.status != "active":
                    continue
                pending_complaints = any([
                    i["status"] in tender.block_complaint_status
                    and i.relatedLot == lot.id for i in tender.complaints
                ])
                lot_awards = [i for i in tender.awards if i.lotID == lot.id]
                if not lot_awards:
                    continue
                awards_no_complaint_periods = all([
                    not a.complaintPeriod for a in lot_awards
                    if a["status"] == "unsuccessful"
                ])
                if (not pending_complaints and awards_no_complaint_periods):
                    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"

            lot_statuses = set([lot.status for lot in tender.lots])
            if not lot_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"

    else:
        if not tender.awards[-1].status == "pending":
            pending_complaints = any([
                i["status"] in tender.block_complaint_status
                for i in tender.complaints
            ])
            last_award_unsuccessful = tender.awards[
                -1].status == "unsuccessful"
            awards_no_complaint_periods = all([
                not a.complaintPeriod for a in tender.awards
                if a["status"] == "unsuccessful"
            ])
            if (not pending_complaints and last_award_unsuccessful
                    and awards_no_complaint_periods):
                LOGGER.info(
                    "Switched tender {} to {}".format(tender.id,
                                                      "unsuccessful"),
                    extra=context_unpack(
                        request,
                        {"MESSAGE_ID": "switched_tender_unsuccessful"}),
                )
                tender.status = "unsuccessful"
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)
예제 #4
0
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)
예제 #5
0
def add_next_award(request, reverse=False, awarding_criteria_key="amount"):
    """Adding next award.
    reverse and awarding_criteria_key are deprecated, since we can get them from request
    :param request:
        The pyramid request object.
    :param reverse:
        Is used for sorting bids to generate award.
        By default (reverse = False) awards are generated from lower to higher by value.amount
        When reverse is set to True awards are generated from higher to lower by value.amount
    """
    tender = request.validated["tender"]
    now = get_now()
    if not tender.awardPeriod:
        tender.awardPeriod = type(tender).awardPeriod({})
    if not tender.awardPeriod.startDate:
        tender.awardPeriod.startDate = now
    if tender.lots:
        statuses = set()
        for lot in tender.lots:
            if lot.status != "active":
                continue
            lot_awards = [i for i in tender.awards if i.lotID == lot.id]
            if lot_awards and lot_awards[-1].status in ["pending", "active"]:
                statuses.add(
                    lot_awards[-1].status if lot_awards else "unsuccessful")
                continue
            all_bids = prepare_bids_for_awarding(tender,
                                                 tender.bids,
                                                 lot_id=lot.id)
            if all_bids:
                bids = exclude_unsuccessful_awarded_bids(tender,
                                                         all_bids,
                                                         lot_id=lot.id)
                if bids:
                    tender.append_award(bids[0], all_bids, lot_id=lot.id)
                    request.response.headers["Location"] = request.route_url(
                        "{}:Tender Awards".format(
                            tender.procurementMethodType),
                        tender_id=tender.id,
                        award_id=tender.awards[-1]["id"])
                    statuses.add("pending")
                else:
                    statuses.add("unsuccessful")
            else:
                lot.status = "unsuccessful"
                statuses.add("unsuccessful")

        if statuses.difference(set(["unsuccessful", "active"])):
            tender.awardPeriod.endDate = None
            tender.status = "active.qualification"
        else:
            tender.awardPeriod.endDate = now
            tender.status = "active.awarded"

            first_revision_date = get_first_revision_date(tender)
            new_defence_complaints = NEW_DEFENSE_COMPLAINTS_FROM < first_revision_date < NEW_DEFENSE_COMPLAINTS_TO
            if new_defence_complaints and statuses == set(["unsuccessful"]):
                for lot in tender.lots:
                    if lot.status != "active":
                        continue
                    pending_complaints = any([
                        i["status"] in tender.block_complaint_status
                        and i.relatedLot == lot.id for i in tender.complaints
                    ])
                    lot_awards = [
                        i for i in tender.awards if i.lotID == lot.id
                    ]
                    if not lot_awards:
                        continue
                    awards_no_complaint_periods = all([
                        not a.complaintPeriod for a in lot_awards
                        if a["status"] == "unsuccessful"
                    ])
                    if (not pending_complaints
                            and awards_no_complaint_periods):
                        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"

                lot_statuses = set([lot.status for lot in tender.lots])
                if not lot_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"

    else:
        if not tender.awards or tender.awards[-1].status not in [
                "pending", "active"
        ]:
            all_bids = prepare_bids_for_awarding(tender,
                                                 tender.bids,
                                                 lot_id=None)
            bids = exclude_unsuccessful_awarded_bids(tender,
                                                     all_bids,
                                                     lot_id=None)
            if bids:
                tender.append_award(bids[0], all_bids)
                request.response.headers["Location"] = request.route_url(
                    "{}:Tender Awards".format(tender.procurementMethodType),
                    tender_id=tender.id,
                    award_id=tender.awards[-1]["id"])
        if tender.awards[-1].status == "pending":
            tender.awardPeriod.endDate = None
            tender.status = "active.qualification"
        else:
            tender.awardPeriod.endDate = now
            tender.status = "active.awarded"

            first_revision_date = get_first_revision_date(tender)
            new_defence_complaints = NEW_DEFENSE_COMPLAINTS_FROM < first_revision_date < NEW_DEFENSE_COMPLAINTS_TO
            if new_defence_complaints:
                pending_complaints = any([
                    i["status"] in tender.block_complaint_status
                    for i in tender.complaints
                ])
                last_award_unsuccessful = tender.awards[
                    -1].status == "unsuccessful"
                awards_no_complaint_periods = all([
                    not a.complaintPeriod for a in tender.awards
                    if a["status"] == "unsuccessful"
                ])
                if (not pending_complaints and last_award_unsuccessful
                        and awards_no_complaint_periods):
                    LOGGER.info(
                        "Switched tender {} to {}".format(
                            tender.id, "unsuccessful"),
                        extra=context_unpack(
                            request,
                            {"MESSAGE_ID": "switched_tender_unsuccessful"}),
                    )
                    tender.status = "unsuccessful"