def post(self): """Report auction results for lot. """ apply_patch(self.request, save=False, src=self.request.validated['tender_src']) if all([i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['tender'].lots if i.numberOfBids > 1]): add_next_award(self.request) if save_tender(self.request): LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_lot_auction_post'})) return {'data': self.request.validated['tender'].serialize(self.request.validated['tender'].status)}
def patch(self): """Post a complaint resolution for award """ tender = self.request.validated["tender"] if tender.status not in ["active.qualification", "active.awarded"]: self.request.errors.add( "body", "data", "Can't update complaint in current ({}) tender status".format(tender.status) ) self.request.errors.status = 403 return if any([i.status != "active" for i in tender.lots if i.id == self.request.validated["award"].lotID]): self.request.errors.add("body", "data", "Can update complaint only in active lot status") self.request.errors.status = 403 return complaint = self.request.context if complaint.status != "pending": self.request.errors.add( "body", "data", "Can't update complaint in current ({}) status".format(complaint.status) ) self.request.errors.status = 403 return if self.request.validated["data"].get("status", complaint.status) == "cancelled": self.request.errors.add("body", "data", "Can't cancel complaint") self.request.errors.status = 403 return apply_patch(self.request, save=False, src=complaint.serialize()) if complaint.status == "resolved": award = self.request.validated["award"] if tender.status == "active.awarded": tender.status = "active.qualification" tender.awardPeriod.endDate = None now = get_now() if award.status == "unsuccessful": for i in tender.awards[tender.awards.index(award) :]: if i.lotID != award.lotID: continue i.complaintPeriod.endDate = now + STAND_STILL_TIME i.status = "cancelled" for j in i.complaints: if j.status == "pending": j.status = "cancelled" for i in tender.contracts: if award.id == i.awardID: i.status = "cancelled" award.complaintPeriod.endDate = now + STAND_STILL_TIME award.status = "cancelled" add_next_award(self.request) elif complaint.status in ["declined", "invalid"] and tender.status == "active.awarded": check_tender_status(self.request) if save_tender(self.request): LOGGER.info( "Updated tender award complaint {}".format(self.request.context.id), extra=context_unpack(self.request, {"MESSAGE_ID": "tender_award_complaint_patch"}), ) return {"data": complaint.serialize("view")}
def patch(self): """Post a complaint resolution for award """ tender = self.request.validated["tender"] if tender.status not in ["active.qualification", "active.awarded"]: self.request.errors.add( "body", "data", "Can't update complaint in current ({}) tender status".format(tender.status) ) self.request.errors.status = 403 return complaint = self.request.context if complaint.status != "pending": self.request.errors.add( "body", "data", "Can't update complaint in current ({}) status".format(complaint.status) ) self.request.errors.status = 403 return apply_patch(self.request, save=False, src=complaint.serialize()) if complaint.status == "cancelled": self.request.errors.add("body", "data", "Can't cancel complaint") self.request.errors.status = 403 return if complaint.status == "resolved": award = self.request.validated["award"] if tender.status == "active.awarded": tender.status = "active.qualification" tender.awardPeriod.endDate = None if award.status == "unsuccessful": for i in tender.awards[tender.awards.index(award) :]: i.complaintPeriod.endDate = get_now() + STAND_STILL_TIME i.status = "cancelled" for j in i.complaints: if j.status == "pending": j.status = "cancelled" for i in award.contracts: i.status = "cancelled" award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME award.status = "cancelled" add_next_award(self.request) elif complaint.status in ["declined", "invalid"] and tender.status == "active.awarded": pending_complaints = [i for i in tender.complaints if i.status == "pending"] pending_awards_complaints = [i for a in tender.awards for i in a.complaints if i.status == "pending"] stand_still_ends = [a.complaintPeriod.endDate for a in tender.awards if a.complaintPeriod.endDate] stand_still_end = max(stand_still_ends) if stand_still_ends else get_now() stand_still_time_expired = stand_still_end < get_now() if not pending_complaints and not pending_awards_complaints and stand_still_time_expired: active_awards = [a for a in tender.awards if a.status == "active"] if not active_awards: tender.status = "unsuccessful" if save_tender(self.request): LOGGER.info( "Updated tender award complaint {}".format(self.request.context.id), extra={"MESSAGE_ID": "tender_award_complaint_patch"}, ) return {"data": complaint.serialize("view")}
def cancel_lot(self, cancellation=None): if not cancellation: cancellation = self.context tender = self.request.validated['tender'] [setattr(i, 'status', 'cancelled') for i in tender.lots if i.id == cancellation.relatedLot] statuses = set([lot.status for lot in tender.lots]) if statuses == set(['cancelled']): self.cancel_tender() elif not statuses.difference(set(['unsuccessful', 'cancelled'])): tender.status = 'unsuccessful' elif not statuses.difference(set(['complete', 'unsuccessful', 'cancelled'])): tender.status = 'complete' if tender.status == 'active.auction' and all([ i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['tender'].lots if i.numberOfBids > 1 and i.status == 'active' ]): add_next_award(self.request)
def cancel_lot(self, cancellation=None): if not cancellation: cancellation = self.context tender = self.request.validated['tender'] [ setattr(i, 'status', 'cancelled') for i in tender.lots if i.id == cancellation.relatedLot ] statuses = set([lot.status for lot in tender.lots]) if statuses == set(['cancelled']): self.cancel_tender() elif not statuses.difference(set(['unsuccessful', 'cancelled'])): tender.status = 'unsuccessful' elif not statuses.difference( set(['complete', 'unsuccessful', 'cancelled'])): tender.status = 'complete' if tender.status == 'active.auction' and all([ i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['tender'].lots if i.numberOfBids > 1 and i.status == 'active' ]): add_next_award(self.request)
def collection_post(self): """Report auction results. Report auction results ---------------------- Example request to report auction results: .. sourcecode:: http POST /tenders/4879d3f8ee2443169b5fbbc9f89fa607/auction HTTP/1.1 Host: example.com Accept: application/json { "data": { "dateModified": "2014-10-27T08:06:58.158Z", "bids": [ { "value": { "amount": 400, "currency": "UAH" } }, { "value": { "amount": 385, "currency": "UAH" } } ] } } This is what one should expect in response: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "data": { "dateModified": "2014-10-27T08:06:58.158Z", "bids": [ { "value": { "amount": 400, "currency": "UAH", "valueAddedTaxIncluded": true } }, { "value": { "amount": 385, "currency": "UAH", "valueAddedTaxIncluded": true } } ], "minimalStep":{ "amount": 35, "currency": "UAH" }, "tenderPeriod":{ "startDate": "2014-11-04T08:00:00" } } } """ apply_patch(self.request, save=False, src=self.request.validated['tender_src']) if all([ i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['tender'].lots if i.numberOfBids > 1 and i.status == 'active' ]): add_next_award(self.request) if save_tender(self.request): self.LOGGER.info( 'Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_auction_post'})) return { 'data': self.request.validated['tender'].serialize( self.request.validated['tender'].status) }
def patch(self): """Update of award Example request to change the award: .. sourcecode:: http PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607/awards/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json { "data": { "value": { "amount": 600 } } } And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "date": "2014-10-28T11:44:17.947Z", "status": "active", "suppliers": [ { "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": 600, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ tender = self.request.validated['tender'] if tender.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update award in current ({}) tender status'.format(tender.status)) self.request.errors.status = 403 return award = self.request.context if any([i.status != 'active' for i in tender.lots if i.id == award.lotID]): self.request.errors.add('body', 'data', 'Can update award only in active lot status') self.request.errors.status = 403 return award_status = award.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if award_status == 'pending' and award.status == 'active': award.complaintPeriod.endDate = calculate_business_date(get_now(), STAND_STILL_TIME, tender, True) tender.contracts.append(type(tender).contracts.model_class({ 'awardID': award.id, 'suppliers': award.suppliers, 'value': award.value, 'items': [i for i in tender.items if i.relatedLot == award.lotID ], 'contractID': '{}-{}{}'.format(tender.tenderID, self.server_id, len(tender.contracts) + 1) })) add_next_award(self.request) elif award_status == 'active' and award.status == 'cancelled': now = get_now() if award.complaintPeriod.endDate > now: award.complaintPeriod.endDate = now for j in award.complaints: if j.status not in ['invalid', 'resolved', 'declined']: j.status = 'cancelled' j.cancellationReason = 'cancelled' j.dateCanceled = now for i in tender.contracts: if i.awardID == award.id: i.status = 'cancelled' add_next_award(self.request) elif award_status == 'pending' and award.status == 'unsuccessful': award.complaintPeriod.endDate = calculate_business_date(get_now(), STAND_STILL_TIME, tender, True) add_next_award(self.request) elif award_status == 'unsuccessful' and award.status == 'cancelled' and any([i.status in ['claim', 'answered', 'pending', 'resolved'] for i in award.complaints]): if tender.status == 'active.awarded': tender.status = 'active.qualification' tender.awardPeriod.endDate = None now = get_now() award.complaintPeriod.endDate = now cancelled_awards = [] for i in tender.awards[tender.awards.index(award):]: if i.lotID != award.lotID: continue i.complaintPeriod.endDate = now i.status = 'cancelled' for j in i.complaints: if j.status not in ['invalid', 'resolved', 'declined']: j.status = 'cancelled' j.cancellationReason = 'cancelled' j.dateCanceled = now cancelled_awards.append(i.id) for i in tender.contracts: if i.awardID in cancelled_awards: i.status = 'cancelled' add_next_award(self.request) elif self.request.authenticated_role != 'Administrator' and not(award_status == 'pending' and award.status == 'pending'): self.request.errors.add('body', 'data', 'Can\'t update award in current ({}) status'.format(award_status)) self.request.errors.status = 403 return if save_tender(self.request): self.LOGGER.info('Updated tender award {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_award_patch'})) return {'data': award.serialize("view")}
def patch(self): """Update of award Example request to change the award: .. sourcecode:: http PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607/awards/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json { "data": { "value": { "amount": 600 } } } And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "date": "2014-10-28T11:44:17.947Z", "status": "active", "suppliers": [ { "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": 600, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ tender = self.request.validated['tender'] if tender.status not in ['active.qualification', 'active.awarded']: self.request.errors.add( 'body', 'data', 'Can\'t update award in current ({}) tender status'.format( tender.status)) self.request.errors.status = 403 return award = self.request.context if any( [i.status != 'active' for i in tender.lots if i.id == award.lotID]): self.request.errors.add( 'body', 'data', 'Can update award only in active lot status') self.request.errors.status = 403 return award_status = award.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if award_status == 'pending' and award.status == 'active': award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME tender.contracts.append( type(tender).contracts.model_class({'awardID': award.id})) add_next_award(self.request) elif award_status == 'active' and award.status == 'cancelled': award.complaintPeriod.endDate = get_now() for i in tender.contracts: if i.awardID == award.id: i.status = 'cancelled' add_next_award(self.request) elif award_status == 'pending' and award.status == 'unsuccessful': award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME add_next_award(self.request) elif award_status == 'unsuccessful' and award.status == 'cancelled' and any( [ i.status in ['claim', 'answered', 'pending', 'resolved'] for i in award.complaints ]): if tender.status == 'active.awarded': tender.status = 'active.qualification' tender.awardPeriod.endDate = None now = get_now() award.complaintPeriod.endDate = now cancelled_awards = [] for i in tender.awards[tender.awards.index(award):]: if i.lotID != award.lotID: continue i.complaintPeriod.endDate = now i.status = 'cancelled' for j in i.complaints: if j.status not in ['invalid', 'resolved', 'declined']: j.status = 'cancelled' j.cancellationReason = 'cancelled' j.dateCanceled = now cancelled_awards.append(i.id) for i in tender.contracts: if i.awardID in cancelled_awards: i.status = 'cancelled' add_next_award(self.request) else: self.request.errors.add( 'body', 'data', 'Can\'t update award in current ({}) status'.format( award_status)) self.request.errors.status = 403 return if save_tender(self.request): LOGGER.info( 'Updated tender award {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_award_patch'})) return {'data': award.serialize("view")}
def collection_post(self): """Report auction results. Report auction results ---------------------- Example request to report auction results: .. sourcecode:: http POST /tenders/4879d3f8ee2443169b5fbbc9f89fa607/auction HTTP/1.1 Host: example.com Accept: application/json { "data": { "dateModified": "2014-10-27T08:06:58.158Z", "bids": [ { "value": { "amount": 400, "currency": "UAH" } }, { "value": { "amount": 385, "currency": "UAH" } } ] } } This is what one should expect in response: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "data": { "dateModified": "2014-10-27T08:06:58.158Z", "bids": [ { "value": { "amount": 400, "currency": "UAH", "valueAddedTaxIncluded": true } }, { "value": { "amount": 385, "currency": "UAH", "valueAddedTaxIncluded": true } } ], "minimalStep":{ "amount": 35, "currency": "UAH" }, "tenderPeriod":{ "startDate": "2014-11-04T08:00:00" } } } """ apply_patch(self.request, save=False, src=self.request.validated['tender_src']) if all([i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['tender'].lots if i.numberOfBids > 1]): add_next_award(self.request) if save_tender(self.request): LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_auction_post'})) return {'data': self.request.validated['tender'].serialize(self.request.validated['tender'].status)}
def patch(self): """Post a complaint resolution for award """ tender = self.request.validated['tender'] if tender.status not in ['active.qualification', 'active.awarded']: self.request.errors.add( 'body', 'data', 'Can\'t update complaint in current ({}) tender status'.format( tender.status)) self.request.errors.status = 403 return complaint = self.request.context if complaint.status != 'pending': self.request.errors.add( 'body', 'data', 'Can\'t update complaint in current ({}) status'.format( complaint.status)) self.request.errors.status = 403 return apply_patch(self.request, save=False, src=complaint.serialize()) if complaint.status == 'cancelled': self.request.errors.add('body', 'data', 'Can\'t cancel complaint') self.request.errors.status = 403 return if complaint.status == 'resolved': award = self.request.validated['award'] if tender.status == 'active.awarded': tender.status = 'active.qualification' tender.awardPeriod.endDate = None if award.status == 'unsuccessful': for i in tender.awards[tender.awards.index(award):]: i.complaintPeriod.endDate = get_now() + STAND_STILL_TIME i.status = 'cancelled' for j in i.complaints: if j.status == 'pending': j.status = 'cancelled' for i in award.contracts: i.status = 'cancelled' award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME award.status = 'cancelled' add_next_award(self.request) elif complaint.status in ['declined', 'invalid' ] and tender.status == 'active.awarded': pending_complaints = [ i for i in tender.complaints if i.status == 'pending' ] pending_awards_complaints = [ i for a in tender.awards for i in a.complaints if i.status == 'pending' ] stand_still_ends = [ a.complaintPeriod.endDate for a in tender.awards if a.complaintPeriod.endDate ] stand_still_end = max( stand_still_ends) if stand_still_ends else get_now() stand_still_time_expired = stand_still_end < get_now() if not pending_complaints and not pending_awards_complaints and stand_still_time_expired: active_awards = [ a for a in tender.awards if a.status == 'active' ] if not active_awards: tender.status = 'unsuccessful' if save_tender(self.request): LOGGER.info('Updated tender award complaint {}'.format( self.request.context.id), extra={'MESSAGE_ID': 'tender_award_complaint_patch'}) return {'data': complaint.serialize("view")}
def post_auction(request): """Report auction results. Report auction results ---------------------- Example request to report auction results: .. sourcecode:: http POST /tenders/4879d3f8ee2443169b5fbbc9f89fa607/auction HTTP/1.1 Host: example.com Accept: application/json { "data": { "dateModified": "2014-10-27T08:06:58.158Z", "bids": [ { "value": { "amount": 400, "currency": "UAH" } }, { "value": { "amount": 385, "currency": "UAH" } } ] } } This is what one should expect in response: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "data": { "dateModified": "2014-10-27T08:06:58.158Z", "bids": [ { "value": { "amount": 400, "currency": "UAH", "valueAddedTaxIncluded": true } }, { "value": { "amount": 385, "currency": "UAH", "valueAddedTaxIncluded": true } } ], "minimalStep":{ "amount": 35, "currency": "UAH" }, "tenderPeriod":{ "startDate": "2014-11-04T08:00:00" } } } """ apply_patch(request, save=False, src=request.validated['tender_src']) add_next_award(request) if save_tender(request): LOGGER.info('Report auction results', extra={'MESSAGE_ID': 'tender_auction_post'}) return {'data': request.context.serialize(request.context.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.request.validated['tender'] if tender.status in ['complete', 'unsuccessful', 'cancelled']: self.request.errors.add( 'body', 'data', 'Can\'t update tender in current ({}) status'.format( tender.status)) self.request.errors.status = 403 return data = self.request.validated['data'] if self.request.authenticated_role == 'tender_owner' and 'status' in data and data[ 'status'] not in ['cancelled', tender.status]: self.request.errors.add('body', 'data', 'Can\'t update tender status') self.request.errors.status = 403 return if self.request.authenticated_role == 'chronograph' and tender.status == 'active.tendering' and data.get( 'status', tender.status ) == 'active.qualification' and tender.numberOfBids == 1: apply_patch(self.request, save=False, src=self.request.validated['tender_src']) add_next_award(self.request) save_tender(self.request) else: apply_patch(self.request, src=self.request.validated['tender_src']) LOGGER.info('Updated tender {}'.format(tender.id), extra={'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.request.validated['tender'] if self.request.authenticated_role != 'Administrator' and tender.status in ['complete', 'unsuccessful', 'cancelled']: self.request.errors.add('body', 'data', 'Can\'t update tender in current ({}) status'.format(tender.status)) self.request.errors.status = 403 return data = self.request.validated['data'] if self.request.authenticated_role == 'tender_owner' and 'status' in data and data['status'] not in ['cancelled', tender.status]: self.request.errors.add('body', 'data', 'Can\'t update tender status') self.request.errors.status = 403 return if self.request.authenticated_role == 'chronograph' and tender.status == 'active.tendering' and data.get('status', tender.status) == 'active.qualification' and tender.numberOfBids == 1: apply_patch(self.request, save=False, src=self.request.validated['tender_src']) add_next_award(self.request) save_tender(self.request) else: apply_patch(self.request, src=self.request.validated['tender_src']) LOGGER.info('Updated tender {}'.format(tender.id), extra={'MESSAGE_ID': 'tender_patch'}) return {'data': tender.serialize(tender.status)}
def patch(self): """Update of award Example request to change the award: .. sourcecode:: http PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607/awards/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json { "data": { "value": { "amount": 600 } } } And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "date": "2014-10-28T11:44:17.947Z", "status": "active", "suppliers": [ { "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": 600, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ tender = self.request.validated["tender"] if tender.status not in ["active.qualification", "active.awarded"]: self.request.errors.add( "body", "data", "Can't update award in current ({}) tender status".format(tender.status) ) self.request.errors.status = 403 return award = self.request.context award_status = award.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if award_status == "pending" and award.status == "active": award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME award.contracts.append(Contract({"awardID": award.id})) tender.awardPeriod.endDate = get_now() tender.status = "active.awarded" elif award_status == "active" and award.status == "cancelled": award.complaintPeriod.endDate = get_now() for i in award.contracts: i.status = "cancelled" add_next_award(self.request) tender.status = "active.qualification" tender.awardPeriod.endDate = None elif award_status == "pending" and award.status == "unsuccessful": award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME add_next_award(self.request) else: self.request.errors.add("body", "data", "Can't update award in current ({}) status".format(award_status)) self.request.errors.status = 403 return if save_tender(self.request): LOGGER.info( "Updated tender award {}".format(self.request.context.id), extra={"MESSAGE_ID": "tender_award_patch"} ) return {"data": award.serialize("view")}
def patch(self): """Update of award Example request to change the award: .. sourcecode:: http PATCH /tenders/4879d3f8ee2443169b5fbbc9f89fa607/awards/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json { "data": { "value": { "amount": 600 } } } And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "date": "2014-10-28T11:44:17.947Z", "status": "active", "suppliers": [ { "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": 600, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ tender = self.request.validated['tender'] if tender.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update award in current ({}) tender status'.format(tender.status)) self.request.errors.status = 403 return award = self.request.context if any([i.status != 'active' for i in tender.lots if i.id == award.lotID]): self.request.errors.add('body', 'data', 'Can update award only in active lot status') self.request.errors.status = 403 return award_status = award.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if award_status == 'pending' and award.status == 'active': award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME tender.contracts.append(Contract({'awardID': award.id})) add_next_award(self.request) elif award_status == 'active' and award.status == 'cancelled': award.complaintPeriod.endDate = get_now() for i in tender.contracts: if i.awardID == award.id: i.status = 'cancelled' add_next_award(self.request) elif award_status == 'pending' and award.status == 'unsuccessful': award.complaintPeriod.endDate = get_now() + STAND_STILL_TIME add_next_award(self.request) else: self.request.errors.add('body', 'data', 'Can\'t update award in current ({}) status'.format(award_status)) self.request.errors.status = 403 return if save_tender(self.request): LOGGER.info('Updated tender award {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_award_patch'}, {'TENDER_REV': tender.rev})) return {'data': award.serialize("view")}