def collection_post(self): """Post a complaint """ auction = self.context if auction.status not in ['active.enquiries', 'active.tendering']: self.request.errors.add('body', 'data', 'Can\'t add complaint in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return complaint = self.request.validated['complaint'] complaint.date = get_now() if complaint.status == 'claim': complaint.dateSubmitted = get_now() else: complaint.status = 'draft' complaint.complaintID = '{}.{}{}'.format(auction.auctionID, self.server_id, sum([len(i.complaints) for i in auction.awards], len(auction.complaints)) + 1) set_ownership(complaint, self.request) auction.complaints.append(complaint) if save_auction(self.request): self.LOGGER.info('Created auction complaint {}'.format(complaint.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_complaint_create'}, {'complaint_id': complaint.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=route, complaint_id=complaint.id, _query={}) return { 'data': complaint.serialize(auction.status), 'access': { 'token': complaint.owner_token } }
def collection_post(self): """Post a cancellation """ auction = self.request.validated['auction'] if auction.status in ['complete', 'cancelled', 'unsuccessful']: self.request.errors.add('body', 'data', 'Can\'t add cancellation in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return cancellation = self.request.validated['cancellation'] cancellation.date = get_now() if any([i.status != 'active' for i in auction.lots if i.id == cancellation.relatedLot]): self.request.errors.add('body', 'data', 'Can add cancellation only in active lot status') self.request.errors.status = 403 return if cancellation.relatedLot and cancellation.status == 'active': self.cancel_lot(cancellation) elif cancellation.status == 'active': self.cancel_auction() auction.cancellations.append(cancellation) if save_auction(self.request): self.LOGGER.info('Created auction cancellation {}'.format(cancellation.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_cancellation_create'}, {'cancellation_id': cancellation.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=route, cancellation_id=cancellation.id, _query={}) return {'data': cancellation.serialize("view")}
def put(self): """Auction Award Complaint Document Update""" if self.request.authenticated_role != self.context.author: self.request.errors.add('url', 'role', 'Can update document only author') self.request.errors.status = 403 return if self.request.validated['auction_status'] not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return if any([i.status != 'active' for i in self.request.validated['auction'].lots if i.id == self.request.validated['award'].lotID]): self.request.errors.add('body', 'data', 'Can update document only in active lot status') self.request.errors.status = 403 return if self.request.validated['complaint'].status not in STATUS4ROLE.get(self.request.authenticated_role, []): self.request.errors.add('body', 'data', 'Can\'t update document in current ({}) complaint status'.format(self.request.validated['complaint'].status)) self.request.errors.status = 403 return document = upload_file(self.request) document.author = self.request.authenticated_role self.request.validated['complaint'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction award complaint document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_complaint_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): """Auction Award Complaint Document Upload """ if self.request.validated['auction_status'] not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t add document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return if any([i.status != 'active' for i in self.request.validated['auction'].lots if i.id == self.request.validated['award'].lotID]): self.request.errors.add('body', 'data', 'Can add document only in active lot status') self.request.errors.status = 403 return if self.context.status not in STATUS4ROLE.get(self.request.authenticated_role, []): self.request.errors.add('body', 'data', 'Can\'t add document in current ({}) complaint status'.format(self.context.status)) self.request.errors.status = 403 return document = upload_file(self.request) document.author = self.request.authenticated_role self.context.documents.append(document) if save_auction(self.request): self.LOGGER.info('Created auction award complaint document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_complaint_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def collection_post(self): """Auction Bid Document Upload """ if self.request.validated['auction_status'] not in ['active.tendering', 'active.qualification']: self.request.errors.add('body', 'data', 'Can\'t add document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if self.request.validated['auction_status'] == 'active.tendering' and (auction.tenderPeriod.startDate and get_now() < auction.tenderPeriod.startDate or get_now() > auction.tenderPeriod.endDate): self.request.errors.add('body', 'data', 'Document can be added only during the tendering period: from ({}) to ({}).'.format(auction.auctionPeriod.startDate and auction.auctionPeriod.startDate.isoformat(), auction.auctionPeriod.endDate.isoformat())) self.request.errors.status = 403 return if self.request.validated['auction_status'] == 'active.qualification' and not [i for i in self.request.validated['auction'].awards if i.status == 'pending' and i.bid_id == self.request.validated['bid_id']]: self.request.errors.add('body', 'data', 'Can\'t add document because award of bid is not in pending state') self.request.errors.status = 403 return document = upload_file(self.request) self.context.documents.append(document) if self.request.validated['auction_status'] == 'active.tendering': self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info('Created auction bid document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def patch(self): """Post a complaint resolution """ auction = self.request.validated['auction'] if auction.status not in ['active.enquiries', 'active.tendering', 'active.auction', 'active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update complaint in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return if self.context.status not in ['draft', 'claim', 'answered', 'pending']: self.request.errors.add('body', 'data', 'Can\'t update complaint in current ({}) status'.format(self.context.status)) self.request.errors.status = 403 return data = self.request.validated['data'] # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in ['draft', 'claim', 'answered', 'pending'] and data.get('status', self.context.status) == 'cancelled': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif self.request.authenticated_role == 'complaint_owner' and auction.status in ['active.enquiries', 'active.tendering'] and self.context.status == 'draft' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and auction.status in ['active.enquiries', 'active.tendering'] and self.context.status == 'draft' and data.get('status', self.context.status) == 'claim': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is True and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is False and data.get('status', self.context.status) == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get('resolution', self.context.resolution) and data.get('resolutionType', self.context.resolutionType) and data.get('status', self.context.status) == 'answered': if len(data.get('resolution', self.context.resolution)) < 20: self.request.errors.add('body', 'data', 'Can\'t update complaint: resolution too short') self.request.errors.status = 403 return apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAnswered = get_now() elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) # reviewers elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) in ['resolved', 'invalid', 'declined']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() else: self.request.errors.add('body', 'data', 'Can\'t update complaint') self.request.errors.status = 403 return if self.context.tendererAction and not self.context.tendererActionDate: self.context.tendererActionDate = get_now() if self.context.status not in ['draft', 'claim', 'answered', 'pending'] and auction.status in ['active.qualification', 'active.awarded']: check_auction_status(self.request) if save_auction(self.request): self.LOGGER.info('Updated auction complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_complaint_patch'})) return {'data': self.context.serialize("view")}
def post(self): """Report auction results for lot. """ apply_patch(self.request, save=False, src=self.request.validated['auction_src']) if all([i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['auction'].lots if i.numberOfBids > 1 and i.status == 'active']): cleanup_bids_for_cancelled_lots(self.request.validated['auction']) add_next_award(self.request) if save_auction(self.request): self.LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_lot_auction_post'})) return {'data': self.request.validated['auction'].serialize(self.request.validated['auction'].status)}
def put(self): """Auction Award Document Update""" if not self.validate_award_document('update'): return document = upload_file(self.request) self.request.validated['award'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction award document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_document_put'})) return {'data': document.serialize("view")}
def put(self): """Auction Contract Document Update""" if not self.validate_contract_document('update'): return document = upload_file(self.request) self.request.validated['contract'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction contract document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_contract_document_put'})) return {'data': document.serialize("view")}
def put(self): """Auction Award Document Update""" if not self.validate_award_document('update'): return document = upload_file(self.request) document.author = self.request.authenticated_role self.request.validated['award'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction award document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_document_put'})) return {'data': document.serialize("view")}
def patch(self): award = self.request.validated['award'] manager = self.request.registry.getAdapter(award, IAwardManagerAdapter) manager.change_award(self.request, server_id=self.server_id) if save_auction(self.request): self.LOGGER.info( 'Updated auction award {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_patch'})) return {'data': award.serialize("view")}
def put(self): """Auction Cancellation Document Update""" if self.request.validated['auction_status'] in ['complete', 'cancelled', 'unsuccessful']: self.request.errors.add('body', 'data', 'Can\'t update document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return document = upload_file(self.request) self.request.validated['cancellation'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction cancellation document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_cancellation_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): apply_patch(self.request, save=False, src=self.request.validated['auction_src']) auction = self.request.validated['auction'] adapter = self.request.registry.getAdapter(auction, IAuctionManager) invalidate_bids_under_threshold(auction) if any([i.status == 'active' for i in auction.bids]): self.request.content_configurator.start_awarding() else: adapter.pendify_auction_status('unsuccessful') if save_auction(self.request): self.LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_auction_post'})) return {'data': self.request.validated['auction'].serialize(self.request.validated['auction'].status)}
def put(self): """Auction Bid Document Update""" if not self.validate_bid_document('update'): return document = upload_file(self.request) self.request.validated['bid'].documents.append(document) if self.request.validated['auction_status'] == 'active.tendering': self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info('Updated auction bid document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_document_put'})) return {'data': document.serialize("view")}
def put(self): """Auction Award Document Update""" if self.request.authenticated_role != self.request.context.author: self.request.errors.add('url', 'role', 'Can update document only author') self.request.errors.status = 403 return document = upload_file(self.request) document.author = self.request.authenticated_role self.request.validated['award'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction award document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_document_put'})) return {'data': document.serialize("view")}
def put(self): """Auction Document Update""" if self.request.authenticated_role != 'auction' and self.request.validated['auction_status'] != 'active.enquiries' or \ self.request.authenticated_role == 'auction' and self.request.validated['auction_status'] not in ['active.auction', 'active.qualification']: self.request.errors.add('body', 'data', 'Can\'t update document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return document = upload_file(self.request) self.request.validated['auction'].documents.append(document) if save_auction(self.request): self.LOGGER.info('Updated auction document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): """Auction Award Document Upload """ document = upload_file(self.request) document.author = self.request.authenticated_role self.context.documents.append(document) if save_auction(self.request): self.LOGGER.info('Created auction award document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def collection_post(self): """Auction Award Document Upload """ if not self.validate_award_document('add'): return document = upload_file(self.request) self.context.documents.append(document) if save_auction(self.request): self.LOGGER.info('Created auction award document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def patch(self): """Update of contract """ contract = self.request.context contract_manager = self.request.registry.getAdapter( contract, IContractManagerAdapter) contract_manager.change_contract(self.request, context=self.context) if save_auction(self.request): self.LOGGER.info( 'Updated auction contract {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_contract_patch'})) return {'data': self.request.context.serialize()}
def patch(self): """Post a complaint resolution for award """ auction = self.request.validated['auction'] data = self.request.validated['data'] complaintPeriod = self.request.validated['award'].complaintPeriod is_complaintPeriod = complaintPeriod.startDate < get_now() and complaintPeriod.endDate > get_now() if complaintPeriod.endDate else complaintPeriod.startDate < get_now() # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in ['draft', 'claim', 'answered', 'pending'] and data.get('status', self.context.status) == 'cancelled': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif self.request.authenticated_role == 'complaint_owner' and is_complaintPeriod and self.context.status == 'draft' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and is_complaintPeriod and self.context.status == 'draft' and data.get('status', self.context.status) == 'claim': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is True and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is False and data.get('status', self.context.status) == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() # auction_owner elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get('resolution', self.context.resolution) and len(data.get('resolution', self.context.resolution or "")) >= 20 and data.get('resolutionType', self.context.resolutionType) and data.get('status', self.context.status) == 'answered': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAnswered = get_now() elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) # reviewers elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) in ['resolved', 'invalid', 'declined']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() else: self.request.errors.add('body', 'data', 'Can\'t update complaint') self.request.errors.status = 403 return if self.context.tendererAction and not self.context.tendererActionDate: self.context.tendererActionDate = get_now() if self.context.status not in ['draft', 'claim', 'answered', 'pending'] and auction.status in ['active.qualification', 'active.awarded']: check_auction_status(self.request) if save_auction(self.request): self.LOGGER.info('Updated auction award complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_complaint_patch'})) return {'data': self.context.serialize("view")}
def put(self): """Auction Document Update""" # TODO rm black box if not self.validate_document_editing_period('update'): return document = upload_file(self.request) if self.request.authenticated_role != "auction": invalidate_bids_data(self.request.auction) self.request.validated['auction'].documents.append(document) if save_auction(self.request): self.LOGGER.info( 'Updated auction document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): """Auction Award Complaint Document Upload """ if self.request.validated['auction_status'] not in [ 'active.qualification', 'active.awarded' ]: self.request.errors.add( 'body', 'data', 'Can\'t add document in current ({}) auction status'.format( self.request.validated['auction_status'])) self.request.errors.status = 403 return if any([ i.status != 'active' for i in self.request.validated['auction'].lots if i.id == self.request.validated['award'].lotID ]): self.request.errors.add( 'body', 'data', 'Can add document only in active lot status') self.request.errors.status = 403 return if self.context.status not in STATUS4ROLE.get( self.request.authenticated_role, []): self.request.errors.add( 'body', 'data', 'Can\'t add document in current ({}) complaint status'.format( self.context.status)) self.request.errors.status = 403 return document = upload_file(self.request) document.author = self.request.authenticated_role self.context.documents.append(document) if save_auction(self.request): self.LOGGER.info( 'Created auction award complaint document {}'.format( document.id), extra=context_unpack( self.request, {'MESSAGE_ID': 'auction_award_complaint_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace( "collection_", "") self.request.response.headers[ 'Location'] = self.request.current_route_url( _route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def delete(self): """Lot deleting """ auction = self.request.validated['auction'] if auction.status not in ['active.enquiries']: self.request.errors.add('body', 'data', 'Can\'t delete lot in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return lot = self.request.context res = lot.serialize("view") auction.lots.remove(lot) if save_auction(self.request): self.LOGGER.info('Deleted auction lot {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_lot_delete'})) return {'data': res}
def collection_post(self): auction = self.context.serialize() merge_auction_results(auction, self.request) apply_patch(self.request, save=False, src=self.request.validated['auction_src']) remove_draft_bids(self.request) auction = self.request.validated['auction'] invalidate_empty_bids(auction) if any([i.status == 'active' for i in auction.bids]): create_awards(self.request) else: auction.status = 'unsuccessful' if save_auction(self.request): self.LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_auction_post'})) return {'data': self.request.validated['auction'].serialize(self.request.validated['auction'].status)}
def post(self): """Report auction results for lot. """ apply_patch(self.request, save=False, src=self.request.validated['auction_src']) auction = self.request.validated['auction'] if all([i.auctionPeriod and i.auctionPeriod.endDate for i in auction.lots if i.numberOfBids > 1 and i.status == 'active']): cleanup_bids_for_cancelled_lots(auction) invalidate_bids_under_threshold(auction) if any([i.status == 'active' for i in auction.bids]): self.request.content_configurator.start_awarding() else: auction.status = 'unsuccessful' if save_auction(self.request): self.LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_lot_auction_post'})) return {'data': self.request.validated['auction'].serialize(self.request.validated['auction'].status)}
def patch(self): """Auction Document Update""" # TODO rm black box if not self.validate_document_editing_period('update'): return apply_patch(self.request, save=False, src=self.request.context.serialize()) if self.request.authenticated_role != "auction": invalidate_bids_data(self.request.auction) if save_auction(self.request): self.LOGGER.info( 'Updated auction document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_document_patch'})) return {'data': self.request.context.serialize("view")}
def delete(self): """Lot deleting """ auction = self.request.validated['auction'] if auction.status not in ['active.tendering']: self.request.errors.add('body', 'data', 'Can\'t delete lot in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return lot = self.request.context res = lot.serialize("view") auction.lots.remove(lot) if save_auction(self.request): self.LOGGER.info('Deleted auction lot {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_lot_delete'})) return {'data': res}
def put(self): """Auction Bid Document Update""" if self.request.validated['auction_status'] not in [ 'active.tendering', 'active.qualification' ]: self.request.errors.add( 'body', 'data', 'Can\'t update document in current ({}) auction status'.format( self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if self.request.validated['auction_status'] == 'active.tendering' and ( auction.tenderPeriod.startDate and get_now() < auction.tenderPeriod.startDate or get_now() > auction.tenderPeriod.endDate): self.request.errors.add( 'body', 'data', 'Document can be updated only during the tendering period: from ({}) to ({}).' .format( auction.auctionPeriod.startDate and auction.auctionPeriod.startDate.isoformat(), auction.auctionPeriod.endDate.isoformat())) self.request.errors.status = 403 return if self.request.validated[ 'auction_status'] == 'active.qualification' and not [ i for i in self.request.validated['auction'].awards if i.status == 'pending' and i.bid_id == self.request.validated['bid_id'] ]: self.request.errors.add( 'body', 'data', 'Can\'t update document because award of bid is not in pending state' ) self.request.errors.status = 403 return document = upload_file(self.request) self.request.validated['bid'].documents.append(document) if self.request.validated['auction_status'] == 'active.tendering': self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info('Updated auction bid document {}'.format( self.request.context.id), extra=context_unpack( self.request, {'MESSAGE_ID': 'auction_bid_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): """Auction Cancellation Document Upload """ if self.request.validated['auction_status'] in ['complete', 'cancelled', 'unsuccessful']: self.request.errors.add('body', 'data', 'Can\'t add document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return document = upload_file(self.request) self.context.documents.append(document) if save_auction(self.request): self.LOGGER.info('Created auction cancellation document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_cancellation_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def collection_post(self): """Auction Document Upload""" if self.request.authenticated_role != 'auction' and self.request.validated['auction_status'] != 'active.enquiries' or \ self.request.authenticated_role == 'auction' and self.request.validated['auction_status'] not in ['active.auction', 'active.qualification']: self.request.errors.add('body', 'data', 'Can\'t add document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return document = upload_file(self.request) self.context.documents.append(document) if save_auction(self.request): self.LOGGER.info('Created auction document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def collection_post(self): """Post a contract for award """ auction = self.request.validated['auction'] if auction.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t add contract in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return contract = self.request.validated['contract'] auction.contracts.append(contract) if save_auction(self.request): self.LOGGER.info('Created auction contract {}'.format(contract.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_contract_create'}, {'contract_id': contract.id})) self.request.response.status = 201 self.request.response.headers['Location'] = self.request.route_url('Auction Contracts', auction_id=auction.id, contract_id=contract['id']) return {'data': contract.serialize()}
def collection_post(self): """Auction Bid Document Upload """ if not self.validate_bid_document('add'): return document = upload_file(self.request) self.context.documents.append(document) if self.request.validated['auction_status'] == 'active.tendering': self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info('Created auction bid document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def collection_post(self): item = self.request.validated['item'] self.context.items.append(item) if save_auction(self.request): self.LOGGER.info( 'Created lot item {}'.format(item.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_item_create'}, {'item_id': item.id})) self.request.response.status = 201 item_route = self.request.matched_route.name.replace( "collection_", "") self.request.response.headers[ 'Location'] = self.request.current_route_url( _route_name=item_route, item_id=item.id, _query={}) return {'data': item.serialize("view")}
def collection_post(self): """Add a lot """ auction = self.request.validated['auction'] if auction.status not in ['active.tendering']: self.request.errors.add('body', 'data', 'Can\'t add lot in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return lot = self.request.validated['lot'] lot.date = get_now() auction.lots.append(lot) if save_auction(self.request): self.LOGGER.info('Created auction lot {}'.format(lot.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_lot_create'}, {'lot_id': lot.id})) self.request.response.status = 201 self.request.response.headers['Location'] = self.request.route_url('Auction Lots', auction_id=auction.id, lot_id=lot.id) return {'data': lot.serialize("view")}
def collection_post(self): """Add a lot """ auction = self.request.validated['auction'] if auction.status not in ['active.enquiries']: self.request.errors.add('body', 'data', 'Can\'t add lot in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return lot = self.request.validated['lot'] lot.date = get_now() auction.lots.append(lot) if save_auction(self.request): self.LOGGER.info('Created auction lot {}'.format(lot.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_lot_create'}, {'lot_id': lot.id})) self.request.response.status = 201 self.request.response.headers['Location'] = self.request.route_url('Auction Lots', auction_id=auction.id, lot_id=lot.id) return {'data': lot.serialize("view")}
def collection_post(self): award = self.request.validated['award'] manager = self.request.registry.getAdapter(award, IAwardManagerAdapter) manager.create_award(self.request) if save_auction(self.request): self.LOGGER.info( 'Created auction award {}'.format(award.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_create'}, {'award_id': award.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers[ 'Location'] = self.request.current_route_url(_route_name=route, award_id=award.id, _query={}) return {'data': award.serialize("view")}
def put(self): """Auction Document Update""" if self.request.authenticated_role != 'auction' and self.request.validated['auction_status'] != 'active.tendering' or \ self.request.authenticated_role == 'auction' and self.request.validated['auction_status'] not in ['active.auction', 'active.qualification']: self.request.errors.add('body', 'data', 'Can\'t update document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return document = dgf_upload_file(self.request) self.request.validated['auction'].documents.append(document) if self.request.authenticated_role == 'auction_owner': invalidate_bids_data(self.request.auction) if save_auction(self.request): self.LOGGER.info('Updated auction document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_document_put'})) return {'data': document.serialize("view")}
def delete(self): """Cancelling the proposal Example request for cancelling the proposal: .. sourcecode:: http DELETE /auctions/4879d3f8ee2443169b5fbbc9f89fa607/bids/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "value": { "amount": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ bid = self.request.context if self.request.validated['auction_status'] != 'active.tendering': self.request.errors.add('body', 'data', 'Can\'t delete bid in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if auction.tenderPeriod.startDate and get_now() < auction.tenderPeriod.startDate or get_now() > auction.tenderPeriod.endDate: self.request.errors.add('body', 'data', 'Bid can be deleted only during the tendering period: from ({}) to ({}).'.format(auction.tenderPeriod.startDate and auction.tenderPeriod.startDate.isoformat(), auction.tenderPeriod.endDate.isoformat())) self.request.errors.status = 403 return res = bid.serialize("view") self.request.validated['auction'].bids.remove(bid) self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info('Deleted auction bid {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_delete'})) return {'data': res}
def collection_post(self): """Post a contract for award """ auction = self.request.validated['auction'] if auction.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t add contract in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return contract = self.request.validated['contract'] auction.contracts.append(contract) if save_auction(self.request): self.LOGGER.info('Created auction contract {}'.format(contract.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_contract_create'}, {'contract_id': contract.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=route, contract_id=contract.id, _query={}) return {'data': contract.serialize()}
def put(self): """Auction Award Complaint Document Update""" if self.request.authenticated_role != self.context.author: self.request.errors.add('url', 'role', 'Can update document only author') self.request.errors.status = 403 return if self.request.validated['auction_status'] not in [ 'active.qualification', 'active.awarded' ]: self.request.errors.add( 'body', 'data', 'Can\'t update document in current ({}) auction status'.format( self.request.validated['auction_status'])) self.request.errors.status = 403 return if any([ i.status != 'active' for i in self.request.validated['auction'].lots if i.id == self.request.validated['award'].lotID ]): self.request.errors.add( 'body', 'data', 'Can update document only in active lot status') self.request.errors.status = 403 return if self.request.validated['complaint'].status not in STATUS4ROLE.get( self.request.authenticated_role, []): self.request.errors.add( 'body', 'data', 'Can\'t update document in current ({}) complaint status'. format(self.request.validated['complaint'].status)) self.request.errors.status = 403 return document = upload_file(self.request) document.author = self.request.authenticated_role self.request.validated['complaint'].documents.append(document) if save_auction(self.request): self.LOGGER.info( 'Updated auction award complaint document {}'.format( self.request.context.id), extra=context_unpack( self.request, {'MESSAGE_ID': 'auction_award_complaint_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): """Post a contract for award """ auction = self.request.validated['auction'] contract = self.request.validated['contract'] auction.contracts.append(contract) if save_auction(self.request): self.LOGGER.info( 'Created auction contract {}'.format(contract.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_contract_create'}, {'contract_id': contract.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers[ 'Location'] = self.request.current_route_url( _route_name=route, contract_id=contract.id, _query={}) return {'data': contract.serialize()}
def delete(self): """Lot deleting """ auction = self.request.validated["auction"] if auction.status not in ["active.enquiries"]: self.request.errors.add( "body", "data", "Can't delete lot in current ({}) auction status".format(auction.status) ) self.request.errors.status = 403 return lot = self.request.context res = lot.serialize("view") auction.lots.remove(lot) if save_auction(self.request): self.LOGGER.info( "Deleted auction lot {}".format(self.request.context.id), extra=context_unpack(self.request, {"MESSAGE_ID": "auction_lot_delete"}), ) return {"data": res}
def collection_post(self): """Post a cancellation """ auction = self.request.validated['auction'] if auction.status in ['complete', 'cancelled', 'unsuccessful']: self.request.errors.add( 'body', 'data', 'Can\'t add cancellation in current ({}) auction status'. format(auction.status)) self.request.errors.status = 403 return cancellation = self.request.validated['cancellation'] cancellation.date = get_now() if any([ i.status != 'active' for i in auction.lots if i.id == cancellation.relatedLot ]): self.request.errors.add( 'body', 'data', 'Can add cancellation only in active lot status') self.request.errors.status = 403 return if cancellation.relatedLot and cancellation.status == 'active': self.cancel_lot(cancellation) elif cancellation.status == 'active': self.cancel_auction() auction.cancellations.append(cancellation) if save_auction(self.request): self.LOGGER.info('Created auction cancellation {}'.format( cancellation.id), extra=context_unpack( self.request, {'MESSAGE_ID': 'auction_cancellation_create'}, {'cancellation_id': cancellation.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers[ 'Location'] = self.request.current_route_url( _route_name=route, cancellation_id=cancellation.id, _query={}) return {'data': cancellation.serialize("view")}
def collection_post(self): """Auction Document Upload""" if self.request.authenticated_role != 'auction' and self.request.validated['auction_status'] != 'active.tendering' or \ self.request.authenticated_role == 'auction' and self.request.validated['auction_status'] not in ['active.auction', 'active.qualification']: self.request.errors.add('body', 'data', 'Can\'t add document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return document = dgf_upload_file(self.request) self.context.documents.append(document) if self.request.authenticated_role == 'auction_owner': invalidate_bids_data(self.request.auction) if save_auction(self.request): self.LOGGER.info('Created auction document {}'.format(document.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_document_create'}, {'document_id': document.id})) self.request.response.status = 201 document_route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=document_route, document_id=document.id, _query={}) return {'data': document.serialize("view")}
def collection_post(self): """Post a question """ auction = self.request.validated['auction'] if auction.status != 'active.enquiries' or get_now() < auction.enquiryPeriod.startDate or get_now() > auction.enquiryPeriod.endDate: self.request.errors.add('body', 'data', 'Can add question only in enquiryPeriod') self.request.errors.status = 403 return question = self.request.validated['question'] if any([i.status != 'active' for i in auction.lots if i.id == question.relatedItem]): self.request.errors.add('body', 'data', 'Can add question only in active lot status') self.request.errors.status = 403 return auction.questions.append(question) if save_auction(self.request): self.LOGGER.info('Created auction question {}'.format(question.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_question_create'}, {'question_id': question.id})) self.request.response.status = 201 self.request.response.headers['Location'] = self.request.route_url('Auction Questions', auction_id=auction.id, question_id=question.id) return {'data': question.serialize("view")}
def post(self): """This API request is targeted to creating new Auctions by procuring organizations. """ auction = self.request.validated['auction'] if auction['_internal_type'] == 'geb': manager = self.request.registry.queryMultiAdapter( (self.request, auction), IManager) applicant = self.request.validated['auction'] auction = manager.create(applicant) if not auction: return else: self.request.registry.getAdapter( auction, IAuctionManager).create_auction(self.request) auction_id = generate_id() auction.id = auction_id auction.auctionID = generate_auction_id(get_now(), self.db, self.server_id) if hasattr(auction, "initialize"): auction.initialize() status = self.request.json_body['data'].get('status') if status and status in ['draft', 'pending.verification']: auction.status = status acc = set_ownership(auction, self.request) self.request.validated['auction'] = auction self.request.validated['auction_src'] = {} if save_auction(self.request): self.LOGGER.info( 'Created auction {} ({})'.format(auction['id'], auction.auctionID), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_create'}, { 'auction_id': auction['id'], 'auctionID': auction.auctionID })) self.request.response.status = 201 auction_route_name = get_auction_route_name(self.request, auction) self.request.response.headers['Location'] = self.request.route_url( route_name=auction_route_name, auction_id=auction['id']) return {'data': auction.serialize(auction.status), 'access': acc}
def patch(self): """Post a cancellation resolution """ auction = self.request.validated['auction'] if auction.status in ['complete', 'cancelled', 'unsuccessful']: self.request.errors.add('body', 'data', 'Can\'t update cancellation in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return if any([i.status != 'active' for i in auction.lots if i.id == self.request.context.relatedLot]): self.request.errors.add('body', 'data', 'Can update cancellation only in active lot status') self.request.errors.status = 403 return apply_patch(self.request, save=False, src=self.request.context.serialize()) if self.request.context.relatedLot and self.request.context.status == 'active': self.cancel_lot() elif self.request.context.status == 'active': self.cancel_auction() if save_auction(self.request): self.LOGGER.info('Updated auction cancellation {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_cancellation_patch'})) return {'data': self.request.context.serialize("view")}
def collection_post(self): """Post a complaint for award """ auction = self.request.validated['auction'] if auction.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t add complaint in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return if any([i.status != 'active' for i in auction.lots if i.id == self.context.lotID]): self.request.errors.add('body', 'data', 'Can add complaint only in active lot status') self.request.errors.status = 403 return if self.context.complaintPeriod and \ (self.context.complaintPeriod.startDate and self.context.complaintPeriod.startDate > get_now() or self.context.complaintPeriod.endDate and self.context.complaintPeriod.endDate < get_now()): self.request.errors.add('body', 'data', 'Can add complaint only in complaintPeriod') self.request.errors.status = 403 return complaint = self.request.validated['complaint'] complaint.date = get_now() complaint.relatedLot = self.context.lotID if complaint.status == 'claim': complaint.dateSubmitted = get_now() else: complaint.status = 'draft' complaint.complaintID = '{}.{}{}'.format(auction.auctionID, self.server_id, sum([len(i.complaints) for i in auction.awards], len(auction.complaints)) + 1) set_ownership(complaint, self.request) self.context.complaints.append(complaint) if save_auction(self.request): self.LOGGER.info('Created auction award complaint {}'.format(complaint.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_complaint_create'}, {'complaint_id': complaint.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=route, complaint_id=complaint.id, _query={}) return { 'data': complaint.serialize("view"), 'access': { 'token': complaint.owner_token } }
def put(self): """Auction Bid Document Update""" if self.request.validated['auction_status'] not in ['active.tendering', 'active.qualification']: self.request.errors.add('body', 'data', 'Can\'t update document in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if self.request.validated['auction_status'] == 'active.tendering' and (auction.tenderPeriod.startDate and get_now() < auction.tenderPeriod.startDate or get_now() > auction.tenderPeriod.endDate): self.request.errors.add('body', 'data', 'Document can be updated only during the tendering period: from ({}) to ({}).'.format(auction.auctionPeriod.startDate and auction.auctionPeriod.startDate.isoformat(), auction.auctionPeriod.endDate.isoformat())) self.request.errors.status = 403 return if self.request.validated['auction_status'] == 'active.qualification' and not [i for i in self.request.validated['auction'].awards if i.status == 'pending' and i.bid_id == self.request.validated['bid_id']]: self.request.errors.add('body', 'data', 'Can\'t update document because award of bid is not in pending state') self.request.errors.status = 403 return document = upload_file(self.request) self.request.validated['bid'].documents.append(document) if self.request.validated['auction_status'] == 'active.tendering': self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info('Updated auction bid document {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_document_put'})) return {'data': document.serialize("view")}
def collection_post(self): """Add a lot """ auction = self.request.validated["auction"] if auction.status not in ["active.enquiries"]: self.request.errors.add( "body", "data", "Can't add lot in current ({}) auction status".format(auction.status) ) self.request.errors.status = 403 return lot = self.request.validated["lot"] lot.date = get_now() auction.lots.append(lot) if save_auction(self.request): self.LOGGER.info( "Created auction lot {}".format(lot.id), extra=context_unpack(self.request, {"MESSAGE_ID": "auction_lot_create"}, {"lot_id": lot.id}), ) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers["Location"] = self.request.current_route_url( _route_name=route, lot_id=lot.id, _query={} ) return {"data": lot.serialize("view")}
def patch(self): """Update of award Example request to change the award: .. sourcecode:: http PATCH /auctions/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 } } } """ auction = self.request.validated['auction'] if auction.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update award in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return award = self.request.context if any([i.status != 'active' for i in auction.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, auction, True) auction.contracts.append(type(auction).contracts.model_class({ 'awardID': award.id, 'suppliers': award.suppliers, 'value': award.value, 'date': get_now(), 'items': [i for i in auction.items if i.relatedLot == award.lotID ], 'contractID': '{}-{}{}'.format(auction.auctionID, self.server_id, len(auction.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 auction.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, auction, 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 auction.status == 'active.awarded': auction.status = 'active.qualification' auction.awardPeriod.endDate = None now = get_now() award.complaintPeriod.endDate = now cancelled_awards = [] for i in auction.awards[auction.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 auction.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_auction(self.request): self.LOGGER.info('Updated auction award {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_patch'})) return {'data': award.serialize("view")}
def patch(self): """Auction Edit (partial) For example here is how procuring entity can change number of items to be procured and total Value of a auction: .. sourcecode:: http PATCH /auctions/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", "auctionID": "UA-64e93250be76435397e8c992ed4214d1", "dateModified": "2014-10-27T08:12:34.956Z", "value": { "amount": 600 }, "itemsToBeProcured": [ { "quantity": 6 } ] } } """ auction = self.context if self.request.authenticated_role != 'Administrator' and auction.status in ['complete', 'unsuccessful', 'cancelled']: self.request.errors.add('body', 'data', 'Can\'t update auction in current ({}) status'.format(auction.status)) self.request.errors.status = 403 return if self.request.authenticated_role == 'chronograph': apply_patch(self.request, save=False, src=self.request.validated['auction_src']) check_status(self.request) save_auction(self.request) else: apply_patch(self.request, src=self.request.validated['auction_src']) self.LOGGER.info('Updated auction {}'.format(auction.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_patch'})) return {'data': auction.serialize(auction.status)}
def collection_post(self): """Report auction results. Report auction results ---------------------- Example request to report auction results: .. sourcecode:: http POST /auctions/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['auction_src']) if all([i.auctionPeriod and i.auctionPeriod.endDate for i in self.request.validated['auction'].lots if i.numberOfBids > 1 and i.status == 'active']): add_next_award(self.request) if save_auction(self.request): self.LOGGER.info('Report auction results', extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_auction_post'})) return {'data': self.request.validated['auction'].serialize(self.request.validated['auction'].status)}
def collection_post(self): """Accept or reject bidder application Creating new Award ------------------ Example request to create award: .. sourcecode:: http POST /auctions/4879d3f8ee2443169b5fbbc9f89fa607/awards HTTP/1.1 Host: example.com Accept: application/json { "data": { "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": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } This is what one should expect in response: .. sourcecode:: http HTTP/1.1 201 Created 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": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ auction = self.request.validated['auction'] if auction.status != 'active.qualification': self.request.errors.add('body', 'data', 'Can\'t create award in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return award = self.request.validated['award'] if any([i.status != 'active' for i in auction.lots if i.id == award.lotID]): self.request.errors.add('body', 'data', 'Can create award only in active lot status') self.request.errors.status = 403 return award.complaintPeriod = {'startDate': get_now().isoformat()} auction.awards.append(award) if save_auction(self.request): self.LOGGER.info('Created auction award {}'.format(award.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_create'}, {'award_id': award.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers['Location'] = self.request.current_route_url(_route_name=route, award_id=award.id, _query={}) return {'data': award.serialize("view")}
def collection_post(self): """Registration of new bid proposal Creating new Bid proposal ------------------------- Example request to create bid proposal: .. sourcecode:: http POST /auctions/4879d3f8ee2443169b5fbbc9f89fa607/bids HTTP/1.1 Host: example.com Accept: application/json { "data": { "tenderers": [ { "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": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } This is what one should expect in response: .. sourcecode:: http HTTP/1.1 201 Created Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "status": "registration", "date": "2014-10-28T11:44:17.947Z", "tenderers": [ { "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": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ # See https://github.com/open-contracting/standard/issues/78#issuecomment-59830415 # for more info upon schema auction = self.request.validated['auction'] if self.request.validated['auction_status'] != 'active.tendering': self.request.errors.add('body', 'data', 'Can\'t add bid in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return if auction.tenderPeriod.startDate and get_now() < auction.tenderPeriod.startDate or get_now() > auction.tenderPeriod.endDate: self.request.errors.add('body', 'data', 'Bid can be added only during the tendering period: from ({}) to ({}).'.format(auction.tenderPeriod.startDate and auction.tenderPeriod.startDate.isoformat(), auction.tenderPeriod.endDate.isoformat())) self.request.errors.status = 403 return bid = self.request.validated['bid'] set_ownership(bid, self.request) auction.bids.append(bid) auction.modified = False if save_auction(self.request): self.LOGGER.info('Created auction bid {}'.format(bid.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_create'}, {'bid_id': bid.id})) self.request.response.status = 201 self.request.response.headers['Location'] = self.request.route_url('Auction Bids', auction_id=auction.id, bid_id=bid['id']) return { 'data': bid.serialize('view'), 'access': { 'token': bid.owner_token } }
def patch(self): """Update of contract """ if self.request.validated['auction_status'] not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update contract in current ({}) auction status'.format(self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if any([i.status != 'active' for i in auction.lots if i.id in [a.lotID for a in auction.awards if a.id == self.request.context.awardID]]): self.request.errors.add('body', 'data', 'Can update contract only in active lot status') self.request.errors.status = 403 return data = self.request.validated['data'] if data['value']: for ro_attr in ('valueAddedTaxIncluded', 'currency'): if data['value'][ro_attr] != getattr(self.context.value, ro_attr): self.request.errors.add('body', 'data', 'Can\'t update {} for contract value'.format(ro_attr)) self.request.errors.status = 403 return award = [a for a in auction.awards if a.id == self.request.context.awardID][0] if data['value']['amount'] < award.value.amount: self.request.errors.add('body', 'data', 'Value amount should be greater or equal to awarded amount ({})'.format(award.value.amount)) self.request.errors.status = 403 return if self.request.context.status != 'active' and 'status' in data and data['status'] == 'active': award = [a for a in auction.awards if a.id == self.request.context.awardID][0] stand_still_end = award.complaintPeriod.endDate if stand_still_end > get_now(): self.request.errors.add('body', 'data', 'Can\'t sign contract before stand-still period end ({})'.format(stand_still_end.isoformat())) self.request.errors.status = 403 return pending_complaints = [ i for i in auction.complaints if i.status in ['claim', 'answered', 'pending'] and i.relatedLot in [None, award.lotID] ] pending_awards_complaints = [ i for a in auction.awards for i in a.complaints if i.status in ['claim', 'answered', 'pending'] and a.lotID == award.lotID ] if pending_complaints or pending_awards_complaints: self.request.errors.add('body', 'data', 'Can\'t sign contract before reviewing all complaints') self.request.errors.status = 403 return contract_status = self.request.context.status apply_patch(self.request, save=False, src=self.request.context.serialize()) if contract_status != self.request.context.status and (contract_status != 'pending' or self.request.context.status != 'active'): self.request.errors.add('body', 'data', 'Can\'t update contract status') self.request.errors.status = 403 return if self.request.context.status == 'active' and not self.request.context.dateSigned: self.request.context.dateSigned = get_now() check_auction_status(self.request) if save_auction(self.request): self.LOGGER.info('Updated auction contract {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_contract_patch'})) return {'data': self.request.context.serialize()}
def patch(self): """Post a complaint resolution for award """ auction = self.request.validated['auction'] if auction.status not in ['active.qualification', 'active.awarded']: self.request.errors.add('body', 'data', 'Can\'t update complaint in current ({}) auction status'.format(auction.status)) self.request.errors.status = 403 return if any([i.status != 'active' for i in auction.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 if self.context.status not in ['draft', 'claim', 'answered', 'pending']: self.request.errors.add('body', 'data', 'Can\'t update complaint in current ({}) status'.format(self.context.status)) self.request.errors.status = 403 return data = self.request.validated['data'] complaintPeriod = self.request.validated['award'].complaintPeriod is_complaintPeriod = complaintPeriod.startDate < get_now() and complaintPeriod.endDate > get_now() if complaintPeriod.endDate else complaintPeriod.startDate < get_now() # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in ['draft', 'claim', 'answered', 'pending'] and data.get('status', self.context.status) == 'cancelled': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif self.request.authenticated_role == 'complaint_owner' and is_complaintPeriod and self.context.status == 'draft' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and is_complaintPeriod and self.context.status == 'draft' and data.get('status', self.context.status) == 'claim': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is True and data.get('status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get('satisfied', self.context.satisfied) is False and data.get('status', self.context.status) == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() # auction_owner elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get('resolution', self.context.resolution) and len(data.get('resolution', self.context.resolution or "")) >= 20 and data.get('resolutionType', self.context.resolutionType) and data.get('status', self.context.status) == 'answered': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAnswered = get_now() elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) # reviewers elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get('status', self.context.status) in ['resolved', 'invalid', 'declined']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() else: self.request.errors.add('body', 'data', 'Can\'t update complaint') self.request.errors.status = 403 return if self.context.tendererAction and not self.context.tendererActionDate: self.context.tendererActionDate = get_now() if self.context.status not in ['draft', 'claim', 'answered', 'pending'] and auction.status in ['active.qualification', 'active.awarded']: check_auction_status(self.request) if save_auction(self.request): self.LOGGER.info('Updated auction award complaint {}'.format(self.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_award_complaint_patch'})) return {'data': self.context.serialize("view")}