Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contract local role contract_supplier for signing #7

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

VDigitall
Copy link
Member

@VDigitall VDigitall commented Mar 17, 2020

Концепція підписання договору між замовником та постачальником-переможцем аукціону

Процес підписання

Процес підписання договору між замовником (tender owner) та постачальником (supplier відбувається у об’єкті Contract у статусі pending.

Workflow:

  1. Перевірка, чи Contract у статусі pending
  2. Визначення постачальника. Перевірка, чи його Bid та Award у статусі active
  3. Зміна замовником статусу контракту до pending.winner-signing .
  4. Завантаження постачальником документів та ЄЦП (підписання контракту);
  5. Зміна постачальником статусу до pending;
  6. Завантаження замовником документів та ЄЦП (підписання контракту);
  7. Зміна замовником статусу контракту до active.

Підсумок:

Для створення процесу підписання та унеможливлення підписання контракту кимось іншим, окрім замовника та постачальника, внесли наступні зміни:

  • використали існуючу роль tender_owner та ввели нову - contract_supplier;
  • ввели поняття локальні ролі у Contract ( __local_roles__), додали туди contract_supplier
  • Роль edit розділили на моделі Contract на три:
    • edit_admins;
    • edit_contract_supplier;
    • edit_tender_owner.
  • надали дозволи (permissions) для tender_owner i contract_supplier, і вони однакові :
    • upload_contract_documents ;
    • edit_contract.
  • створили статус pending.winner-signing та валідації до нього:
    • validate_role_for_contract_document_operation,
    • validate_update_contract_status_by_supplier,
    • validate_contract_document (існуюча, змінена).

Зміни:

Модель Contract:

Для індентифікації постачальника необхідно знайти пропозицію (Bid), чий власник виграв аукціон. При тому і Bid, і Award повинні бути у статусі active.

Цим керуючись, в core утилітах додали функцію get_contract_supplier_roles - присвоювання локальної ролі contract_supplier власнику Bid:

Окільки намає змоги видати постачальнику токен для контракту напряму, ми використали токен його виграшної пропозиції (Bid).

def get_contract_supplier_roles(contract):
roles = {}
if 'bids' not in contract.__parent__:
return roles
bid_id = jmespath.search("awards[?id=='{}'].bid_id".format(contract.awardID), contract.__parent__)[0]
tokens = jmespath.search("bids[?id=='{}'].[owner,owner_token]".format(bid_id), contract.__parent__)
if tokens:
for item in tokens:
roles['_'.join(item)] = 'contract_supplier'
return roles

У самій моделі Contract перевизначили __local_roles__ ролями постачальника:

def __local_roles__(self):
roles = {}
roles.update(get_contract_supplier_roles(self))
return roles

Тут і змінили метод get_role, що повертає відповідну роль edit для замовника та постачальника:

def get_role(self):
root = self.get_root()
request = root.request
if request.authenticated_role in ("tender_owner", "contract_supplier"):
role = "edit_{}".format(request.authenticated_role)
else:
role = request.authenticated_role
return role

Зміни внесли для всіх типів Contract та Tender:

Зміни у класі Options, для closeFrameworkAgreementSelectionUA - сontract.csv файлі.

"admins": blacklist("id", "documents", "date", "awardID", "suppliers", "items", "contractID"),
"edit_tender_owner": blacklist("id", "documents", "date", "awardID", "suppliers", "items", "contractID"),
"edit_contract_supplier": whitelist("status"),

Модель Tender:

У core утиліти додали функцію get_contract_supplier_permissions - визначенні дозволів постачальників contract_supplier_permissions (керується принципом роботи, описаним над get_contract_supplier_roles). Надали постачальнику дозволи upload_contract_documents та edit_contract.

def get_contract_supplier_permissions(tender):
"""
Set `upload_contract_document` permissions for award in `active` status owners
"""
suppliers_permissions = []
if tender.get('bids', []) and tender.get('awards', []):
win_bids = jmespath.search("awards[?status=='active'].bid_id", tender._data) or []
for bid in tender.bids:
if bid.status == "active" and bid.id in win_bids:
suppliers_permissions.append(
(Allow, "{}_{}".format(bid.owner, bid.owner_token), "upload_contract_documents")
)
suppliers_permissions.append((Allow, "{}_{}".format(bid.owner, bid.owner_token), "edit_contract"))
return suppliers_permissions

У моделі Tender перевизначили список контролю-доступу новими ролями та дозволами постачальника, аналогічні ( upload_contract_documents та edit_contract) дали і замовнику.

def __acl__(self):
acl = [(Allow, "{}_{}".format(i.owner, i.owner_token), "create_award_complaint") for i in self.bids]
suppliers_permissions = get_contract_supplier_permissions(self)
if suppliers_permissions:
acl.extend(suppliers_permissions)
acl.extend(
[
(Allow, "{}_{}".format(self.owner, self.owner_token), "edit_complaint"),
(Allow, "{}_{}".format(self.owner, self.owner_token), "edit_contract"),
(Allow, "{}_{}".format(self.owner, self.owner_token), "upload_contract_documents"),
]
)
self._acl_cancellation_complaint(acl)
return acl

Статус pending.winner-signing:

Створили статус pending.winner-signing:

  • замовник може перемкнути на цей статус;
  • під час цього статусу постачальник-переможець матиме можливість завантажити документи та підписати контракт.
    status = StringType(choices=["pending", "pending.winner-signing", "terminated", "active", "cancelled"], default="pending")

Перевизначили можливість оновити всі типи контрактів (PATCH) у всіх типах моделі Tender з permission="edit_contract" у статусі pending.winner-signing:

if contract_status != self.request.context.status and \
(contract_status not in ("pending", "pending.winner-signing",) or \
self.request.context.status not in ("active", "pending", "pending.winner-signing",)):
raise_operation_error(self.request, "Can't update contract status")
if self.request.context.status == "active" and not self.request.context.dateSigned:

Створили валідації статусу:

def validate_update_contract_status_by_supplier(request):
if request.authenticated_role == "contract_supplier":
data = request.validated["data"]
if "status" in data and data["status"] != "pending" or request.context.status != "pending.winner-signing":
raise_operation_error(request, "Supplier can change status to `pending`")

def validate_role_for_contract_document_operation(request):
if request.authenticated_role not in ("tender_owner", "contract_supplier",):
raise_operation_error(request, "Can {} document only buyer or supplier".format(OPERATIONS.get(request.method)))
if request.authenticated_role == "contract_supplier" and \
request.validated["contract"].status != "pending.winner-signing":
raise_operation_error(
request, "Supplier can't {} document in current contract status".format(OPERATIONS.get(request.method))
)
if request.authenticated_role == "tender_owner" and \
request.validated["contract"].status == "pending.winner-signing":
raise_operation_error(
request, "Tender onwer can't {} document in current contract status".format(OPERATIONS.get(request.method))
)

@VDigitall VDigitall changed the title Feature/local role contract supplier Contract local role contract_supplier for signing Mar 17, 2020
@VDigitall VDigitall mentioned this pull request Mar 17, 2020
@VDigitall VDigitall force-pushed the feature/local-role-contract_supplier branch from 6ec4a5e to 0fba980 Compare March 17, 2020 17:57
@VDigitall VDigitall force-pushed the feature/local-role-contract_supplier branch 3 times, most recently from d8c12a8 to 4fe6ee9 Compare March 20, 2020 07:24
@VDigitall VDigitall force-pushed the feature/local-role-contract_supplier branch 2 times, most recently from a80f6c9 to 7b002d6 Compare April 14, 2020 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant