def patch_decisions_with_lot_by_broker(self): self.app.authorization = ('Basic', ('broker', '')) self.initial_status = 'draft' self.create_resource() decision_data = [ { 'decisionID': 'decID', 'decisionDate': get_now().isoformat() }, { 'decisionID': 'decID2', 'decisionDate': get_now().isoformat() } ] decision_data = { 'decisions': decision_data } check_patch_status_200(self, '/{}'.format(self.resource_id), 'composing', self.access_header) response = self.app.patch_json( '/{}'.format(self.resource_id), params={'data': decision_data}, headers=self.access_header ) self.assertNotIn('decisions', response.json)
def test_generate_id(self, mock_project_configurator): test_prefix = 'TEST-ID' mock_project_configurator.LOT_PREFIX = test_prefix result = generate_lot_id(get_now(), self.db) key = get_now().date().isoformat() index = self.db.get(key, 1) mock_id = '{}-{:04}-{:02}-{:02}-{:06}{}'.format( test_prefix, get_now().year, get_now().month, get_now().day, index, '') self.assertEqual(result, mock_id)
def check_lot_status(request, lot, now=None): if not now: now = get_now() if lot.status == 'pending' and lot.next_check <= now: LOGGER.info('Switched lot %s to %s', lot.id, 'active.salable', extra=context_unpack(request, {'MESSAGE_ID': 'switched_lot_active.salable'})) lot.status = 'active.salable'
def rectificationPeriod_auction_workflow(self): rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) data = deepcopy(self.initial_auctions_data) lot = self.create_resource() # Change rectification period in db fromdb = self.db.get(lot['id']) fromdb = Lot(fromdb) fromdb.status = 'pending' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) self.assertEqual(fromdb.id, lot['id']) response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) response = self.app.get('/{}/auctions'.format(self.resource_id)) auctions = sorted(response.json['data'], key=lambda a: a['tenderAttempts']) english = auctions[0] response = self.app.patch_json('/{}/auctions/{}'.format( lot['id'], english['id']), headers=self.access_header, params={'data': data['english']}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change auctions after rectification period')
def add_lot_decision(self, lot_id, headers): old_authorization = self.app.authorization self.app.authorization = ('Basic', ('broker', '')) response = self.app.get('/{}'.format(lot_id)) old_decs_count = len(response.json['data'].get('decisions', [])) decision_data = { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionLotID' } response = self.app.post_json('/{}/decisions'.format(lot_id), {"data": decision_data}, headers=headers) self.assertEqual(response.status, '201 Created') self.assertEqual(response.json['data']['decisionDate'], decision_data['decisionDate']) self.assertEqual(response.json['data']['decisionID'], decision_data['decisionID']) response = self.app.get('/{}'.format(lot_id)) present_decs_count = len(response.json['data'].get('decisions', [])) self.assertEqual(old_decs_count + 1, present_decs_count) self.app.authorization = old_authorization return response.json['data']
def _set_rectificationPeriod(self, request): data = dict() data['startDate'] = get_now() data['endDate'] = calculate_business_date(data['startDate'], RECTIFICATION_PERIOD_DURATION, None) request.context.rectificationPeriod = type(request.context).rectificationPeriod.model_class(data)
def add_decisions(self, lot): asset_decision = { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID', 'decisionOf': 'asset', 'relatedItem': '1' * 32 } data_with_decisions = {"decisions": [lot['decisions'][0], asset_decision]} response = self.app.patch_json('/{}'.format(lot['id']), params={'data': data_with_decisions}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']['decisions'][0]['decisionOf'], 'lot') self.assertEqual(response.json['data']['decisions'][0]['id'], data_with_decisions['decisions'][0]['id']) self.assertEqual(response.json['data']['decisions'][0]['decisionID'], data_with_decisions['decisions'][0]['decisionID']) self.assertNotIn('relatedItem', response.json['data']['decisions'][0]) self.assertEqual(response.json['data']['decisions'][1]['decisionOf'], 'asset') self.assertIsNotNone(response.json['data']['decisions'][1].get('id')) self.assertEqual(response.json['data']['decisions'][1]['decisionID'], data_with_decisions['decisions'][1]['decisionID']) self.assertEqual(response.json['data']['decisions'][1]['relatedItem'], data_with_decisions['decisions'][1]['relatedItem'])
def create_decisions_with_lot(self): data = deepcopy(self.initial_data) decision_1 = {'id': '1' * 32, 'decisionID': 'decID', 'decisionDate': get_now().isoformat()} decision_2 = deepcopy(decision_1) decision_2['id'] = '2' * 32 data['decisions'] = [ decision_1, decision_2 ] response = self.app.post_json('/', params={'data': data}) decision_1['decisionOf'] = 'lot' decision_2['decisionOf'] = 'lot' self.assertEqual(response.status, '201 Created') self.assertEqual(len(response.json['data']['decisions']), 2) self.assertEqual(response.json['data']['decisions'][0], decision_1) self.assertEqual(response.json['data']['decisions'][1], decision_2) del decision_1['decisionOf'] del decision_2['decisionOf'] decision_2['id'] = '1' * 32 data['decisions'] = [ decision_1, decision_2 ] response = self.app.post_json('/', params={'data': data}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual( response.json['errors'][0]['description'][0], u'Decision id should be unique for all decisions' )
def create_or_patch_decision_in_not_allowed_status(self): self.app.authorization = ('Basic', ('broker', '')) self.initial_status = 'draft' self.create_resource() check_patch_status_200(self, '/{}'.format(self.resource_id), 'composing', self.access_header) lot = add_lot_decision(self, self.resource_id, self.access_header) add_lot_related_process(self, self.resource_id, self.access_header) add_auctions(self, lot, self.access_header) check_patch_status_200(self, '/{}'.format(self.resource_id), 'verification', self.access_header) decision_data = { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionLotID' } response = self.app.post_json('/{}/decisions'.format(self.resource_id), {"data": decision_data}, headers=self.access_header, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]['description'], 'Can\'t update decisions in current (verification) lot status')
def rectificationPeriod_item_validation(request, error_handler, **kwargs): if request.validated['lot'].rectificationPeriod and request.validated[ 'lot'].rectificationPeriod.endDate < get_now(): request.errors.add( 'body', 'mode', 'You can\'t change items after rectification period') request.errors.status = 403 raise error_handler(request)
def rectificationPeriod_item_workflow(self): rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) lot = self.create_resource() response = self.app.post_json('/{}/items'.format(lot['id']), headers=self.access_header, params={'data': self.initial_item_data}) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') item_id = response.json["data"]['id'] self.assertIn(item_id, response.headers['Location']) self.assertEqual(self.initial_item_data['description'], response.json["data"]["description"]) self.assertEqual(self.initial_item_data['quantity'], response.json["data"]["quantity"]) self.assertEqual(self.initial_item_data['address'], response.json["data"]["address"]) item_id = response.json['data']['id'] response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) # Change rectification period in db fromdb = self.db.get(lot['id']) fromdb = Lot(fromdb) fromdb.status = 'pending' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) self.assertEqual(fromdb.id, lot['id']) response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) response = self.app.post_json('/{}/items'.format(lot['id']), headers=self.access_header, params={'data': self.initial_item_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change items after rectification period') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change items after rectification period') response = self.app.patch_json('/{}/items/{}'.format(lot['id'], item_id), headers=self.access_header, params={'data': self.initial_item_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change items after rectification period')
def rectificationPeriod_auction_validation(request, error_handler, **kwargs): is_rectificationPeriod_finished = bool( request.validated['lot'].rectificationPeriod and request.validated['lot'].rectificationPeriod.endDate < get_now() ) if request.authenticated_role != 'convoy' and is_rectificationPeriod_finished: request.errors.add('body', 'mode', 'You can\'t change auctions after rectification period') request.errors.status = 403 raise error_handler(request)
def from_initial_to_decisions(self): request_path = '/?opt_pretty=1' self.initial_data['decisions'] = [ { 'decisionDate': get_now().isoformat(), 'decisionID': 'initialDecisionID' } ] response = self.app.post_json(request_path, {"data": self.initial_data}) self.assertEqual(response.status, '201 Created') lot = response.json['data'] lot_id = response.json['data']['id'] owner_token = response.json['access']['token'] response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') response = self.app.get('/{}/auctions'.format(lot_id)) auctions = response.json['data'] english = auctions[0] access_header = {'X-Access-Token': str(owner_token)} # Switch to 'composing' response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'composing'}}) self.assertEqual(response.status, '200 OK') # Compose lot with first english data response = self.app.patch_json( '/{}/auctions/{}'.format(lot_id, english['id']), params={'data': auction_common}, headers=access_header) self.assertEqual(response.status, '200 OK') # Add relatedProcess to lot # related_process = { 'relatedProcessID': uuid4().hex, 'type': 'asset' } response = self.app.post_json( '/{}/related_processes'.format(lot_id), params={'data': related_process}, headers=access_header) self.assertEqual(response.status, '201 Created') # Switch to 'verification' response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'verification'}}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('concierge', '')) add_decisions(self, lot) return lot, lot_id, owner_token
def _create_auctions(self, request): lot = request.validated['lot'] lot.date = get_now() auction_types = [DEFAULT_PROCUREMENT_TYPE] auction_class = lot.__class__.auctions.model_class for auction_type in auction_types: data = dict() data['procurementMethodType'] = auction_type data['status'] = 'scheduled' data['__parent__'] = lot lot.auctions.append(auction_class(data))
def validate_verification_status(request, error_handler): if request.validated['data'].get( 'status' ) == 'verification' and request.context.status == 'composing': # Decision validation if not any(decision.decisionOf == 'lot' for decision in request.context.decisions): raise_operation_error( request, error_handler, 'Can\'t switch to verification while lot decisions not available.' ) # Auction validation lot = request.validated['lot'] auctions = sorted(lot.auctions, key=lambda a: a.tenderAttempts) english = auctions[0] auction_error_message = get_auction_validation_result(lot) # Raise errors from first and second auction if auction_error_message['description']: request.errors.add(**auction_error_message) request.errors.status = 422 raise error_handler(request) duration = DAYS_AFTER_RECTIFICATION_PERIOD + RECTIFICATION_PERIOD_DURATION min_auction_start_date = calculate_business_date(start=get_now(), delta=duration, context=lot, working_days=True) auction_period = english.auctionPeriod if auction_period and min_auction_start_date > auction_period.startDate: request.errors.add( 'body', 'mode', 'startDate of auctionPeriod must be ' 'at least in {} days after today'.format(duration.days)) request.errors.status = 422 raise error_handler(request) if not lot.relatedProcesses: request.errors.add( 'body', 'mode', 'You can set verification status ' 'only when lot have at least one relatedProcess') request.errors.status = 422 raise error_handler(request) if request.errors: raise error_handler(request)
def patch_decisions_with_lot_by_concierge(self): self.app.authorization = ('Basic', ('broker', '')) self.initial_status = 'draft' self.create_resource() decision_data = [{ 'decisionID': 'decID', 'decisionDate': get_now().isoformat(), 'relatedItem': '1' * 32, 'decisionOf': 'asset' }] decision_data = {'decisions': decision_data} check_patch_status_200(self, '/{}'.format(self.resource_id), 'composing', self.access_header) add_lot_decision(self, self.resource_id, self.access_header) lot = add_lot_related_process(self, self.resource_id, self.access_header) add_auctions(self, lot, self.access_header) check_patch_status_200(self, '/{}'.format(self.resource_id), 'verification', self.access_header) self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}'.format(self.resource_id), params={'data': decision_data}, headers=self.access_header) decision = response.json['data']['decisions'][0] self.assertEqual(decision['decisionID'], decision_data['decisions'][0]['decisionID']) self.assertEqual(decision['decisionDate'], decision_data['decisions'][0]['decisionDate']) self.assertEqual(decision['relatedItem'], decision_data['decisions'][0]['relatedItem']) self.assertEqual(decision['decisionOf'], decision_data['decisions'][0]['decisionOf']) decision_id = decision['id'] response = self.app.get('/{}/decisions/{}'.format(self.resource_id, decision_id)) self.assertEqual(response.json['data']['id'], decision_id) self.assertEqual(response.json['data']['decisionID'], decision_data['decisions'][0]['decisionID']) self.assertEqual(response.json['data']['decisionDate'], decision_data['decisions'][0]['decisionDate']) self.assertEqual(response.json['data']['relatedItem'], decision_data['decisions'][0]['relatedItem']) self.assertEqual(response.json['data']['decisionOf'], decision_data['decisions'][0]['decisionOf'])
def _create_auctions(self, request): lot = request.validated['lot'] lot.date = get_now() auction_types = ['sellout.english', 'sellout.english', 'sellout.insider'] auction_class = lot.__class__.auctions.model_class for tenderAttempts, auction_type in enumerate(auction_types, 1): data = dict() data['tenderAttempts'] = tenderAttempts data['procurementMethodType'] = auction_type data['status'] = 'scheduled' data['auctionParameters'] = {} if auction_type == 'sellout.english': data['auctionParameters']['type'] = 'english' elif auction_type == 'sellout.insider': data['auctionParameters']['type'] = 'insider' data['auctionParameters']['dutchSteps'] = DEFAULT_DUTCH_STEPS lot.auctions.append(auction_class(data))
def get_role(self): root = self.__parent__ request = root.request if request.authenticated_role == 'Administrator': role = 'Administrator' elif request.authenticated_role == 'concierge': role = 'concierge' elif request.authenticated_role == 'convoy': role = 'convoy' else: after_rectificationPeriod = bool( request.context.rectificationPeriod and request.context.rectificationPeriod.endDate < get_now()) if request.context.status == 'pending' and after_rectificationPeriod: return 'edit_pendingAfterRectificationPeriod' role = 'edit_{}'.format(request.context.status) return role
def rectificationPeriod_auction_document_validation(request, error_handler, **kwargs): is_period_ended = bool( request.validated['lot'].rectificationPeriod and request.validated['lot'].rectificationPeriod.endDate < get_now()) if is_period_ended and request.method == 'POST': request.errors.add( 'body', 'mode', 'You can\'t add documents to auction after rectification period') request.errors.status = 403 raise error_handler(request) if is_period_ended and request.method in ['PUT', 'PATCH']: request.errors.add( 'body', 'mode', 'You can\'t change documents after rectification period') request.errors.status = 403 raise error_handler(request)
def rectificationPeriod_document_validation(request, error_handler, **kwargs): is_period_ended = bool( request.validated['lot'].rectificationPeriod and request.validated['lot'].rectificationPeriod.endDate < get_now()) if (is_period_ended and request.validated['document'].documentType != 'cancellationDetails') and request.method == 'POST': request.errors.add( 'body', 'mode', 'You can add only document with cancellationDetails after rectification period' ) request.errors.status = 403 raise error_handler(request) if is_period_ended and request.method in ['PUT', 'PATCH']: request.errors.add( 'body', 'mode', 'You can\'t change documents after rectification period') request.errors.status = 403 raise error_handler(request)
def test_docs_tutorial_with_concierge(self): ### Switch to invalid workflow ### lot, lot_id, owner_token = self.from_initial_to_decisions() self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}'.format(lot_id), params={'data': {"status": 'invalid'}}) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/lot-after-concierge-switch-to-invalid.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') ### Switch to deleted workflow ### self.app.authorization = ('Basic', ('broker', '')) lot, lot_id, owner_token = self.from_initial_to_decisions() access_header = {'X-Access-Token': str(owner_token)} # switch lot to 'pending' asset_items = [test_loki_item_data] lot = self.app.get('/{}'.format(lot_id)).json['data'] related_process_id = lot['relatedProcesses'][0]['id'] response = self.app.patch_json('/{}/related_processes/{}'.format(lot_id, related_process_id), {'data': {'identifier': 'UA-AR-P-2018-08-17-000002-1'}}) self.assertEqual(response.status, '200 OK') concierge_patch = { 'status': 'pending', 'items': asset_items, 'title': 'Нежитлове приміщення', 'description': 'Нежитлове приміщення для збереження насіння', 'lotHolder': {'name': 'Власник лоту', 'identifier': {'scheme': 'AE-ADCD', 'id': '11111-4'}}, 'lotCustodian': { 'name': 'Зберігач лоту', 'address': {'countryName': 'Україна'}, 'identifier': {'scheme': 'AE-ADCD', 'id': '11111-4'}, 'contactPoint': {'name': 'Сергій', 'email': '*****@*****.**'} }, 'decisions': [ lot['decisions'][0], {'decisionID': '11111-4-5', 'relatedItem': uuid4().hex, 'decisionOf': 'asset'} ] } response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': concierge_patch}) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/lot-after-concierge-patch-pending-2.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('broker', '')) add_cancellationDetails_document(self, lot, access_header) # switch lot to 'deleted' response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'pending.deleted'}}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'deleted'}}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('broker', '')) with open('docs/source/tutorial/lot-delete-3pc.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') ### Switch to pending.dissolution workflow ### self.app.authorization = ('Basic', ('broker', '')) lot, lot_id, owner_token = self.from_initial_to_decisions() access_header = {'X-Access-Token': str(owner_token)} # switch lot to 'pending' asset_items = [test_loki_item_data] lot = self.app.get('/{}'.format(lot_id)).json['data'] related_process_id = lot['relatedProcesses'][0]['id'] response = self.app.patch_json('/{}/related_processes/{}'.format(lot_id, related_process_id), {'data': {'identifier': 'UA-AR-P-2018-08-17-000002-1'}}) self.assertEqual(response.status, '200 OK') concierge_patch = { 'status': 'pending', 'items': asset_items, 'title': 'Нежитлове приміщення', 'description': 'Нежитлове приміщення для збереження насіння', 'lotHolder': {'name': 'Власник лоту', 'identifier': {'scheme': 'AE-ADCD', 'id': '11111-4'}}, 'lotCustodian': { 'name': 'Зберігач лоту', 'address': {'countryName': 'Україна'}, 'identifier': {'scheme': 'AE-ADCD', 'id': '11111-4'}, 'contactPoint': {'name': 'Сергій', 'email': '*****@*****.**'} }, 'decisions': [ lot['decisions'][0], {'decisionID': '11111-4-5', 'relatedItem': uuid4().hex, 'decisionOf': 'asset'} ] } response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': concierge_patch}) self.assertEqual(response.status, '200 OK') rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date(rectificationPeriod.startDate, timedelta(1), None) # change rectification period in db fromdb = self.db.get(lot['id']) fromdb = self.lot_model(fromdb) fromdb.status = 'pending' fromdb.decisions = [ { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' }, { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' } ] fromdb.title = 'title' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) lot = fromdb self.assertEqual(fromdb.id, lot['id']) # switch lot to 'active.salable' response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/{}'.format(lot['id']), params={'data': {'title': ' PATCHED'}}) self.assertNotEqual(response.json['data']['title'], 'PATCHED') self.assertEqual(lot['title'], response.json['data']['title']) self.assertEqual(response.json['data']['status'], 'active.salable') with open('docs/source/tutorial/concierge-patched-lot-to-active.salable.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') # switch lot to 'active.auction' self.app.authorization = ('Basic', ('concierge', '')) with open('docs/source/tutorial/switch-lot-active.auction.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}'.format(lot_id), {'data': {"status": 'active.auction'}}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('convoy', '')) auction_id = lot['auctions'][0]['id'] response = self.app.patch_json('/{}/auctions/{}'.format(lot_id, auction_id), {'data': {"status": 'complete'}}) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/lot-after-convoy-patch-auction-complete.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') fromdb = self.db.get(lot['id']) fromdb = self.lot_model(fromdb) fromdb.status = 'active.auction' fromdb.auctions[0].status = 'active' fromdb.store(self.db) # switch to 'pending.dissolution' response = self.app.patch_json('/{}/auctions/{}'.format(lot_id, auction_id), {'data': {"status": 'cancelled'}}) self.assertEqual(response.status, '200 OK') response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.json['data']['status'], 'pending.dissolution') with open('docs/source/tutorial/lot-after-convoy-patch-auction-cancelled.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('concierge', '')) # Switch to 'dissolved' response = self.app.patch_json('/{}'.format(lot_id), {'data': {"status": 'dissolved'}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['status'], 'dissolved') with open('docs/source/tutorial/lot-after-concierge-patch-lot-dissolved.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') ### Switch to sold workflow ### self.app.authorization = ('Basic', ('broker', '')) lot, lot_id, owner_token = self.from_initial_to_decisions() # switch lot to 'pending' response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'pending', 'items': asset_items}}) self.assertEqual(response.status, '200 OK') rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date(rectificationPeriod.startDate, timedelta(1), None) # change rectification period in db fromdb = self.db.get(lot['id']) fromdb = self.lot_model(fromdb) fromdb.status = 'pending' fromdb.decisions = [ { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' }, { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' } ] fromdb.title = 'title' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) lot = fromdb self.assertEqual(fromdb.id, lot['id']) # switch lot to 'active.salable' response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/{}'.format(lot['id']), params={'data': {'title': ' PATCHED'}}) self.assertNotEqual(response.json['data']['title'], 'PATCHED') self.assertEqual(lot['title'], response.json['data']['title']) self.assertEqual(response.json['data']['status'], 'active.salable') response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') # switch lot to 'active.auction' self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}'.format(lot_id), {'data': {"status": 'active.auction'}}) self.assertEqual(response.status, '200 OK') # switch to 'active.contracting' self.app.authorization = ('Basic', ('convoy', '')) auction_id = lot['auctions'][0]['id'] response = self.app.patch_json('/{}/auctions/{}'.format(lot_id, auction_id), {'data': {"status": 'complete'}}) self.assertEqual(response.status, '200 OK') # switch to 'pending.sold' self.app.authorization = ('Basic', ('caravan', '')) contract_id = lot['contracts'][0]['id'] response = self.app.patch_json('/{}/contracts/{}'.format(lot_id, contract_id), {'data': {"status": 'complete'}}) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/lot-after-caravan-patch-contract-complete.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') # switch to 'sold' self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}'.format(lot_id), {'data': {"status": 'sold'}}) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/lot-after-concierge-patch-lot-sold.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK')
def rectificationPeriod_decision_workflow(self): rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) self.create_resource() response = self.app.get('/{}'.format(self.resource_id)) lot = response.json['data'] self.set_status('draft') add_auctions(self, lot, access_header=self.access_header) self.set_status('pending') add_lot_decision(self, lot['id'], self.access_header) response = self.app.post_json('/{}/decisions'.format(lot['id']), headers=self.access_header, params={'data': self.initial_decision_data}) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') decision_id = response.json["data"]['id'] self.assertIn(decision_id, response.headers['Location']) self.assertEqual(self.initial_decision_data['decisionID'], response.json["data"]["decisionID"]) self.assertEqual(self.initial_decision_data['decisionDate'], response.json["data"]["decisionDate"]) self.assertEqual('lot', response.json["data"]["decisionOf"]) decision_id = response.json['data']['id'] response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) # Change rectification period in db fromdb = self.db.get(lot['id']) fromdb = Lot(fromdb) fromdb.status = 'pending' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) self.assertEqual(fromdb.id, lot['id']) response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) response = self.app.post_json('/{}/decisions'.format(lot['id']), headers=self.access_header, params={'data': self.initial_decision_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]['description'], 'You can\'t change or add decisions after rectification period') response = self.app.patch_json('/{}/decisions/{}'.format( lot['id'], decision_id), headers=self.access_header, params={'data': self.initial_decision_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]['description'], 'You can\'t change or add decisions after rectification period')
def rectificationPeriod_document_workflow(self): rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) lot = self.create_resource() response = self.app.post_json('/{}/documents'.format(self.resource_id), headers=self.access_header, params={'data': self.initial_document_data}) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) # Change rectification period in db fromdb = self.db.get(lot['id']) fromdb = Lot(fromdb) fromdb.status = 'pending' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) self.assertEqual(fromdb.id, lot['id']) response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) response = self.app.post_json('/{}/documents'.format(lot['id']), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]['description'], 'You can add only document with cancellationDetails after rectification period' ) response = self.app.patch_json('/{}/documents/{}'.format( lot['id'], doc_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change documents after rectification period') response = self.app.put_json('/{}/documents/{}'.format(lot['id'], doc_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change documents after rectification period') test_document_data = { # 'url': self.generate_docservice_url(), 'title': u'укр.doc', 'hash': 'md5:' + '0' * 32, 'format': 'application/msword', 'documentType': 'cancellationDetails' } test_document_data['url'] = self.generate_docservice_url() response = self.app.post_json('/{}/documents'.format(lot['id']), headers=self.access_header, params={'data': test_document_data}) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] response = self.app.patch_json('/{}/documents/{}'.format( lot['id'], doc_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change documents after rectification period') response = self.app.put_json('/{}/documents/{}'.format(lot['id'], doc_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change documents after rectification period')
def test_docs_tutorial_with_concierge(self): ### Switch to invalid workflow ### lot, lot_id, owner_token = self.from_initial_to_decisions() self.app.authorization = ('Basic', ('concierge', '')) with open('docs/source/tutorial/switch-lot-to-invalid.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}'.format(lot_id), params={'data': { "status": 'invalid' }}) self.assertEqual(response.status, '200 OK') ### Switch to deleted workflow ### self.app.authorization = ('Basic', ('broker', '')) lot, lot_id, owner_token = self.from_initial_to_decisions() access_header = {'X-Access-Token': str(owner_token)} # switch lot to 'pending' with open('docs/source/tutorial/switch-lot-to-pending.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}?acc_token={}'.format(lot_id, owner_token), {'data': { "status": 'pending' }}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('broker', '')) add_cancellationDetails_document(self, lot, access_header) # switch lot to 'deleted' with open('docs/source/tutorial/lot-delete-3pc.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}?acc_token={}'.format(lot_id, owner_token), {'data': { "status": 'pending.deleted' }}) self.assertEqual(response.status, '200 OK') ### Switch to pending.dissolution workflow ### self.app.authorization = ('Basic', ('broker', '')) lot, lot_id, owner_token = self.from_initial_to_decisions() access_header = {'X-Access-Token': str(owner_token)} # switch lot to 'pending' response = self.app.patch_json( '/{}?acc_token={}'.format(lot_id, owner_token), {'data': { "status": 'pending' }}) self.assertEqual(response.status, '200 OK') rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) # change rectification period in db fromdb = self.db.get(lot['id']) fromdb = self.lot_model(fromdb) fromdb.status = 'pending' fromdb.decisions = [{ 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' }, { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' }] fromdb.title = 'title' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) lot = fromdb self.assertEqual(fromdb.id, lot['id']) # switch lot to 'active.salable' response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/{}'.format(lot['id']), params={'data': { 'title': ' PATCHED' }}) self.assertNotEqual(response.json['data']['title'], 'PATCHED') self.assertEqual(lot['title'], response.json['data']['title']) self.assertEqual(response.json['data']['status'], 'active.salable') with open( 'docs/source/tutorial/concierge-patched-lot-to-active.salable.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') # switch lot to 'active.auction' self.app.authorization = ('Basic', ('concierge', '')) with open('docs/source/tutorial/switch-lot-active.auction.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}'.format(lot_id), {'data': { "status": 'active.auction' }}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('convoy', '')) with open('docs/source/tutorial/switch-lot-active.contracting.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}'.format(lot_id), {'data': { "status": 'active.contracting' }}) self.assertEqual(response.status, '200 OK') # switch to 'pending.dissolution' with open('docs/source/tutorial/patch-lot-to-pending.dissolution.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}'.format(lot_id), {'data': { "status": 'pending.dissolution' }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['status'], 'pending.dissolution') self.app.authorization = ('Basic', ('concierge', '')) # Switch to 'dissolved' with open('docs/source/tutorial/patch-lot-to-dissolved.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}'.format(lot_id), {'data': { "status": 'dissolved' }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['status'], 'dissolved') ### Switch to sold workflow ### self.app.authorization = ('Basic', ('broker', '')) lot, lot_id, owner_token = self.from_initial_to_decisions() # switch lot to 'pending' response = self.app.patch_json( '/{}?acc_token={}'.format(lot_id, owner_token), {'data': { "status": 'pending' }}) self.assertEqual(response.status, '200 OK') rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) # change rectification period in db fromdb = self.db.get(lot['id']) fromdb = self.lot_model(fromdb) fromdb.status = 'pending' fromdb.decisions = [{ 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' }, { 'decisionDate': get_now().isoformat(), 'decisionID': 'decisionAssetID' }] fromdb.title = 'title' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) lot = fromdb self.assertEqual(fromdb.id, lot['id']) # switch lot to 'active.salable' response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/{}'.format(lot['id']), params={'data': { 'title': ' PATCHED' }}) self.assertNotEqual(response.json['data']['title'], 'PATCHED') self.assertEqual(lot['title'], response.json['data']['title']) self.assertEqual(response.json['data']['status'], 'active.salable') response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') # switch lot to 'active.auction' self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}'.format(lot_id), {'data': { "status": 'active.auction' }}) self.assertEqual(response.status, '200 OK') # switch to 'active.contracting' self.app.authorization = ('Basic', ('convoy', '')) response = self.app.patch_json( '/{}'.format(lot_id), {'data': { "status": 'active.contracting' }}) self.assertEqual(response.status, '200 OK') # switch to 'pending.sold' with open('docs/source/tutorial/switch-lot-to-pending.sold.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}'.format(lot_id), {'data': { "status": 'pending.sold' }}) self.assertEqual(response.status, '200 OK') # switch to 'sold' with open('docs/source/tutorial/switch-lot-to-sold.http', 'w') as self.app.file_obj: self.app.authorization = ('Basic', ('concierge', '')) response = self.app.patch_json('/{}'.format(lot_id), {'data': { "status": 'sold' }}) self.assertEqual(response.status, '200 OK')
def check_status(request): lot = request.validated['lot'] now = get_now() check_lot_status(request, lot, now)
# -*- coding: utf-8 -*- import unittest import mock from datetime import timedelta from openregistry.lots.core.utils import get_now, error_handler from openregistry.lots.core.models import Lot from openregistry.lots.core.validation import ( validate_post_lot_role, validate_lot_document_update_not_by_author_or_lot_owner, validate_update_item_in_not_allowed_status, validate_lot_data, validate_patch_lot_data) from openregistry.lots.core.tests.base import DummyException now = get_now() class TestValidatePostLotRole(unittest.TestCase): def setUp(self): self.mocked_request = mock.MagicMock() self.mocked_request.errors = mock.MagicMock() self.mocked_request.errors.add = mock.MagicMock() self.mocked_handler = mock.MagicMock() self.mocked_handler.side_effect = [DummyException, DummyException] def test_concierge_post(self): self.mocked_request.authenticated_role = 'concierge' with self.assertRaises(DummyException): validate_post_lot_role(self.mocked_request, self.mocked_handler)
def tender_init_handler(event): """ initialization handler for basic lots """ event.lot.date = get_now()
# -*- coding: utf-8 -*- from copy import deepcopy from datetime import timedelta from openregistry.lots.core.utils import get_now from openregistry.lots.core.tests.blanks.json_data import ( test_document_data, test_item_data, test_organization ) now = get_now() test_loki_document_data = deepcopy(test_document_data) test_loki_document_data['documentOf'] = 'lot' auction_common = { 'auctionPeriod': { 'startDate': (now + timedelta(days=5)).isoformat(), 'endDate': (now + timedelta(days=10)).isoformat() }, 'value': { 'amount': 3000, 'currency': 'UAH', 'valueAddedTaxIncluded': True }, 'minimalStep': { 'amount': 300, 'currency': 'UAH', 'valueAddedTaxIncluded': True }, 'guarantee': {
def test_docs_tutorial(self): request_path = '/?opt_pretty=1' self.initial_data['decisions'] = [ { 'decisionDate': get_now().isoformat(), 'decisionID': 'initialDecisionID' } ] # Exploring basic rules # with open('docs/source/tutorial/lot-listing.http', 'w') as self.app.file_obj: response = self.app.get(request_path) self.assertEqual(response.status, '200 OK') self.app.file_obj.write("\n") with open('docs/source/tutorial/lot-post-attempt.http', 'w') as self.app.file_obj: response = self.app.post(request_path, 'data', status=415) self.assertEqual(response.status, '415 Unsupported Media Type') with open('docs/source/tutorial/lot-post-attempt-json.http', 'w') as self.app.file_obj: response = self.app.post( request_path, 'data', content_type='application/json', status=422) self.assertEqual(response.status, '422 Unprocessable Entity') # Creating lot in draft status with relatedProcesses # data_with_rPs = deepcopy(self.initial_data) data_with_rPs['relatedProcesses'] = [ { 'relatedProcessID': uuid4().hex, 'type': 'asset' } ] with open('docs/source/tutorial/lot-post-with-rPs.http', 'w') as self.app.file_obj: response = self.app.post_json(request_path, {"data": data_with_rPs}) self.assertEqual(response.status, '201 Created') # Creating lot in draft status # with open('docs/source/tutorial/lot-post-2pc.http', 'w') as self.app.file_obj: response = self.app.post_json(request_path, {"data": self.initial_data}) self.assertEqual(response.status, '201 Created') lot = response.json['data'] lot_id = response.json['data']['id'] owner_token = response.json['access']['token'] with open('docs/source/tutorial/blank-lot-view.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') response = self.app.get('/{}/auctions'.format(lot_id)) auctions = sorted(response.json['data'], key=lambda a: a['tenderAttempts']) english = auctions[0] second_english = auctions[1] access_header = {'X-Access-Token': str(owner_token)} # Switch to 'composing' # with open('docs/source/tutorial/lot-to-composing.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'composing'}}) self.assertEqual(response.status, '200 OK') # Compose lot with first english data # with open('docs/source/tutorial/compose_lot_patch_1.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}/auctions/{}'.format(lot_id, english['id']), params={'data': auction_english_data}, headers=access_header) self.assertEqual(response.status, '200 OK') # Compose lot with second english data # with open('docs/source/tutorial/compose_lot_patch_2.http', 'w') as self.app.file_obj: response = self.app.patch_json( '/{}/auctions/{}'.format(lot_id, second_english['id']), params={'data': auction_second_english_data}, headers=access_header) self.assertEqual(response.status, '200 OK') # Add relatedProcess to lot # related_process = { 'relatedProcessID': uuid4().hex, 'type': 'asset' } with open('docs/source/tutorial/add_related_process_1.http', 'w') as self.app.file_obj: response = self.app.post_json( '/{}/related_processes'.format(lot_id), params={'data': related_process}, headers=access_header) self.assertEqual(response.status, '201 Created') # Switch to 'verification' # with open('docs/source/tutorial/lot-to-varification.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'verification'}}) self.assertEqual(response.status, '200 OK') # Hack for update_after # self.app.get(request_path) # with open('docs/source/tutorial/initial-lot-listing.http', 'w') as self.app.file_obj: response = self.app.get(request_path) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/create-second-lot.http', 'w') as self.app.file_obj: response = self.app.post_json(request_path, {"data": self.initial_data}) self.assertEqual(response.status, '201 Created') second_lot_id = response.json['data']['id'] second_owner_token = response.json['access']['token'] response = self.app.get('/{}/auctions'.format(second_lot_id)) auctions = sorted(response.json['data'], key=lambda a: a['tenderAttempts']) english = auctions[0] second_english = auctions[1] second_access_header = {'X-Access-Token': str(second_owner_token)} # Switch to 'composing' # with open('docs/source/tutorial/second-lot-to-composing.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}?acc_token={}'.format(second_lot_id, second_owner_token), {'data': {"status": 'composing'}}) self.assertEqual(response.status, '200 OK') # Hack for update_after # self.app.get(request_path) # with open('docs/source/tutorial/listing-with-some-lots.http', 'w') as self.app.file_obj: response = self.app.get(request_path) self.assertEqual(response.status, '200 OK') # Modifying lot # with open('docs/source/tutorial/patch-lot.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}?acc_token={}'.format(second_lot_id, second_owner_token), {'data': { "description": "Lot description modified" } }) self.assertEqual(response.status, '200 OK') self.app.get(request_path) with open('docs/source/tutorial/lot-listing-after-patch.http', 'w') as self.app.file_obj: response = self.app.get(request_path) self.assertEqual(response.status, '200 OK') # Posting decisions to the first lot to be able to switch to pending self.app.authorization = ('Basic', ('concierge', '')) add_decisions(self, lot) # Switch first lot to 'pending' # asset_items = [test_loki_item_data] lot = self.app.get('/{}'.format(lot_id)).json['data'] related_process_id = lot['relatedProcesses'][0]['id'] response = self.app.patch_json('/{}/related_processes/{}'.format(lot_id, related_process_id), {'data': {'identifier': 'UA-AR-P-2018-08-17-000002-1'}}) self.assertEqual(response.status, '200 OK') concierge_patch = { 'status': 'pending', 'items': asset_items, 'title': 'Нежитлове приміщення', 'description': 'Нежитлове приміщення для збереження насіння', 'lotHolder': {'name': 'Власник лоту', 'identifier': {'scheme': 'AE-ADCD', 'id': '11111-4'}}, 'lotCustodian': { 'name': 'Зберігач лоту', 'address': {'countryName': 'Україна'}, 'identifier': {'scheme': 'AE-ADCD', 'id': '11111-4'}, 'contactPoint': {'name': 'Сергій', 'email': '*****@*****.**'} }, 'decisions': [ lot['decisions'][0], {'decisionID': '11111-4-5', 'relatedItem': uuid4().hex, 'decisionOf': 'asset'} ] } response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': concierge_patch}) self.assertEqual(response.status, '200 OK') with open('docs/source/tutorial/lot-after-concierge-patch-pending-1.http', 'w') as self.app.file_obj: response = self.app.get('/{}'.format(lot_id)) self.assertEqual(response.status, '200 OK') # Switch first lot to 'pending.deleted' # self.app.authorization = ('Basic', ('broker', '')) access_header = {'X-Access-Token': str(owner_token)} with open('docs/source/tutorial/add_cancellation_docs.hhtp', 'w') as self.app.file_obj: add_cancellationDetails_document(self, lot, access_header) with open('docs/source/tutorial/lot-delete-2pc.http', 'w') as self.app.file_obj: response = self.app.patch_json('/{}?acc_token={}'.format(lot_id, owner_token), {'data': {"status": 'pending.deleted'}}) self.assertEqual(response.status, '200 OK') self.app.authorization = ('Basic', ('broker', ''))
def rectificationPeriod_document_workflow(self): rectificationPeriod = Period() rectificationPeriod.startDate = get_now() - timedelta(3) rectificationPeriod.endDate = calculate_business_date( rectificationPeriod.startDate, timedelta(1), None) lot = self.create_resource() response = self.app.get('/{}/auctions'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') auction_id = response.json["data"][0]['id'] response = self.app.post_json('/{}/auctions/{}/documents'.format( lot['id'], auction_id), headers=self.access_header, params={'data': self.initial_document_data}) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) # Change rectification period in db fromdb = self.db.get(lot['id']) fromdb = Lot(fromdb) fromdb.status = 'pending' fromdb.rectificationPeriod = rectificationPeriod fromdb = fromdb.store(self.db) self.assertEqual(fromdb.id, lot['id']) response = self.app.get('/{}'.format(lot['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['id'], lot['id']) response = self.app.post_json('/{}/auctions/{}/documents'.format( lot['id'], auction_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]['description'], 'You can\'t add documents to auction after rectification period') response = self.app.patch_json('/{}/auctions/{}/documents/{}'.format( lot['id'], auction_id, doc_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change documents after rectification period') response = self.app.put_json('/{}/auctions/{}/documents/{}'.format( lot['id'], auction_id, doc_id), headers=self.access_header, params={'data': self.initial_document_data}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]['description'], 'You can\'t change documents after rectification period')