Skip to content

Commit

Permalink
Merge branch 'a147460966605399_set_date_on_status'
Browse files Browse the repository at this point in the history
  • Loading branch information
ktarasz committed Jul 8, 2016
2 parents a041edc + 606bf8f commit b3b1c7d
Show file tree
Hide file tree
Showing 13 changed files with 48 additions and 12 deletions.
15 changes: 11 additions & 4 deletions src/openprocurement/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -809,8 +809,8 @@ def validate_relatedLot(self, data, relatedLot):
class Contract(Model):
class Options:
roles = {
'create': blacklist('id', 'status', 'documents', 'dateSigned'),
'edit': blacklist('id', 'documents', 'awardID', 'suppliers', 'items', 'contractID'),
'create': blacklist('id', 'status', 'date', 'documents', 'dateSigned'),
'edit': blacklist('id', 'documents', 'date', 'awardID', 'suppliers', 'items', 'contractID'),
'embedded': schematics_embedded_role,
'view': schematics_default_role,
}
Expand Down Expand Up @@ -952,6 +952,7 @@ class Options:
description = StringType()
description_en = StringType()
description_ru = StringType()
date = IsoDateTimeType()
value = ModelType(Value, required=True)
minimalStep = ModelType(Value, required=True)
auctionPeriod = ModelType(LotAuctionPeriod, default={})
Expand Down Expand Up @@ -1021,9 +1022,9 @@ def validate_cpv_group(items, *args):


plain_role = (blacklist('_attachments', 'revisions', 'dateModified') + schematics_embedded_role)
create_role = (blacklist('owner_token', 'owner', '_attachments', 'revisions', 'dateModified', 'doc_id', 'tenderID', 'bids', 'documents', 'awards', 'questions', 'complaints', 'auctionUrl', 'status', 'auctionPeriod', 'awardPeriod', 'procurementMethod', 'awardCriteria', 'submissionMethod', 'cancellations') + schematics_embedded_role)
create_role = (blacklist('owner_token', 'owner', '_attachments', 'revisions', 'date', 'dateModified', 'doc_id', 'tenderID', 'bids', 'documents', 'awards', 'questions', 'complaints', 'auctionUrl', 'status', 'auctionPeriod', 'awardPeriod', 'procurementMethod', 'awardCriteria', 'submissionMethod', 'cancellations') + schematics_embedded_role)
draft_role = whitelist('status')
edit_role = (blacklist('status', 'procurementMethodType', 'lots', 'owner_token', 'owner', '_attachments', 'revisions', 'dateModified', 'doc_id', 'tenderID', 'bids', 'documents', 'awards', 'questions', 'complaints', 'auctionUrl', 'auctionPeriod', 'awardPeriod', 'procurementMethod', 'awardCriteria', 'submissionMethod', 'mode', 'cancellations') + schematics_embedded_role)
edit_role = (blacklist('status', 'procurementMethodType', 'lots', 'owner_token', 'owner', '_attachments', 'revisions', 'date', 'dateModified', 'doc_id', 'tenderID', 'bids', 'documents', 'awards', 'questions', 'complaints', 'auctionUrl', 'auctionPeriod', 'awardPeriod', 'procurementMethod', 'awardCriteria', 'submissionMethod', 'mode', 'cancellations') + schematics_embedded_role)
view_role = (blacklist('owner_token', '_attachments', 'revisions') + schematics_embedded_role)
listing_role = whitelist('dateModified', 'doc_id')
auction_view_role = whitelist('tenderID', 'dateModified', 'bids', 'auctionPeriod', 'minimalStep', 'auctionUrl', 'features', 'lots')
Expand Down Expand Up @@ -1087,6 +1088,7 @@ def __local_roles__(self):
description = StringType()
description_en = StringType()
description_ru = StringType()
date = IsoDateTimeType()
tenderID = StringType() # TenderID should always be the same as the OCID. It is included to make the flattened data structure more convenient.
items = ListType(ModelType(Item), required=True, min_size=1, validators=[validate_cpv_group, validate_items_uniq]) # The goods and services to be purchased, broken into line items wherever possible. Items should not be duplicated, but a quantity of 2 specified instead.
value = ModelType(Value, required=True) # The total estimated value of the procurement.
Expand Down Expand Up @@ -1179,6 +1181,11 @@ def initialize(self):
self.enquiryPeriod.startDate = get_now()
if not self.tenderPeriod.startDate:
self.tenderPeriod.startDate = self.enquiryPeriod.endDate
now = get_now()
self.date = now
if self.lots:
for lot in self.lots:
lot.date = now

@serializable(serialize_when_none=False)
def next_check(self):
Expand Down
2 changes: 2 additions & 0 deletions src/openprocurement/api/tests/chronograph.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ def test_switch_to_tendering_by_enquiryPeriod_endDate(self):
self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})
self.assertEqual(response.status, '200 OK')
date_1 = response.json['data']['date']
self.assertNotEqual(response.json['data']["status"], "active.tendering")
self.set_status('active.tendering', {'status': 'active.enquiries', "tenderPeriod": {"startDate": None}})
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.json['data']["status"], "active.tendering")
self.assertNotEqual(date_1, response.json['data']['date'])

def test_switch_to_tendering_by_tenderPeriod_startDate(self):
self.set_status('active.tendering', {'status': 'active.enquiries', "tenderPeriod": {}})
Expand Down
4 changes: 4 additions & 0 deletions src/openprocurement/api/tests/complaint.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ def test_create_tender_complaint(self):
self.assertEqual(response.status, '201 Created')
self.assertEqual(response.content_type, 'application/json')
complaint = response.json['data']
status_date = response.json['data']['date']
owner_token = response.json['access']['token']
self.assertEqual(complaint['author']['name'], test_organization['name'])
self.assertIn('id', complaint)
Expand Down Expand Up @@ -144,6 +145,8 @@ def test_create_tender_complaint(self):
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.json['data']["status"], "answered")
self.assertNotEqual(response.json['data']['date'], status_date)
status_date = response.json['data']['date']
self.assertEqual(response.json['data']["resolutionType"], "invalid")
self.assertEqual(response.json['data']["resolution"], "spam 100% " * 3)

Expand All @@ -154,6 +157,7 @@ def test_create_tender_complaint(self):
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.json['data']["status"], "resolved")
self.assertNotEqual(response.json['data']['date'], status_date)

response = self.app.patch_json('/tenders/{}/complaints/{}?acc_token={}'.format(self.tender_id, complaint['id'], owner_token), {"data": {"status": "cancelled", "cancellationReason": "reason"}}, status=403)
self.assertEqual(response.status, '403 Forbidden')
Expand Down
4 changes: 2 additions & 2 deletions src/openprocurement/api/tests/lot.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ def test_get_tender_lot(self):
response = self.app.get('/tenders/{}/lots/{}'.format(self.tender_id, lot['id']))
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(set(response.json['data']), set([u'id', u'title', u'description', u'minimalStep', u'value', u'status']))
self.assertEqual(set(response.json['data']), set([u'id', u'date', u'title', u'description', u'minimalStep', u'value', u'status']))

self.set_status('active.qualification')

Expand Down Expand Up @@ -424,7 +424,7 @@ def test_get_tender_lots(self):
response = self.app.get('/tenders/{}/lots'.format(self.tender_id))
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(set(response.json['data'][0]), set([u'id', u'title', u'description', u'minimalStep', u'value', u'status']))
self.assertEqual(set(response.json['data'][0]), set([u'id', u'date', u'title', u'description', u'minimalStep', u'value', u'status']))

self.set_status('active.qualification')

Expand Down
4 changes: 2 additions & 2 deletions src/openprocurement/api/tests/tender.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ def test_create_tender_generated(self):
tender = response.json['data']
if 'procurementMethodDetails' in tender:
tender.pop('procurementMethodDetails')
self.assertEqual(set(tender), set([u'procurementMethodType', u'id', u'dateModified', u'tenderID', u'status', u'enquiryPeriod',
self.assertEqual(set(tender), set([u'procurementMethodType', u'id', u'date', u'dateModified', u'tenderID', u'status', u'enquiryPeriod',
u'tenderPeriod', u'minimalStep', u'items', u'value', u'procuringEntity', u'next_check',
u'procurementMethod', u'awardCriteria', u'submissionMethod', u'title', u'owner']))
self.assertNotEqual(data['id'], tender['id'])
Expand Down Expand Up @@ -610,7 +610,7 @@ def test_create_tender(self):
self.assertEqual(response.content_type, 'application/json')
tender = response.json['data']
self.assertEqual(set(tender) - set(test_tender_data), set(
[u'id', u'dateModified', u'tenderID', u'status', u'procurementMethod', u'awardCriteria', u'submissionMethod', u'next_check', u'owner']))
[u'id', u'dateModified', u'tenderID', u'date', u'status', u'procurementMethod', u'awardCriteria', u'submissionMethod', u'next_check', u'owner']))
self.assertIn(tender['id'], response.headers['Location'])

response = self.app.get('/tenders/{}'.format(tender['id']))
Expand Down
20 changes: 19 additions & 1 deletion src/openprocurement/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from functools import partial
from json import dumps
from jsonpatch import make_patch, apply_patch as _apply_patch
from jsonpointer import resolve_pointer
from logging import getLogger
from openprocurement.api.models import get_now, TZ, COMPLAINT_STAND_STILL_TIME, WORKING_DAYS
from openprocurement.api.traversal import factory
Expand Down Expand Up @@ -224,10 +225,25 @@ def save_tender(request):
set_modetest_titles(tender)
patch = get_revision_changes(tender.serialize("plain"), request.validated['tender_src'])
if patch:
now = get_now()
status_changes = [
p
for p in patch
if not p['path'].startswith('/bids/') and p['path'].endswith("/status") and p['op'] == "replace"
]
for change in status_changes:
obj = resolve_pointer(tender, change['path'].replace('/status', ''))
if obj and hasattr(obj, "date"):
date_path = change['path'].replace('/status', '/date')
if obj.date and not any([p for p in patch if date_path == p['path']]):
patch.append({"op": "replace", "path": date_path, "value": obj.date.isoformat()})
elif not obj.date:
patch.append({"op": "remove", "path": date_path})
obj.date = now
tender.revisions.append(type(tender).revisions.model_class({'author': request.authenticated_userid, 'changes': patch, 'rev': tender.rev}))
old_dateModified = tender.dateModified
if getattr(tender, 'modified', True):
tender.dateModified = get_now()
tender.dateModified = now
try:
tender.store(request.registry.db)
except ModelValidationError, e:
Expand Down Expand Up @@ -522,6 +538,7 @@ def add_next_award(request):
'lotID': lot.id,
'status': 'pending',
'value': bid['value'],
'date': get_now(),
'suppliers': bid['tenderers'],
'complaintPeriod': {
'startDate': now.isoformat()
Expand All @@ -547,6 +564,7 @@ def add_next_award(request):
award = type(tender).awards.model_class({
'bid_id': bid['id'],
'status': 'pending',
'date': get_now(),
'value': bid['value'],
'suppliers': bid['tenderers'],
'complaintPeriod': {
Expand Down
2 changes: 1 addition & 1 deletion src/openprocurement/api/views/award.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,13 @@ def patch(self):
return
award_status = award.status
apply_patch(self.request, save=False, src=self.request.context.serialize())
award.date = get_now()
if award_status == 'pending' and award.status == 'active':
award.complaintPeriod.endDate = calculate_business_date(get_now(), STAND_STILL_TIME, tender, True)
tender.contracts.append(type(tender).contracts.model_class({
'awardID': award.id,
'suppliers': award.suppliers,
'value': award.value,
'date': get_now(),
'items': [i for i in tender.items if i.relatedLot == award.lotID ],
'contractID': '{}-{}{}'.format(tender.tenderID, self.server_id, len(tender.contracts) + 1) }))
add_next_award(self.request)
Expand Down
1 change: 1 addition & 0 deletions src/openprocurement/api/views/award_complaint.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def collection_post(self):
self.request.errors.status = 403
return
complaint = self.request.validated['complaint']
complaint.date = get_now()
complaint.relatedLot = self.context.lotID
if complaint.status == 'claim':
complaint.dateSubmitted = get_now()
Expand Down
2 changes: 2 additions & 0 deletions src/openprocurement/api/views/cancellation.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
json_view,
context_unpack,
APIResource,
get_now
)
from openprocurement.api.validation import (
validate_cancellation_data,
Expand Down Expand Up @@ -56,6 +57,7 @@ def collection_post(self):
self.request.errors.status = 403
return
cancellation = self.request.validated['cancellation']
cancellation.date = get_now()
if any([i.status != 'active' for i in tender.lots if i.id == cancellation.relatedLot]):
self.request.errors.add('body', 'data', 'Can add cancellation only in active lot status')
self.request.errors.status = 403
Expand Down
1 change: 1 addition & 0 deletions src/openprocurement/api/views/complaint.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def collection_post(self):
self.request.errors.status = 403
return
complaint = self.request.validated['complaint']
complaint.date = get_now()
if complaint.status == 'claim':
complaint.dateSubmitted = get_now()
else:
Expand Down
1 change: 0 additions & 1 deletion src/openprocurement/api/views/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ def patch(self):
return
contract_status = self.request.context.status
apply_patch(self.request, save=False, src=self.request.context.serialize())
self.request.context.date = get_now()
if contract_status != self.request.context.status and (contract_status != 'pending' or self.request.context.status != 'active'):
self.request.errors.add('body', 'data', 'Can\'t update contract status')
self.request.errors.status = 403
Expand Down
2 changes: 2 additions & 0 deletions src/openprocurement/api/views/lot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
json_view,
context_unpack,
APIResource,
get_now
)
from openprocurement.api.validation import (
validate_lot_data,
Expand All @@ -30,6 +31,7 @@ def collection_post(self):
self.request.errors.status = 403
return
lot = self.request.validated['lot']
lot.date = get_now()
tender.lots.append(lot)
if save_tender(self.request):
self.LOGGER.info('Created tender lot {}'.format(lot.id),
Expand Down
2 changes: 1 addition & 1 deletion versions.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ iso8601 = 0.1.11

# Required by:
# openprocurement.api==0.8.1
jsonpatch = 1.13-jsondiff.0
jsonpatch = 1.9op1

# Required by:
# openprocurement.api==0.8.1
Expand Down

0 comments on commit b3b1c7d

Please sign in to comment.