Exemplo n.º 1
0
    def patch(self):
        """Tender Edit (partial)

        For example here is how procuring entity can change number of items to be procured and total Value of a tender:

        .. sourcecode:: http

            PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607 HTTP/1.1
            Host: example.com
            Accept: application/json

            {
                "data": {
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        And here is the response to be expected:

        .. sourcecode:: http

            HTTP/1.0 200 OK
            Content-Type: application/json

            {
                "data": {
                    "id": "4879d3f8ee2443169b5fbbc9f89fa607",
                    "tenderID": "UA-64e93250be76435397e8c992ed4214d1",
                    "dateModified": "2014-10-27T08:12:34.956Z",
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        """
        tender = self.context
        config = getAdapter(tender, IContentConfigurator)
        data = self.request.validated["data"]
        now = get_now()
        if (self.request.authenticated_role == "tender_owner" and
                self.request.validated["tender_status"] == "active.tendering"):
            if "tenderPeriod" in data and "endDate" in data["tenderPeriod"]:
                self.request.validated["tender"].tenderPeriod.import_data(
                    data["tenderPeriod"])
                validate_tender_period_extension(self.request)
                self.request.registry.notify(
                    TenderInitializeEvent(self.request.validated["tender"]))
                self.request.validated["data"][
                    "enquiryPeriod"] = self.request.validated[
                        "tender"].enquiryPeriod.serialize()

        apply_patch(self.request,
                    save=False,
                    src=self.request.validated["tender_src"])
        if self.request.authenticated_role == "chronograph":
            check_status(self.request)
        elif self.request.authenticated_role == "tender_owner" and tender.status == "active.tendering":
            tender.invalidate_bids_data()
        elif (self.request.authenticated_role == "tender_owner"
              and self.request.validated["tender_status"]
              == "active.pre-qualification"
              and tender.status == "active.pre-qualification.stand-still"):
            active_lots = [
                lot.id for lot in tender.lots if lot.status == "active"
            ] if tender.lots else [None]
            if any([
                    i["status"]
                    in self.request.validated["tender"].block_complaint_status
                    for q in self.request.validated["tender"]["qualifications"]
                    for i in q["complaints"] if q["lotID"] in active_lots
            ]):
                raise_operation_error(
                    self.request,
                    "Can't switch to 'active.pre-qualification.stand-still' before resolve all complaints"
                )
            if all_bids_are_reviewed(self.request):
                tender.qualificationPeriod.endDate = calculate_complaint_business_date(
                    now, config.prequalification_complaint_stand_still,
                    self.request.validated["tender"])
                tender.check_auction_time()
            else:
                raise_operation_error(
                    self.request,
                    "Can't switch to 'active.pre-qualification.stand-still' while not all bids are qualified",
                )
        elif (self.request.authenticated_role == "tender_owner" and
              self.request.validated["tender_status"] == "active.qualification"
              and tender.status == "active.qualification.stand-still"):
            active_lots = [
                lot.id for lot in tender.lots if lot.status == "active"
            ] if tender.lots else [None]
            if any([
                    i["status"]
                    in self.request.validated["tender"].block_complaint_status
                    for a in self.request.validated["tender"]["awards"]
                    for i in a["complaints"] if a["lotID"] in active_lots
            ]):
                raise_operation_error(
                    self.request,
                    "Can't switch to 'active.qualification.stand-still' before resolve all complaints"
                )
            if all_awards_are_reviewed(self.request):
                tender.awardPeriod.endDate = calculate_complaint_business_date(
                    now, config.qualification_complaint_stand_still,
                    self.request.validated["tender"])
                for award in [
                        a for a in tender.awards if a.status != "cancelled"
                ]:
                    award["complaintPeriod"] = {
                        "startDate": now.isoformat(),
                        "endDate": tender.awardPeriod.endDate.isoformat(),
                    }
            else:
                raise_operation_error(
                    self.request,
                    "Can't switch to 'active.qualification.stand-still' while not all awards are qualified",
                )

        save_tender(self.request)
        self.LOGGER.info("Updated tender {}".format(tender.id),
                         extra=context_unpack(self.request,
                                              {"MESSAGE_ID": "tender_patch"}))
        return {"data": tender.serialize(tender.status)}
Exemplo n.º 2
0
    def patch(self):
        """Tender Edit (partial)

        For example here is how procuring entity can change number of items to be procured and total Value of a tender:

        .. sourcecode:: http

            PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607 HTTP/1.1
            Host: example.com
            Accept: application/json

            {
                "data": {
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        And here is the response to be expected:

        .. sourcecode:: http

            HTTP/1.0 200 OK
            Content-Type: application/json

            {
                "data": {
                    "id": "4879d3f8ee2443169b5fbbc9f89fa607",
                    "tenderID": "UA-64e93250be76435397e8c992ed4214d1",
                    "dateModified": "2014-10-27T08:12:34.956Z",
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        """
        tender = self.context
        data = self.request.validated["data"]

        if (self.request.authenticated_role == "tender_owner" and
                self.request.validated["tender_status"] == "active.tendering"):
            if "tenderPeriod" in data and "endDate" in data["tenderPeriod"]:
                self.request.validated["tender"].tenderPeriod.import_data(
                    data["tenderPeriod"])
                validate_tender_period_extension_with_working_days(
                    self.request)
                self.request.registry.notify(
                    TenderInitializeEvent(self.request.validated["tender"]))
                self.request.validated["data"][
                    "enquiryPeriod"] = self.request.validated[
                        "tender"].enquiryPeriod.serialize()

        apply_patch(self.request,
                    save=False,
                    src=self.request.validated["tender_src"])
        if self.request.authenticated_role == "chronograph":
            check_status(self.request)
        elif self.request.authenticated_role == "tender_owner" and tender.status == "active.tendering":
            # invalidate bids on tender change
            tender.invalidate_bids_data()
        save_tender(self.request)
        self.LOGGER.info("Updated tender {}".format(tender.id),
                         extra=context_unpack(self.request,
                                              {"MESSAGE_ID": "tender_patch"}))
        return {"data": tender.serialize(tender.status)}
Exemplo n.º 3
0
Arquivo: tender.py Projeto: lttga/op2
    def patch(self):
        """Tender Edit (partial)

        For example here is how procuring entity can change number of items to be procured and total Value of a tender:

        .. sourcecode:: http

            PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607 HTTP/1.1
            Host: example.com
            Accept: application/json

            {
                "data": {
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        And here is the response to be expected:

        .. sourcecode:: http

            HTTP/1.0 200 OK
            Content-Type: application/json

            {
                "data": {
                    "id": "4879d3f8ee2443169b5fbbc9f89fa607",
                    "tenderID": "UA-64e93250be76435397e8c992ed4214d1",
                    "dateModified": "2014-10-27T08:12:34.956Z",
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        """
        tender = self.context
        data = self.request.validated["data"]
        if self.request.authenticated_role == "tender_owner" and self.request.validated[
                "tender_status"] in [
                    "active.tendering",
                    STAGE2_STATUS,
                ]:
            if "tenderPeriod" in data and "endDate" in data["tenderPeriod"]:
                self.request.validated["tender"].tenderPeriod.import_data(
                    data["tenderPeriod"])
                validate_tender_period_extension(self.request)
                self.request.registry.notify(
                    TenderInitializeEvent(self.request.validated["tender"]))
                self.request.validated["data"][
                    "enquiryPeriod"] = self.request.validated[
                        "tender"].enquiryPeriod.serialize()

        apply_patch(self.request,
                    save=False,
                    src=self.request.validated["tender_src"])
        if self.request.authenticated_role == "chronograph":
            check_status_eu(self.request)
        elif self.request.authenticated_role == "tender_owner" and tender.status == "active.tendering":
            tender.invalidate_bids_data()
        elif (self.request.authenticated_role == "tender_owner"
              and self.request.validated["tender_status"]
              == "active.pre-qualification"
              and tender.status == "active.pre-qualification.stand-still"):
            if all_bids_are_reviewed(self.request):
                tender.qualificationPeriod.endDate = calculate_tender_business_date(
                    get_now(), COMPLAINT_STAND_STILL,
                    self.request.validated["tender"])
                tender.check_auction_time()
            else:
                raise_operation_error(
                    self.request,
                    "Can't switch to 'active.pre-qualification.stand-still' while not all bids are qualified",
                )

        save_tender(self.request)
        self.LOGGER.info("Updated tender {}".format(tender.id),
                         extra=context_unpack(self.request,
                                              {"MESSAGE_ID": "tender_patch"}))
        return {"data": tender.serialize(tender.status)}
    def patch(self):
        """Tender Edit (partial)

        For example here is how procuring entity can change number of items to be procured and total Value of a tender:

        .. sourcecode:: http

            PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607 HTTP/1.1
            Host: example.com
            Accept: application/json

            {
                "data": {
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        And here is the response to be expected:

        .. sourcecode:: http

            HTTP/1.0 200 OK
            Content-Type: application/json

            {
                "data": {
                    "id": "4879d3f8ee2443169b5fbbc9f89fa607",
                    "tenderID": "UA-64e93250be76435397e8c992ed4214d1",
                    "dateModified": "2014-10-27T08:12:34.956Z",
                    "value": {
                        "amount": 600
                    },
                    "itemsToBeProcured": [
                        {
                            "quantity": 6
                        }
                    ]
                }
            }

        """
        tender = self.context
        data = self.request.validated['data']
        if self.request.authenticated_role == 'tender_owner' and self.request.validated['tender_status'] == 'active.tendering':
            if 'tenderPeriod' in data and 'endDate' in data['tenderPeriod']:
                self.request.validated['tender'].tenderPeriod.import_data(data['tenderPeriod'])
                validate_tender_period_extension(self.request)
                self.request.registry.notify(TenderInitializeEvent(self.request.validated['tender']))
                self.request.validated['data']["enquiryPeriod"] = self.request.validated['tender'].enquiryPeriod.serialize()

        apply_patch(self.request, save=False, src=self.request.validated['tender_src'])
        if self.request.authenticated_role == 'chronograph':
            check_status(self.request)
        elif self.request.authenticated_role == 'tender_owner' and tender.status == 'active.tendering':
            tender.invalidate_bids_data()
        elif self.request.authenticated_role == 'tender_owner' and self.request.validated['tender_status'] == 'active.pre-qualification' and tender.status == "active.pre-qualification.stand-still":
            active_lots = [lot.id for lot in tender.lots if lot.status == 'active'] if tender.lots else [None]
            if any([i['status'] in self.request.validated['tender'].block_complaint_status for q in self.request.validated['tender']['qualifications'] for i in q['complaints'] if q['lotID'] in active_lots]):
                raise_operation_error(self.request, 'Can\'t switch to \'active.pre-qualification.stand-still\' before resolve all complaints')
            if all_bids_are_reviewed(self.request):
                normalized_date = calculate_normalized_date(get_now(), tender, True)
                tender.qualificationPeriod.endDate = calculate_business_date(normalized_date, COMPLAINT_STAND_STILL, self.request.validated['tender'])
                tender.check_auction_time()
            else:
                raise_operation_error(self.request, 'Can\'t switch to \'active.pre-qualification.stand-still\' while not all bids are qualified')

        save_tender(self.request)
        self.LOGGER.info('Updated tender {}'.format(tender.id),
                    extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_patch'}))
        return {'data': tender.serialize(tender.status)}
Exemplo n.º 5
0
    def post(self):
        """This API request is targeted to creating new Tenders by procuring organizations.

        Creating new Tender
        -------------------

        Example request to create tender:

        .. sourcecode:: http

            POST /tenders HTTP/1.1
            Host: example.com
            Accept: application/json

            {
                "data": {
                    "procuringEntity": {
                        "id": {
                            "name": "Державне управління справами",
                            "scheme": "https://ns.openprocurement.org/ua/edrpou",
                            "uid": "00037256",
                            "uri": "http://www.dus.gov.ua/"
                        },
                        "address": {
                            "countryName": "Україна",
                            "postalCode": "01220",
                            "region": "м. Київ",
                            "locality": "м. Київ",
                            "streetAddress": "вул. Банкова, 11, корпус 1"
                        }
                    },
                    "value": {
                        "amount": 500,
                        "currency": "UAH",
                        "valueAddedTaxIncluded": true
                    },
                    "itemsToBeProcured": [
                        {
                            "description": "футляри до державних нагород",
                            "primaryClassification": {
                                "scheme": "CPV",
                                "id": "44617100-9",
                                "description": "Cartons"
                            },
                            "additionalClassification": [
                                {
                                    "scheme": "ДКПП",
                                    "id": "17.21.1",
                                    "description": "папір і картон гофровані, паперова й картонна тара"
                                }
                            ],
                            "unitOfMeasure": "item",
                            "quantity": 5
                        }
                    ],
                    "enquiryPeriod": {
                        "endDate": "2014-10-31T00:00:00"
                    },
                    "tenderPeriod": {
                        "startDate": "2014-11-03T00:00:00",
                        "endDate": "2014-11-06T10:00:00"
                    },
                    "awardPeriod": {
                        "endDate": "2014-11-13T00:00:00"
                    },
                    "deliveryDate": {
                        "endDate": "2014-11-20T00:00:00"
                    },
                    "minimalStep": {
                        "amount": 35,
                        "currency": "UAH"
                    }
                }
            }

        This is what one should expect in response:

        .. sourcecode:: http

            HTTP/1.1 201 Created
            Location: http://localhost/api/0.1/tenders/64e93250be76435397e8c992ed4214d1
            Content-Type: application/json

            {
                "data": {
                    "id": "64e93250be76435397e8c992ed4214d1",
                    "tenderID": "UA-64e93250be76435397e8c992ed4214d1",
                    "dateModified": "2014-10-27T08:06:58.158Z",
                    "procuringEntity": {
                        "id": {
                            "name": "Державне управління справами",
                            "scheme": "https://ns.openprocurement.org/ua/edrpou",
                            "uid": "00037256",
                            "uri": "http://www.dus.gov.ua/"
                        },
                        "address": {
                            "countryName": "Україна",
                            "postalCode": "01220",
                            "region": "м. Київ",
                            "locality": "м. Київ",
                            "streetAddress": "вул. Банкова, 11, корпус 1"
                        }
                    },
                    "value": {
                        "amount": 500,
                        "currency": "UAH",
                        "valueAddedTaxIncluded": true
                    },
                    "itemsToBeProcured": [
                        {
                            "description": "футляри до державних нагород",
                            "primaryClassification": {
                                "scheme": "CPV",
                                "id": "44617100-9",
                                "description": "Cartons"
                            },
                            "additionalClassification": [
                                {
                                    "scheme": "ДКПП",
                                    "id": "17.21.1",
                                    "description": "папір і картон гофровані, паперова й картонна тара"
                                }
                            ],
                            "unitOfMeasure": "item",
                            "quantity": 5
                        }
                    ],
                    "enquiryPeriod": {
                        "endDate": "2014-10-31T00:00:00"
                    },
                    "tenderPeriod": {
                        "startDate": "2014-11-03T00:00:00",
                        "endDate": "2014-11-06T10:00:00"
                    },
                    "awardPeriod": {
                        "endDate": "2014-11-13T00:00:00"
                    },
                    "deliveryDate": {
                        "endDate": "2014-11-20T00:00:00"
                    },
                    "minimalStep": {
                        "amount": 35,
                        "currency": "UAH"
                    }
                }
            }

        """
        tender_id = generate_id()
        tender = self.request.validated["tender"]
        tender.id = tender_id
        if not tender.get("tenderID"):
            tender.tenderID = generate_tender_id(get_now(), self.db,
                                                 self.server_id)
        self.request.registry.notify(TenderInitializeEvent(tender))
        if self.request.json["data"].get("status") == "draft":
            tender.status = "draft"
        access = set_ownership(tender, self.request)
        self.request.validated["tender"] = tender
        self.request.validated["tender_src"] = {}
        if save_tender(self.request):
            self.LOGGER.info(
                "Created tender {} ({})".format(tender_id, tender.tenderID),
                extra=context_unpack(
                    self.request,
                    {"MESSAGE_ID": "tender_create"},
                    {
                        "tender_id": tender_id,
                        "tenderID": tender.tenderID,
                        "tender_mode": tender.mode
                    },
                ),
            )
            self.request.response.status = 201
            self.request.response.headers["Location"] = self.request.route_url(
                "{}:Tender".format(tender.procurementMethodType),
                tender_id=tender_id)
            return {"data": tender.serialize(tender.status), "access": access}