class Unittest(unittest.TestCase): def setUp(self): self.tools = Tools() def test_get_utc_epoch(self): date = '13.04.2018 13:40' result = self.tools.get_utc_epoch(date) self.assertEqual(1523608800000, result) def test_get_utc_epoch_none(self): date = None result = self.tools.get_utc_epoch(date) self.assertIsNone(result)
class Unittest(unittest.TestCase): def setUp(self): self.tools = Tools() def test_get_utc_epoch(self): date = '14.05.2018' result = self.tools.get_utc_epoch(date) self.assertEqual(1526256000000, result)
class Mapper: """ Класс-маппер (перевод из обработанных данных в модель для отправки в менеджер очередей RabbitMQ) """ def __init__(self): self.tools = Tools() @staticmethod def get_organisations_search(lot, org): """на roseltorg.ru кпп не указано""" return lot['customer'] if lot['customer'] else '' @staticmethod def get_customer_model_list(lot, org): return [{ 'guid': None, 'name': lot['customer'] if lot['customer'] else org['name'], 'region': int(org['region']) if org['region'] else None }] @staticmethod def get_global_search(item, lot): return '{} {} {} {}'.format( item['number'], item['name'] if item['name'] else '', lot['customer'] if lot['customer'] else '', item['type'] if item['type'] else '' ) @staticmethod def get_tender_search(item, lot): return '{} {} {}'.format( item['number'] if item['number'] else '', item['name'] if item['name'] else lot['name'], lot['customer'] if lot['customer'] else '' ) def get_attachments(self, files): attachments = [] for file in files: attachments.append({ 'displayName': file['display_name'], 'href': file['url'], 'publicationDateTime': self.tools.get_utc_epoch( file['publication_date'][0], file['publication_date'][1]), 'realName': file['real_name'], 'size': None }) return attachments def map(self, item, multilot, org, attachments, lot, tender_lot_id): """ Функция маппинга итоговой модели """ model = { # Идентификатор тендера (Тендер+Лот) # Для каждого лота в тендере создается отдельная модель 'id': tender_lot_id, # Массив заказчиков # [{ # guid = идентификатор организации (str/None), # name = название организации (str), # region = регион организации (int/None), # }] 'customers': self.get_customer_model_list(lot, org), # массив документов 'attachments': self.get_attachments(attachments), 'globalSearch': self.get_global_search(item, lot), 'guaranteeApp': lot['guarantee_app'], 'href': item['link'], 'json': None, # Максимальная (начальная) цена тендера 'maxPrice': lot['price'], 'multilot': multilot, 'number': item['number'], # Массив ОКПД (если присутствует) ex. ['11.11', '20.2'] 'okdp': [], # Массив ОКПД2 (если присутствует) 'okpd': [], # Массив ОКДП (если присутствует) 'okpd2': [i.split()[0] for i in lot['okpd2']] if lot['okpd2'] else [], 'orderName': item['name'], 'organisationsSearch': self.get_organisations_search(lot, org), 'placingWay': self.get_placingway(item['type']), 'platform': { 'href': 'https://etpgpb.ru/', 'name': 'ЭТП ГПБ', }, # Дата публикации тендера UNIX EPOCH (UTC) 'publicationDateTime': self.tools.get_utc_epoch(lot['publication_date'][0], lot['publication_date'][1]), 'region': int(org['region']) if org['region'] else None, # Дата окончания подачи заявок UNIX EPOCH (UTC) 'submissionCloseDateTime': self.tools.get_utc_epoch( lot['sub_close_date'][0], lot['sub_close_date'][1]) if lot['sub_close_date'] else None, # Дата начала подачи заявок UNIX EPOCH (UTC) 'submissionStartDateTime': self.tools.get_utc_epoch(lot['publication_date'][0], lot['publication_date'][1]), 'tenderSearch': self.get_tender_search(item, lot), # Дата маппинга модели в UNIX EPOCH (UTC) (milliseconds) 'timestamp': self.tools.get_utc(), 'status': self.get_status(lot['status']), # Версия извещения # Если на площадке нет версии, то ставить 1 'version': 1, 'kind': 0, 'type': 18, 'ktru': ["string"], "modification": { 'modDateTime': '', 'reason': '' }, 'futureNumber': 'string', 'scoringDateTime': 'long', 'biddingDateTime': 'long', 'preference': [], 'group': None, } model['json'] = self.get_json( model, lot, org ) return model def get_placingway(self, org_form): """ Получение способа определения поставщика т.к. на площадке присутствуют не все виды, то задействованы только присутствующие # Открытый конкурс = 1, # Открытый аукцион = 2, # Открытый аукцион в электронной форме = 3, # Запрос котировок = 4, # Предварительный отбор = 5, # Закупка у единственного поставщика (подрядчика, исполнителя) = 6, # Конкурс с ограниченным участием = 7, # Двухэтапный конкурс = 8, # Закрытый конкурс = 9, # Закрытый конкурс с ограниченным участием = 10, # Закрытый двухэтапный конкурс = 11, # Закрытый аукцион = 12, # Запрос котировок без размещения извещения = 13, # Запрос предложений = 14, # Электронный аукцион = 15, # Иной многолотовый способ = 16, # Сообщение о заинтересованности в проведении открытого конкурса = 17, # Иной однолотовый способ = 18 """ if org_form in ['Аукцион на повышение', 'Аукцион на понижение']: return 15 elif org_form in ['Запрос предложений']: return 14 elif org_form in ['Запрос цен']: return 16 elif org_form in ['Попозиционные торги']: return 18 elif org_form in ['Запрос котировок']: return 4 elif org_form in ['Предварительный отбор']: return 5 elif org_form in ['Конкурс']: return 1 elif org_form in ['Открытая тендерная закупка в электронной форме']: return 16 else: return 5000 @staticmethod def get_status(string): """ Получения статуса тендера при изменении статуса тендер должен отсылаться в RabbitMQ # Без статуса = 0, # Опубликован = 1, # На рассмотрении комиссии = 2, # Закрыт = 3, # Отменен = 4, # Приостановлен = 5, # Исполнение завершено = 6, # Исполняется = 7, # Приостановлено определение поставщика = 8 т.к. на площадке присутствуют не все виды, то задействованы только присутствующие status[ , , , , , , , ] """ if string is None or string.strip() == '': return 0 elif string in ['Прием заявок на участие', ]: return 1 elif string in ['Подведение итогов', 'Вскрытие конвертов', 'Рассмотрение первых частей заявок']: return 2 elif string in ['Заключение договора', 'Проведение аукциона']: return 7 elif string in ['Архив']: return 3 elif string == 'Процедура отменена': return 4 @staticmethod def get_currency_mod(lot_currency): if lot_currency == 'RUB': return Modification.CurRUB elif lot_currency == 'USD': return Modification.CurUSD elif lot_currency == 'EUR': return Modification.CurEUR def get_json(self, model, lot, org): """ Получение модели для рендера Использует sharedmodel модуль В данной модели обязательно присутствие: * general - основная информация * customer - заказчик В данной модели должно быть как можно больше информации о тендере (сроки поставки, вскрытия конвертов итп) """ return Root()\ .add_customer( Customer().set_properties( max_price=model['maxPrice'], guarantee_app=model['guaranteeApp'], guarantee_contract=None, customer_guid=model['customers'][0]['guid'], customer_name=model['customers'][0]['name'] ) ).add_category( lambda c: c.set_properties( name='ObjectInfo', displayName='Информация об объекте закупки', ).add_table( lambda t: t.set_properties( name='Objects', displayName='Объекты закупки' ).set_header( lambda th: th.add_cells([ Head(name='Name', displayName='Наименования товара, работы, услуги'), Head(name='Count', displayName='Количество') ]) ).add_rows( [element for element in enumerate(lot['positions'], start=1)], lambda el, row: row.add_cells([ Cell( name='Name', type=FieldType.String, value=el[1].get('name').strip('"'), modifications=[] ), Cell( name='Count', type=FieldType.String, value=el[1].get('quantity'), modifications=[] ) ]) ) ) ).add_category( lambda c: c.set_properties( name='procedureInfo', displayName='Порядок размещения заказа', modifications=[] ).add_field( Field( name='PublicationtDateTime', displayName='Дата публикации', value=model['publicationDateTime'], type=FieldType.DateTime, modifications=[Modification.Calendar] ) ).add_field( Field( name='AcceptOrderEndDateTime', displayName='Дата и время окончания срока приема заявок', value=model['submissionCloseDateTime'], type=FieldType.DateTime, modifications=[Modification.Calendar] ) ).add_field( Field( name='ScoringStartDateTime', displayName='Дата и время вскрытия заявок', value=self.tools.get_utc_epoch( lot['order_view_date'][0], lot['order_view_date'][1]) if lot['order_view_date'] else None, type=FieldType.DateTime, modifications=[] ) ).add_field( # Field( name='ScoringEndDateTime', displayName='Дата подведения итогов', value=self.tools.get_utc_epoch( lot['scoring_date'][0], lot['scoring_date'][1]) if lot['scoring_date'] else None, type=FieldType.DateTime, modifications=[] ) ).add_field( Field( name='TradeDateTime', displayName='Дата проведения торгов', value=self.tools.get_utc_epoch( lot['trade_date'][0], lot['trade_date'][1]) if lot['trade_date'] else None, type=FieldType.Date, modifications=[] ) ) ).add_category( lambda c: c.set_properties( name='Contacts', displayName='Контактная информация', modifications=[] ).add_field(Field( name='Organization', displayName='Организация', value=org['name'], type=FieldType.String, modifications=[] ) ).add_field(Field( name='ActualAddress', displayName='Фактический адрес', value=org['actual_address'], type=FieldType.String, modifications=[] ) ).add_field(Field( name='PostAddress', displayName='Почтовый адрес', value=org['post_address'], type=FieldType.String, modifications=[] ) ).add_array( lambda ar: ar.set_properties( name='Contacts', displayName='Контакты', modifications=[Modification.HiddenLabel] ).add_field(Field( name='FIO', displayName='ФИО', value=org['fio'], type=FieldType.String, modifications=[Modification.HiddenLabel] ) ).add_field(Field( name='Phone', displayName='Телефон', value=org['phone'], type=FieldType.String, modifications=[] ) ).add_field(Field( name='Email', displayName='Электронная почта', value=org['email'], type=FieldType.String, modifications=[Modification.Email] ) ) ) ).add_general( lambda f: f.set_properties( name='Quantity', displayName='Количество поставляемого товара/объем выполняемых работ/оказываемых услуг', value=lot['quantity'], type=FieldType.String, modifications=[] ) ).add_general( lambda f: f.set_properties( name='deliveryPlace', displayName='Место поставки товаров оказания услуг', value=lot['delivery_place'] if lot['delivery_place'] else '', type=FieldType.String, modifications=[] ) ).add_general( lambda f: f.set_properties( name='PaymentTerms', displayName='Условия оплаты и поставки товаров/выполнения работ/оказания услуг', value=lot['payment_terms'] if lot['payment_terms'] else '', type=FieldType.String, modifications=[] ) ).to_json()
class Http(): def __init__(self): cfg = configparse() self.parser = Parser() cfg_mongo = cfg['mongodb'] self.repository = MongoRepository(cfg_mongo['host'], cfg_mongo['port'], cfg_mongo['database'], cfg_mongo['collection']) self.tools = Tools() def get_page_list(self, starturl): Startpage = [] index = requests.get(starturl) y = 0 x = 0 while True: Startpage.append(starturl) print("add page", x) x = x + 1 for href in Selector(index.text).css( '.pagination ul :last-child a::attr(href)').extract(): url = urljoin(index.url, href) sel = Selector(requests.get(url).text) if url == starturl: break else: starturl = url index = requests.get(starturl) return Startpage def get_special_tender_list(self, starturl): SpecialTenderInfo = set() index = requests.get(starturl) for href in Selector( index.text).css('.purchase-title a::attr(href)').extract(): url = urljoin(index.url, href) sel = Selector(requests.get(url).text) id = sel.css(' .purchase-single-head span::text').extract_first() title = handler( sel.css(' .purchase-single-head h2').extract_first()) if self.parser.special_search(title) is not None: SpecialTenderInfo.add(id) return list(SpecialTenderInfo) def get_tender_list(self, starturl, status, time): """Возвращает списком c данными для тендеров""" TenderInfo = set() index = requests.get(starturl) for href in Selector( index.text).css('.purchase-title a::attr(href)').extract(): url = urljoin(index.url, href) sel = Selector(requests.get(url).text) id = sel.css(' .purchase-single-head span::text').extract_first() dbmodel = self.repository.get_one('{}'.format(id)) info = handler( sel.css('.purchase-single-head .purchase-single-info::text'). extract_first()) tm = info[info.find("|") + 20:info.rfind("|") - 1] #Проверка с базой в середине функции, мне казалось,что брейк просто бы остановил цикл в колекте продолжилось бы выполнение, тут сравнение со временем можно регулировать, накинуть дни например if dbmodel is not None and dbmodel['_id'] == id and dbmodel[ 'status'] == status and dbmodel[ 'time'] == self.tools.get_utc_epoch(tm) and ( time is not None and (self.tools.get_utc_epoch(tm)) < time): sys.exit(0) if dbmodel is not None and dbmodel['_id'] == id and dbmodel[ 'status'] == status and dbmodel[ 'time'] == self.tools.get_utc_epoch(tm): print("Coincidence? I don't think so ...") continue title = handler( sel.css(' .purchase-single-head h2').extract_first()) organization = sel.css( ' .purchase-single-filters a::text').extract_first() TenderInfo.add(( id, href, title[title.find("]") + 2:], organization, tm, info[info.find("|") - 12:info.find("|")], )) a = list(TenderInfo) return a def get_tender_mindate(self, url): index = requests.get(url) for href in Selector( index.text).css('.purchase-title a::attr(href)').extract(): url = urljoin(index.url, href) sel = Selector(requests.get(url).text) info = handler( sel.css('.purchase-single-head .purchase-single-info::text'). extract_first()) a = info[info.find("|") + 20:info.rfind("|") - 1] #Неполучилось воспользщоваться функцией из Tools, поэтому скопировал (ಥ﹏ಥ) date = datetime.strptime( a.replace('\n', '').replace('\t', '').replace('\r', '').strip(), '%d.%m.%Y') ep_time = (date - datetime(1970, 1, 1)).total_seconds() * 1000 break return int(ep_time) def get_tender_contacts(self, tender_number): """Возвращает HTML документ с контактами для тендера""" starturl = 'http://tenders.polyusgold.com/purchases/{}'.format( tender_number) sel = Selector(requests.get(starturl).text) a = sel.css(' .purchase-single-body').extract_first() return a def get_tender_lots(self, tender_id, tender_number, token): """Возвращает JSON со списком лотов для тендера""" url = 'https://zakupki.ugmk.com/Tenders/LoadLots/{}'.format(tender_id) headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Cookie': 'ASP.NET_SessionId=vvselgjio1azsx5igfremgcb; __RequestVerificationToken_Lw__={}' .format(token), 'Host': 'zakupki.ugmk.com', 'Origin': 'https://zakupki.ugmk.com', 'Pragma': 'no-cache', 'Referer': 'https://zakupki.ugmk.com/Tender/{}'.format(tender_number), 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest' } data = { 'offset': 0, 'limit': 1000, 'sortColumn': None, 'sortAsc': False, '__RequestVerificationToken': token } r = requests.post(url, data, headers=headers) return r.json()['Rows'] def get_tender_data(self, tender_number): """Возвращает HTML документ с данными тендера""" url = 'http://tenders.polyusgold.com/purchases/{}'.format( tender_number) r = requests.get(url) return r.text def get_tender_documents(self, tender_number): """Получение HTML с документами тендера""" #TenderInfo = set() starturl = 'http://tenders.polyusgold.com/purchases/{}'.format( tender_number) sel = Selector(requests.get(starturl).text) a = sel.css(' .purchase-single-docs ul').extract_first() return a def get_lot_data(self, lot_url, tender_number, token): """Возвращает HTML с данными для лота""" url = 'https://zakupki.ugmk.com{}'.format(lot_url) headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Cookie': 'ASP.NET_SessionId=vvselgjio1azsx5igfremgcb; __RequestVerificationToken_Lw__={}' .format(token), 'Host': 'zakupki.ugmk.com', 'Pragma': 'no-cache', 'Referer': 'https://zakupki.ugmk.com/Tender/{}'.format(tender_number), 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' } r = requests.get(url, headers=headers) return r.text def get_lot_documents(self, entity_id, lot_url, token): url = 'https://zakupki.ugmk.com/Documents/List?entityTypeCode=TenderLot&entityUid={}'.format( entity_id) headers = { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Cookie': 'ASP.NET_SessionId=vvselgjio1azsx5igfremgcb; __RequestVerificationToken_Lw__=K3dfzSt3g/2sa7vr2mJqfDTCyXcqWyLBvjQ7Omjx2Alt6sT63z9CQ43PEsPx7cPND1LSl1GmDQ+MlQX806uU7WV3Sm00gdhatsjwNQXDDe7KnvzYWnAiDNTAr28sZSElM/4l7PBVnzo2tOM6SfQY7mPkdS2hE0G5AckN1/mudaA=', 'Host': 'zakupki.ugmk.com', 'Origin': 'https://zakupki.ugmk.com', 'Pragma': 'no-cache', 'Referer': 'https://zakupki.ugmk.com{}'.format(lot_url), 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest' } data = {'__RequestVerificationToken': token} r = requests.post(url, data, headers=headers) return r.text def get_lot_stages(self, lot_uid, lot_url, token): url = 'https://zakupki.ugmk.com/Tenders/LoadNotices?lotUId={}'.format( lot_uid) headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Cookie': 'SP.NET_SessionId=vvselgjio1azsx5igfremgcb; __RequestVerificationToken_Lw__={}' .format(token), 'Host': 'zakupki.ugmk.com', 'Origin': 'https://zakupki.ugmk.com', 'Pragma': 'no-cache', 'Referer': 'https://zakupki.ugmk.com/{}'.format(lot_url), 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest' } data = { 'offset': 0, 'limit': 1000, 'sortColumn': None, 'sortAsc': False, '__RequestVerificationToken': token } r = requests.post(url, data, headers=headers) return r.json() def get_organization_page(self, company_id, token): url = 'https://zakupki.ugmk.com/Companies/Details/{}'.format( company_id) headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Cookie': 'ASP.NET_SessionId=vvselgjio1azsx5igfremgcb; __RequestVerificationToken_Lw__={}' .format(token), 'Host': 'zakupki.ugmk.com', 'Pragma': 'no-cache', 'Referer': 'https://zakupki.ugmk.com/Tender/T-000001749', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' } r = requests.get(url, headers=headers) return r.text def get_organization(self, name, inn, kpp): url = 'http://organizationHost/organization?inn={}&kpp={}&name={}'.format( inn, kpp, name) # r = requests.get(url) # return r.json() # заглушка if name is None: return None return {'guid': None, 'name': name, 'region': None} def get_stages_list(self, lot_uid, lot_url, token): url = 'https://zakupki.ugmk.com/Tenders/LoadNotices?lotUId={}'.format( lot_uid) headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Cookie': 'ASP.NET_SessionId=vvselgjio1azsx5igfremgcb; __RequestVerificationToken_Lw__={}' .format(token), 'Host': 'zakupki.ugmk.com', 'Origin': 'https://zakupki.ugmk.com', 'Pragma': 'no-cache', 'Referer': 'https://zakupki.ugmk.com{}'.format(lot_url), 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest' } data = { 'offset': 0, 'limit': 1000, 'sortColumn': None, 'sortAsc': False, '__RequestVerificationToken': token } r = requests.post(url, data, headers=headers) return r.json()['Rows']
class Mapper(): def __init__(self): self.tools = Tools() def map_short(self, model): return { '_id': model['_id'], 'status': model['status'], } def map_participant(self, participant): return { 'admitted': True, 'evolveDateTime': None, 'guid': participant['guid'], 'name': participant['name'], 'price': None, 'region': participant['region'], 'rejectionCodes': [], 'winner': True # потому что на этой площадке из участников показывается только победитель } def map(self, item, item1, item2, item3, item4, item5, multilot, attachments, customer, contacts, s): customer_search = '' if customer is None else '{} {}'.format( customer.get('name'), customer.get('region')) #participant_search = '' if participant is None else '{} {}'.format(participant.get('guid'), participant.get('name')) okpd = [] okpd2 = [] okdp = [] ktru = [] #print([customer][0]['name']) model = { '_id': '{}'.format(item), 'customers': [] if customer is None else [customer], #'participants': [] if participant is None else [self.map_participant(participant)], 'type': 30, #change 'timestamp': self.tools.get_utc(), 'number': item, 'group': item, 'kind': 0, 'orderName': item2, 'maxPrice': None, 'submissionCloseDateTime': self.tools.get_utc_epoch(item4), 'submissionStartDateTime': None, 'publicationDateTime': self.tools.get_utc_epoch(item5), 'guaranteeApp': None, 'guaranteeContract': None, 'preference': [], 'placingWay': 5000, 'region': customer.get('region') if customer is not None else None, 'okpd': okpd, 'okpd2': okpd2, 'okdp': okdp, 'ktru': ktru, 'prepayment': None, 'organisationsSearch': '{}'.format(customer_search).strip(), 'tenderSearch': '{} {} {}'.format(item, item2, customer.get('name')), 'globalSearch': '{} {} {} {}'.format(okdp, okpd, okpd2, (item, item2, customer.get('name'))), 'version': 1, # версия тендера если есть изменения???????? 'multiLot': multilot, 'json': None, 'attachments': attachments, 'platform': { 'href': "http://tenders.polyusgold.com/", 'name': "«ПАО Полюс»", }, 'href': 'http://tenders.polyusgold.com/purchases/{}'.format(item1), 'modification': None, #??????? 'futureNumber': None, #?????? "guid": '{}'.format(customer.get('guid')), #???????? 'scoringDateTime': None, 'biddingDateTime': None, 'status': s #self.get_status(item['LotStatusName']) } json = self.get_json(model, contacts, item3) model.update({'json': json}) return model def get_placingway(self, placingway, org_form): if placingway == 'Аукцион' and org_form == 'Закрытая': return 12 elif placingway == 'Аукцион' and org_form == 'Открытая': return 2 elif placingway == 'Конкурс' and org_form == 'Закрытая': return 9 elif placingway == 'Конкурс' and org_form == 'Открытая': return 1 elif placingway == 'Запрос цен' and org_form == 'Закрытая': return 4 elif placingway == 'Запрос цен' and org_form == 'Открытая': return 4 else: return 0 # fortyfour = { # "Открытый конкурс": 1, # "Открытый аукцион": 2, # "Открытый аукцион в электронной форме": 3, # "Запрос котировок": 4, # "Предварительный отбор": 5, # "Закупка у единственного поставщика (подрядчика, исполнителя)": 6, # "Конкурс с ограниченным участием": 7, # "Двухэтапный конкурс": 8, # "Закрытый конкурс": 9, # "Закрытый конкурс с ограниченным участием": 10, # "Закрытый двухэтапный конкурс": 11, # "Закрытый аукцион": 12, # "Запрос котировок без размещения извещения": 13, # "Запрос предложений": 14, # "Электронный аукцион": 15, # "Иной многолотовый способ": 16, # "Сообщение о заинтересованности в проведении открытого конкурса": 17, # "Иной однолотовый способ": 18 # } def get_status(self, string): if string is None or string.strip() == '': return 0 #elif string == 'Опубликовано': # return 1 #elif string == 'Прием заявок': # return 2 elif string: return 2 elif string == 'Проведена': return 3 #elif string == 'Завершен': # return 7 #elif string == 'Не состоялся с выбором победителя' or string == 'Отменен': # return 4 #elif string == 'Договор завершен': # return 6 #elif string == 'Не состоялся' \ # or string == 'Не состоялся с заключением договора' \ # or string == 'Не состоялся без заключения договора': # return 5 #elif string == 'Заменен новой версией': # return 0 # Без статуса # None = 0, # Опубликован # Active = 1, # На рассмотрении комиссии # Commission = 2, # Закрыт # Closed = 3, # Отменен # Cancel = 4, # Приостановлен # Abandoned = 5, # Исполнение завершено # Played = 6, # Исполняется # Playing = 7, # Приостановлено определение поставщика # Suspended = 8 def get_json(self, model, contacts, organization): return Root() \ .add_general( Field( name="MaxPrice", type=FieldType.Price, value=model['maxPrice'], displayName="Цена контракта" ) ) \ .add_customer( Customer().set_properties( max_price=None, guarantee_app=None, guarantee_contract=None, customer_guid=model['customers'][0]['guid'], customer_name=model['customers'][0]['name'] ) ) \ .add_category( lambda c: c.set_properties( name='ProcedureInfo', displayName='Порядок размещения заказа' ).add_field(Field( name='AcceptOrderEndDateTime', displayName='Дата окончания приема заявок', value=model['submissionCloseDateTime'], type=FieldType.DateTime, modifications=[Modification.Calendar] )) ) \ .add_category( lambda c: c.set_properties( name='Contacts', displayName='Контактная информация' ).add_field(Field( name='Organization', displayName='Организация', value=organization, type=FieldType.String )).add_array( lambda ar: ar.set_properties( name='Contacts', displayName='Контакты', modifications=[Modification.HiddenLabel] ).add_field(Field( name='FIO', displayName='ФИО', value=contacts[0]['name'], type=FieldType.String, modifications=[Modification.HiddenLabel] )).add_field(Field( name='Phone', displayName='Телефон', value=contacts[0]['phone'], type=FieldType.String, modifications=[] )).add_field(Field( name='Email', displayName='Электронная почта', value=contacts[0]['email'], type=FieldType.String, modifications=[] )) ) ) \ .to_json()