def approve_bids_information(self): if self.current_stage in self._bids_data: LOGGER.info( "Current stage bids {}".format(self._bids_data[self.current_stage]), extra={"JOURNAL_REQUEST_ID": self.request_id} ) bid_info = get_latest_bid_for_bidder( self._bids_data[self.current_stage], self.auction_document["stages"][self.current_stage]['bidder_id'] ) if bid_info['yearlyPaymentsPercentage'] == -0.01: LOGGER.info( "Latest bid is bid cancellation: {}".format(bid_info), extra={"JOURNAL_REQUEST_ID": self.request_id, "MESSAGE_ID": AUCTION_WORKER_BIDS_LATEST_BID_CANCELLATION} ) return False bid_info = {key: bid_info[key] for key in BIDS_KEYS_FOR_COPY} bid_info["bidder_name"] = self.mapping[bid_info['bidder_id']] bid_info['amount'] = bid_info['amount'] if self.features: bid_info['amount_features'] = Fraction(bid_info['amount']) * self.bidders_coeficient[bid_info['bidder_id']] self.auction_document["stages"][self.current_stage] = prepare_bids_stage( self.auction_document["stages"][self.current_stage], bid_info ) self.auction_document["stages"][self.current_stage]["changed"] = True return True else: return False
def end_sealedbid(self, stage): with utils.update_auction_document(self): self._end_sealedbid.set() while not self.bids_queue.empty(): LOGGER.info("Waiting for bids to process") sleep(0.1) LOGGER.info("Done processing bids queue") if len(self._bids_data.keys()) < 2: LOGGER.info("No bids on sealedbid phase. end auction") self.end_auction() return all_bids = deepcopy(self._bids_data) minimal_bids = [] max_bid = {'amount': 0} # init sealedbid winner bid for bid_id in all_bids.keys(): bid = get_latest_bid_for_bidder(all_bids[bid_id], bid_id) bid['bidder_name'] = self.mapping[bid['bidder_id']] minimal_bids.append(utils.prepare_results_stage(**bid)) # find a winner max_bid = max([max_bid, bid], key=lambda bid: bid['amount']) minimal_bids = sorting_by_amount(minimal_bids) self.auction_document['results'] = minimal_bids # save winner to stages in auction_document max_bid['sealedbid_winner'] = True self.auction_document['stages'][ self.auction_document['current_stage']].update( utils.prepare_results_stage(**max_bid)) run_time = utils.update_stage(self) self.approve_audit_info_on_sealedbid(run_time) self.auction_document['current_phase'] = PREBESTBID
def post_results_data(self, with_auctions_results=True): patch_data = {'data': {'bids': list(self._auction_data['data']['bids'])}} if with_auctions_results: for bid_index, bid in enumerate(self._auction_data['data']['bids']): if bid.get('status', 'active') == 'active': for lot_index, lot_bid in enumerate(bid['lotValues']): if lot_bid['relatedLot'] == self.lot_id and lot_bid.get( 'status', 'active') == 'active': auction_bid_info = get_latest_bid_for_bidder( self.auction_document["results"], bid["id"]) patch_data['data']['bids'][bid_index]['lotValues'][ lot_index]["value"]["amount"] = auction_bid_info[ "amount"] patch_data['data']['bids'][bid_index]['lotValues'][ lot_index]["date"] = auction_bid_info["time"] break logger.info("Approved data: {}".format(patch_data), extra={ "JOURNAL_REQUEST_ID": self.request_id, "MESSAGE_ID": AUCTION_WORKER_API_APPROVED_DATA }) results = make_request(self.tender_url + '/auction/{}'.format(self.lot_id), data=patch_data, user=self.worker_defaults["TENDERS_API_TOKEN"], method='post', request_id=self.request_id, session=self.session) return results
def _post_results_data(self, external_data, db_document): """ :param auction_data: data from api :param auction_document: data from auction module couchdb :return: response from api where data is posted """ request_id = generate_request_id() result_bids = deepcopy(db_document["results"]) posted_result_data = deepcopy(external_data["data"]["bids"]) for index, bid_info in enumerate(external_data["data"]["bids"]): if bid_info.get('status', 'active') == 'active': auction_bid_info = get_latest_bid_for_bidder( result_bids, bid_info["id"]) posted_result_data[index]["value"][ "amount"] = auction_bid_info["amount"] posted_result_data[index]["date"] = auction_bid_info["time"] data = {'data': {'bids': posted_result_data}} LOGGER.info("Approved data: {}".format(data), extra={ "JOURNAL_REQUEST_ID": request_id, "MESSAGE_ID": AUCTION_WORKER_API_APPROVED_DATA }) return make_request(self.api_url + '/auction', data=data, user=self.api_token, method='post', request_id=request_id, session=self.session)
def post_results_data(self, with_auctions_results=True): if with_auctions_results: all_bids = self.auction_document["results"] for index, bid_info in enumerate(self._auction_data["data"]["bids"]): if bid_info.get('status', 'active') == 'active': auction_bid_info = get_latest_bid_for_bidder( all_bids, bid_info["id"]) self._auction_data["data"]["bids"][index]["value"]["amount"] =\ auction_bid_info["amount"] self._auction_data["data"]["bids"][index]["date"] =\ auction_bid_info["time"] data = {'data': {'bids': self._auction_data["data"]['bids']}} LOGGER.info("Approved data: {}".format(data), extra={ "JOURNAL_REQUEST_ID": self.request_id, "MESSAGE_ID": AUCTION_WORKER_API_APPROVED_DATA }) return make_request(self.tender_url + '/auction', data=data, user=self.worker_defaults["resource_api_token"], method='post', request_id=self.request_id, session=self.session)
def start_auction(self, switch_to_round=None): self.generate_request_id() self.audit['timeline']['auction_start']['time'] = datetime.now( tzlocal()).isoformat() LOGGER.info('---------------- Start auction ----------------', extra={ "JOURNAL_REQUEST_ID": self.request_id, "MESSAGE_ID": AUCTION_WORKER_SERVICE_START_AUCTION }) self.get_auction_info() self.get_auction_document() # Initital Bids bids = deepcopy(self.bidders_data) self.auction_document["initial_bids"] = [] bids_info = sorting_start_bids_by_amount(bids, features=self.features) for index, bid in enumerate(bids_info): amount = bid["value"]["amount"] audit_info = { "bidder": bid["id"], "date": bid["date"], "amount": amount } if self.features: amount_features = cooking(amount, self.features, self.bidders_features[bid["id"]]) coeficient = self.bidders_coeficient[bid["id"]] audit_info["amount_features"] = str(amount_features) audit_info["coeficient"] = str(coeficient) else: coeficient = None amount_features = None self.audit['timeline']['auction_start']['initial_bids'].append( audit_info) self.auction_document["initial_bids"].append( prepare_initial_bid_stage( time=bid["date"] if "date" in bid else self.startDate, bidder_id=bid["id"], bidder_name=self.mapping[bid["id"]], amount=amount, coeficient=coeficient, amount_features=amount_features)) if isinstance(switch_to_round, int): self.auction_document["current_stage"] = switch_to_round else: self.auction_document["current_stage"] = 0 all_bids = deepcopy(self.auction_document["initial_bids"]) minimal_bids = [] for bid_info in self.bidders_data: minimal_bids.append( get_latest_bid_for_bidder(all_bids, str(bid_info['id']))) minimal_bids = self.filter_bids_keys(sorting_by_amount(minimal_bids)) self.update_future_bidding_orders(minimal_bids) self.save_auction_document()
def prepare_auction_results(auction, bids_data): all_bids = deepcopy(bids_data) max_bids = [] for bid_id in all_bids.keys(): bid = get_latest_bid_for_bidder(all_bids[bid_id], bid_id) bid['bidder_name'] = auction.mapping[bid['bidder_id']] max_bids.append( prepare_results_stage(**bid) ) return sorting_by_amount(max_bids)
def post_results_data(auction, with_auctions_results=True): """TODO: make me work""" def generate_value(bid_info): auction_bid = bid_info['amount'] if str(bid_info['amount']) != '-1'\ else None value = auction.auction_document['value'] return { "amount": str(auction_bid), "currency": value.get('currency'), "valueAddedTaxIncluded": value.get('valueAddedTaxIncluded') } info = auction.get_auction_info() bids = info['data'].get("bids", []) if with_auctions_results: for bid_info in bids: if bid_info.get('status', 'active') == 'active': bidder_id = bid_info.get('bidder_id', bid_info.get('id', '')) if bidder_id: try: bid = get_latest_bid_for_bidder( auction.auction_document['results'], bidder_id ) except IndexError: bid = '' if bid: bid_info['value'] = generate_value(bid) bid_info['date'] = bid['time'] data = {'data': {'bids': bids}} LOGGER.info( "Approved data: {}".format(data), extra={"JOURNAL_REQUEST_ID": auction.request_id, "MESSAGE_ID": AUCTION_WORKER_API_APPROVED_DATA} ) if not auction.debug: return make_request( auction.tender_url + '/auction', data=data, user=auction.worker_defaults["resource_api_token"], method='post', request_id=auction.request_id, session=auction.session ) LOGGER.info( "Making request to api with params {}".format( dict(method="post", url=auction.tender_url + '/auction', data=data))) return data
def end_bids_stage(self, switch_to_round=None): self.generate_request_id() self.bids_actions.acquire() self.get_auction_document() LOGGER.info( '---------------- End Bids Stage ----------------', extra={"JOURNAL_REQUEST_ID": self.request_id, "MESSAGE_ID": AUCTION_WORKER_SERVICE_END_BID_STAGE} ) self.current_round = self.get_round_number( self.auction_document["current_stage"] ) self.current_stage = self.auction_document["current_stage"] if self.approve_bids_information(): LOGGER.info("Approved bid on current stage") start_stage, end_stage = self.get_round_stages(self.current_round) all_bids = deepcopy( self.auction_document["stages"][start_stage:end_stage] ) minimal_bids = [] for bid_info in self.bidders_data: minimal_bids.append( get_latest_bid_for_bidder(all_bids, bid_info['id']) ) minimal_bids = self.filter_bids_keys( sorting_by_amount(minimal_bids, reverse=False) ) self.update_future_bidding_orders(minimal_bids) self.approve_audit_info_on_bid_stage() if isinstance(switch_to_round, int): self.auction_document["current_stage"] = switch_to_round else: self.auction_document["current_stage"] += 1 LOGGER.info('---------------- Start stage {0} ----------------'.format( self.auction_document["current_stage"]), extra={"JOURNAL_REQUEST_ID": self.request_id, "MESSAGE_ID": AUCTION_WORKER_SERVICE_START_STAGE} ) self.save_auction_document() if self.auction_document["stages"][self.auction_document["current_stage"]]['type'] == 'pre_announcement': self.end_auction() self.bids_actions.release() if self.auction_document["current_stage"] == (len(self.auction_document["stages"]) - 1): self._end_auction_event.set()
def end_bestbid(self, stage): with utils.update_auction_document(self): all_bids = deepcopy(self._bids_data) minimal_bids = [] for bid_id in all_bids.keys(): bid = get_latest_bid_for_bidder(all_bids[bid_id], bid_id) bid['bidder_name'] = self.mapping[bid['bidder_id']] minimal_bids.append(utils.prepare_results_stage(**bid)) minimal_bids = sorting_by_amount(minimal_bids) self.auction_document['results'] = minimal_bids run_time = utils.update_stage(self) self.approve_audit_info_on_bestbid(run_time) self.end_auction()
def post_results_data(auction, with_auctions_results=True): """TODO: make me work""" if with_auctions_results: for index, bid_info in enumerate( auction._auction_data["data"]["bids"]): if bid_info.get('status', 'active') == 'active': bidder_id = bid_info.get('bidder_id', bid_info.get('id', '')) if bidder_id: try: bid = get_latest_bid_for_bidder( auction.auction_document['results'], bidder_id) except IndexError: bid = '' if bid: auction._auction_data["data"]["bids"][index]["value"][ "amount"] = bid['amount'] auction._auction_data["data"]["bids"][index][ "date"] = bid['time'] data = {'data': {'bids': auction._auction_data["data"]['bids']}} LOGGER.info("Approved data: {}".format(data), extra={ "JOURNAL_REQUEST_ID": auction.request_id, "MESSAGE_ID": AUCTION_WORKER_API_APPROVED_DATA }) if not auction.debug: return make_request(auction.tender_url + '/auction', data=data, user=auction.worker_defaults["resource_api_token"], method='post', request_id=auction.request_id, session=auction.session) else: LOGGER.info("Making request to api with params {}".format( dict(method="post", url=auction.tender_url + '/auction', data=data))) return data
def prepare_auction_stages_fast_forward(self): self.auction_document['auction_type'] = 'meat' if self.features else 'default' bids = deepcopy(self.bidders_data) self.auction_document["initial_bids"] = [] bids_info = sorting_start_bids_by_amount(bids, features=self.features, reverse=False) for index, bid in enumerate(bids_info): amount = bid["value"]["amountPerformance"] annualCostsReduction = bid["value"]["annualCostsReduction"] if self.features: amount_features = cooking( amount, self.features, self.bidders_features[bid["id"]], reverse=True ) coeficient = self.bidders_coeficient[bid["id"]] else: coeficient = None amount_features = None initial_bid_stage = prepare_initial_bid_stage( time=bid["date"] if "date" in bid else self.startDate, bidder_id=bid["id"], bidder_name=self.mapping[bid["id"]], amount=amount, coeficient=coeficient, amount_features=amount_features, annualCostsReduction=annualCostsReduction, yearlyPaymentsPercentage=bid["value"]["yearlyPaymentsPercentage"], contractDurationDays=bid["value"]["contractDuration"].get("days", None), contractDurationYears=bid["value"]["contractDuration"].get("years", None) ) self.auction_document["initial_bids"].append( initial_bid_stage ) self.auction_document['stages'] = [] next_stage_timedelta = datetime.now(tzlocal()) for round_id in xrange(ROUNDS): # Schedule PAUSE Stage pause_stage = prepare_service_stage( start=next_stage_timedelta.isoformat(), stage="pause" ) self.auction_document['stages'].append(pause_stage) # Schedule BIDS Stages for index in xrange(self.bidders_count): bid_stage = prepare_bids_stage({ 'start': next_stage_timedelta.isoformat(), 'bidder_id': '', 'bidder_name': '', 'amount': '0', "contractDurationDays": "0", "contractDurationYears": "0", "yearlyPaymentsPercentage": "0", 'time': '', }) self.auction_document['stages'].append(bid_stage) next_stage_timedelta += timedelta(seconds=BIDS_SECONDS) self.auction_document['stages'].append( prepare_service_stage( start=next_stage_timedelta.isoformat(), type="pre_announcement" ) ) self.auction_document['stages'].append( prepare_service_stage( start="", type="announcement" ) ) all_bids = deepcopy(self.auction_document["initial_bids"]) minimal_bids = [] for bid_info in self.bidders_data: minimal_bids.append(get_latest_bid_for_bidder( all_bids, str(bid_info['id']) )) minimal_bids = self.filter_bids_keys(sorting_by_amount(minimal_bids, reverse=False)) self.update_future_bidding_orders(minimal_bids) self.auction_document['endDate'] = next_stage_timedelta.isoformat() self.auction_document["current_stage"] = len(self.auction_document["stages"]) - 2