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')
Ejemplo n.º 5
0
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']
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
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'
    )
Ejemplo n.º 9
0
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')
Ejemplo n.º 10
0
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')
Ejemplo n.º 12
0
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
Ejemplo n.º 14
0
    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))
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
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'])
Ejemplo n.º 17
0
 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)
Ejemplo n.º 20
0
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')
Ejemplo n.º 22
0
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')
Ejemplo n.º 24
0
    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')
Ejemplo n.º 25
0
def check_status(request):
    lot = request.validated['lot']
    now = get_now()
    check_lot_status(request, lot, now)
Ejemplo n.º 26
0
# -*- 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)
Ejemplo n.º 27
0
def tender_init_handler(event):
    """ initialization handler for basic lots """
    event.lot.date = get_now()
Ejemplo n.º 28
0
# -*- 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')