def amountPerformance_npv(self):
     """ Calculated energy service contract performance indicator """
     return to_decimal(
         npv(self.contractDuration.years, self.contractDuration.days,
             self.yearlyPaymentsPercentage, self.annualCostsReduction,
             get_tender(self).noticePublicationDate,
             get_tender(self).NBUdiscountRate))
예제 #2
0
    def test_get_tender(self):
        period = PeriodEndRequired({
            'startDate': datetime.now(TZ).isoformat(),
            'endDate': datetime.now(TZ).isoformat()
        })
        second_period = PeriodEndRequired({
            'startDate':
            datetime.now(TZ).isoformat(),
            'endDate':
            datetime.now(TZ).isoformat()
        })
        tender = Tender()
        period._data['__parent__'] = tender
        second_period._data['__parent__'] = period

        parent_tender = get_tender(second_period)
        self.assertEqual(tender, parent_tender)
        self.assertIsInstance(parent_tender, Tender)
        self.assertIsInstance(tender, Tender)

        period._data['__parent__'] = None
        with self.assertRaises(AttributeError) as e:
            get_tender(second_period)
        self.assertEqual(e.exception.message,
                         "'NoneType' object has no attribute '__parent__'")
예제 #3
0
 def amountPerfomance_npv(self):
     """ Calculated energy service contract perfomance indicator """
     return float(npv(self.contractDuration.years,
                      self.contractDuration.days,
                      self.yearlyPaymentsPercentage,
                      self.annualCostsReduction,
                      get_tender(self).__class__.announcementDate or get_tender(self).enquiryPeriod.startDate,
                      get_tender(self).NBUdiscountRate))
예제 #4
0
 def validate_yearlyPaymentsPercentage(self, data, value):
     if get_tender(data['__parent__']).fundingKind == 'other' and (
             value < Decimal('0.8') or value > Decimal('1')):
         raise ValidationError(
             'yearlyPaymentsPercentage should be greater than 0.8 and less than 1'
         )
     if get_tender(data['__parent__']).fundingKind == 'budget' and (
             value < Decimal('0') or value > get_tender(
                 data['__parent__']).yearlyPaymentsPercentageRange):
         raise ValidationError(
             'yearlyPaymentsPercentage should be greater than 0 and less than {}'
             .format(
                 get_tender(
                     data['__parent__']).yearlyPaymentsPercentageRange))
예제 #5
0
 def validate_reviewPlace(self, data, reviewPlace):
     tender_date = get_first_revision_date(get_tender(data["__parent__"]),
                                           default=get_now())
     if tender_date < RELEASE_2020_04_19:
         return
     if not reviewPlace and data.get("status") == "accepted":
         raise ValidationError(u"This field is required.")
 def validate_startDate(self, data, value):
     tender = get_tender(data['__parent__'])
     if (tender.revisions[0].date
             if tender.revisions else get_now()) < PERIOD_END_REQUIRED_FROM:
         return
     if value and data.get('endDate') and data.get('endDate') < value:
         raise ValidationError(u"period should begin before its end")
 def validate_relatedLot(self, data, relatedLot):
     if isinstance(data['__parent__'], Model) and (
             data['__parent__'].status
             not in ('invalid', 'deleted', 'draft')) and relatedLot not in [
                 i.id for i in get_tender(data['__parent__']).lots
             ]:
         raise ValidationError(u"relatedLot should be one of lots")
예제 #8
0
 def validate_startDate(self, data, value):
     tender = get_tender(data["__parent__"])
     tender_date = get_first_revision_date(tender, default=get_now())
     if tender_date < PERIOD_END_REQUIRED_FROM:
         return
     if value and data.get("endDate") and data.get("endDate") < value:
         raise ValidationError(u"period should begin before its end")
예제 #9
0
 def shouldStartAfter(self):
     if self.endDate:
         return
     tender = get_tender(self)
     lot = self.__parent__
     if (tender.status not in [
             "active.tendering", "active.pre-qualification.stand-still",
             "active.auction"
     ] or lot.status != "active"):
         return
     start_after = None
     if tender.status == "active.tendering" and tender.tenderPeriod.endDate:
         start_after = calculate_tender_business_date(
             tender.tenderPeriod.endDate, TENDERING_AUCTION, tender)
     elif self.startDate and get_now() > calc_auction_end_time(
             lot.numberOfBids, self.startDate):
         start_after = calc_auction_end_time(lot.numberOfBids,
                                             self.startDate)
     elif tender.qualificationPeriod and tender.qualificationPeriod.endDate:
         decision_dates = [
             datetime.combine(
                 complaint.dateDecision.date() + timedelta(days=3),
                 time(0, tzinfo=complaint.dateDecision.tzinfo))
             for qualification in tender.qualifications
             for complaint in qualification.complaints
             if complaint.dateDecision
         ]
         decision_dates.append(tender.qualificationPeriod.endDate)
         start_after = max(decision_dates)
     if start_after:
         return rounding_shouldStartAfter(start_after, tender).isoformat()
예제 #10
0
 def serialize(self, role=None, context=None):
     if role == 'view' and self.type == 'claim' and get_tender(
             self).status in [
                 'active.tendering', 'active.pre-qualification',
                 'active.pre-qualification.stand-still', 'active.auction'
             ]:
         role = 'view_claim'
     return super(Complaint, self).serialize(role=role, context=context)
 def validate_value(self, data, value):
     if value and isinstance(data['__parent__'], Model) and (data['__parent__'].status not in ('invalid', 'deleted', 'draft')) and data['relatedLot']:
         lots = [i for i in get_tender(data['__parent__']).lots if i.id == data['relatedLot']]
         if not lots:
             return
         lot = lots[0]
         if lot.minValue.amount > value.amount:
             raise ValidationError(u"value of bid should be greater than minValue of lot")
예제 #12
0
 def amount_escp(self):
     return to_decimal(
         escp(
             self.contractDuration.years,
             self.contractDuration.days,
             self.yearlyPaymentsPercentage,
             self.annualCostsReduction,
             get_tender(self).noticePublicationDate,
         ))
예제 #13
0
 def validate_relatedItem(self, data, relatedItem):
     if not relatedItem and data.get("documentOf") in ["item"]:
         raise ValidationError(u"This field is required.")
     parent = data["__parent__"]
     if relatedItem and isinstance(parent, Model):
         tender = get_tender(parent)
         items = [i.id for i in tender.items if i]
         if data.get("documentOf") == "item" and relatedItem not in items:
             raise ValidationError(u"relatedItem should be one of items")
예제 #14
0
 def validate_rejectReason(self, data, rejectReason):
     tender_date = get_first_revision_date(get_tender(data["__parent__"]),
                                           default=get_now())
     if tender_date < RELEASE_2020_04_19:
         return
     if not rejectReason and data.get("status") in [
             "invalid", "stopped"
     ] and data.get("type") == "complaint":
         raise ValidationError(u"This field is required.")
예제 #15
0
 def validate_relatedBuyer(self, data, related_buyer):
     tender = get_tender(data["__parent__"])
     validation_date = get_first_revision_date(tender, default=get_now())
     validation_enabled = all([
         tender.buyers, tender.status != "draft",
         validation_date >= MULTI_CONTRACTS_REQUIRED_FROM
     ])
     if validation_enabled and not related_buyer:
         raise ValidationError(BaseType.MESSAGES["required"])
예제 #16
0
 def serialize(self, role=None, context=None):
     if (role == "view" and self.type == "claim"
             and get_tender(self).status in [
                 "active.tendering",
                 "active.pre-qualification",
                 "active.pre-qualification.stand-still",
                 "active.auction",
             ]):
         role = "view_claim"
     return super(Complaint, self).serialize(role=role, context=context)
 def validate_value(self, data, value):
     if value and isinstance(data['__parent__'], Model) and (data['__parent__'].status not in ('invalid', 'deleted', 'draft')) and data['relatedLot']:
         lots = [i for i in get_tender(data['__parent__']).lots if i.id == data['relatedLot']]
         if not lots:
             return
         lot = lots[0]
         if lot.value.amount < value.amount:
             raise ValidationError(u"value of bid should be less than value of lot")
         if lot.get('value').currency != value.currency:
             raise ValidationError(u"currency of bid should be identical to currency of value of lot")
         if lot.get('value').valueAddedTaxIncluded != value.valueAddedTaxIncluded:
             raise ValidationError(u"valueAddedTaxIncluded of bid should be identical to valueAddedTaxIncluded of value of lot")
예제 #18
0
 def validate_value(self, data, value):
     parent = data["__parent__"]
     if value and isinstance(parent, Model) and parent.status not in self.skip and data["relatedLot"]:
         lots = [lot for lot in get_tender(parent).lots if lot and lot.id == data["relatedLot"]]
         if not lots:
             return
         lot = lots[0]
         if lot.get("minValue").currency != value.currency:
             raise ValidationError(u"currency of bid should be identical to currency of minValue of lot")
         if lot.get("minValue").valueAddedTaxIncluded != value.valueAddedTaxIncluded:
             raise ValidationError(
                 u"valueAddedTaxIncluded of bid should be identical to valueAddedTaxIncluded of minValue of lot"
             )
예제 #19
0
 def validate_value(self, data, value):
     if value and isinstance(data['__parent__'], Model) and (data['__parent__'].status not in ('invalid', 'deleted', 'draft')) and data['relatedLot']:
         lots = [i for i in get_tender(data['__parent__']).lots if i.id == data['relatedLot']]
         if not lots:
             return
         lot = lots[0]
         tender = lot['__parent__']
         amount = calculate_npv(tender.NBUdiscountRate, value.annualCostsReduction, value.yearlyPayments, value.contractDuration)  #XXX: Calculating value.amount manually
         if lot.minValue.amount > amount:
             raise ValidationError(u"value of bid should be greater than minValue of lot")
         if lot.get('minValue').currency != value.currency:
             raise ValidationError(u"currency of bid should be identical to currency of minValue of lot")
         if lot.get('minValue').valueAddedTaxIncluded != value.valueAddedTaxIncluded:
             raise ValidationError(u"valueAddedTaxIncluded of bid should be identical to valueAddedTaxIncluded of minValue of lot")
예제 #20
0
 def shouldStartAfter(self):
     if self.endDate:
         return
     tender = get_tender(self)
     lot = self.__parent__
     if tender.status not in ["active.tendering", "active.auction"] or lot.status != "active":
         return
     if tender.status == "active.auction" and lot.numberOfBids < 2:
         return
     if self.startDate and get_now() > calc_auction_end_time(lot.numberOfBids, self.startDate):
         start_after = calc_auction_end_time(tender.numberOfBids, self.startDate)
     else:
         start_after = tender.tenderPeriod.endDate
     return rounding_shouldStartAfter(start_after, tender).isoformat()
 def shouldStartAfter(self):
     if self.endDate:
         return
     tender = get_tender(self)
     lot = self.__parent__
     if tender.status not in ['active.tendering', 'active.auction'] or lot.status != 'active':
         return
     if tender.status == 'active.auction' and lot.numberOfBids < 2:
         return
     if self.startDate and get_now() > calc_auction_end_time(lot.numberOfBids, self.startDate):
         return calc_auction_end_time(lot.numberOfBids, self.startDate).isoformat()
     else:
         decision_dates = [
             datetime.combine(complaint.dateDecision.date() + timedelta(days=3), time(0, tzinfo=complaint.dateDecision.tzinfo))
             for complaint in tender.complaints
             if complaint.dateDecision
         ]
         decision_dates.append(tender.tenderPeriod.endDate)
         return max(decision_dates).isoformat()
예제 #22
0
    def validate_yearlyPaymentsPercentage(self, data, value):
        parent = data["__parent__"]
        tender = get_tender(parent)

        if tender.fundingKind == "other" and value < Decimal("0.8"):
            raise ValidationError(
                "yearlyPaymentsPercentage should be greater than 0.8 and less than 1"
            )
        if tender.fundingKind == "budget":
            if tender.lots:
                lots = [i for i in tender.lots if i.id == parent["relatedLot"]]

                if lots and value > lots[0].yearlyPaymentsPercentageRange:
                    raise ValidationError(
                        "yearlyPaymentsPercentage should be greater than 0 and less than {}"
                        .format(lots[0].yearlyPaymentsPercentageRange))
            else:
                if value > tender.yearlyPaymentsPercentageRange:
                    raise ValidationError(
                        "yearlyPaymentsPercentage should be greater than 0 and less than {}"
                        .format(tender.yearlyPaymentsPercentageRange))
예제 #23
0
 def shouldStartAfter(self):
     if self.endDate:
         return
     tender = get_tender(self)
     lot = self.__parent__
     if tender.status not in [
             'active.tendering', 'active.pre-qualification.stand-still',
             'active.auction'
     ] or lot.status != 'active':
         return
     start_after = None
     if tender.status == 'active.tendering' and tender.tenderPeriod.endDate:
         start_after = calculate_business_date(tender.tenderPeriod.endDate,
                                               TENDERING_AUCTION, tender)
     elif self.startDate and get_now() > calc_auction_end_time(
             lot.numberOfBids, self.startDate):
         start_after = calc_auction_end_time(lot.numberOfBids,
                                             self.startDate)
     elif tender.qualificationPeriod and tender.qualificationPeriod.endDate:
         start_after = tender.qualificationPeriod.endDate
     if start_after:
         return rounding_shouldStartAfter(start_after, tender).isoformat()
    def validate_yearlyPaymentsPercentage(self, data, value):
        tender = get_tender(data['__parent__'])

        if tender.fundingKind == 'other' and value < Decimal('0.8'):
            raise ValidationError(
                'yearlyPaymentsPercentage should be greater than 0.8 and less than 1'
            )
        if tender.fundingKind == 'budget':
            if tender.lots:
                lots = [
                    i for i in tender.lots
                    if i.id == data['__parent__']['relatedLot']
                ]

                if lots and value > lots[0].yearlyPaymentsPercentageRange:
                    raise ValidationError(
                        'yearlyPaymentsPercentage should be greater than 0 and less than {}'
                        .format(lots[0].yearlyPaymentsPercentageRange))
            else:
                if value > tender.yearlyPaymentsPercentageRange:
                    raise ValidationError(
                        'yearlyPaymentsPercentage should be greater than 0 and less than {}'
                        .format(tender.yearlyPaymentsPercentageRange))
 def shouldStartAfter(self):
     if self.endDate:
         return
     tender = get_tender(self)
     lot = self.__parent__
     if tender.status not in ['active.tendering', 'active.auction'
                              ] or lot.status != 'active':
         return
     if tender.status == 'active.auction' and lot.numberOfBids < 2:
         return
     if self.startDate and get_now() > calc_auction_end_time(
             lot.numberOfBids, self.startDate):
         return calc_auction_end_time(lot.numberOfBids,
                                      self.startDate).isoformat()
     else:
         decision_dates = [
             datetime.combine(
                 complaint.dateDecision.date() + timedelta(days=3),
                 time(0, tzinfo=complaint.dateDecision.tzinfo))
             for complaint in tender.complaints if complaint.dateDecision
         ]
         decision_dates.append(tender.tenderPeriod.endDate)
         return max(decision_dates).isoformat()
예제 #26
0
 def validate_relatedLot(self, data, relatedLot):
     parent = data["__parent__"]
     if isinstance(parent, Model) and parent.status not in self.skip:
         validate_relatedlot(get_tender(parent), relatedLot)
예제 #27
0
 def validate_value(self, data, value):
     parent = data["__parent__"]
     if isinstance(parent, Bid) and parent.status not in self.skip:
         validate_lotvalue_value(get_tender(parent), data["relatedLot"],
                                 value)
 def validate_id(self, data, lot_id):
     if lot_id and isinstance(data['__parent__'], Model) and lot_id not in [i.id for i in get_tender(data['__parent__']).lots]:
         raise ValidationError(u"id should be one of lots")
 def validate_value(self, data, value):
     if value and isinstance(data['__parent__'], Bid) and (
             data['__parent__'].status
             not in ('invalid', 'deleted', 'draft')) and data['relatedLot']:
         validate_LotValue_value(get_tender(data['__parent__']),
                                 data['relatedLot'], value)
예제 #30
0
 def validate_id(self, data, lot_id):
     parent = data["__parent__"]
     if lot_id and isinstance(parent, Model) and lot_id not in [
             lot.id for lot in get_tender(parent).lots if lot
     ]:
         raise ValidationError(u"id should be one of lots")
예제 #31
0
 def validate_quantity(self, data, value):
     tender = get_tender(data["__parent__"])
     validation_date = get_first_revision_date(tender, default=get_now())
     if validation_date >= UNIT_PRICE_REQUIRED_FROM and value is None:
         raise ValidationError(BaseType.MESSAGES["required"])
 def validate_id(self, data, lot_id):
     if lot_id and isinstance(data['__parent__'], Model) and lot_id not in [
             i.id for i in get_tender(data['__parent__']).lots
     ]:
         raise ValidationError(u"id should be one of lots")