import uuid from fastapi import Depends, HTTPException, File, UploadFile import shutil from ..core.routes import get_crud_router from .routes_draft import draft_router from .print import print_router from .models import Contract, ContractDraft, ContractDraftStatus, Party, replace_variables_in_value from .schemas import ContractCreate, ContractRead, ContractUpdate, SignatureRead from ..entity.models import Entity from ..template.models import ProvisionTemplate from ..user.manager import get_current_user, get_current_superuser contract_router = get_crud_router(Contract, ContractCreate, ContractRead, ContractUpdate) del(contract_router.routes[0]) del(contract_router.routes[2]) del(contract_router.routes[2]) contract_router.include_router(draft_router, prefix="/draft", ) contract_router.include_router(print_router, prefix="/print", ) @contract_router.post("/", response_description="Contract Successfully created") async def create(item: ContractCreate, user=Depends(get_current_user)) -> dict: await item.validate_foreign_key() draft = await ContractDraft.get(item.draft_id) for v in draft.variables: if not v.key or not v.value: raise HTTPException(status_code=400, detail="Variable {} is invalid".format(v)) contract_dict = item.dict() del(contract_dict['draft_id']) contract_dict['lawyer'] = await Entity.get(user.entity_id) contract_dict['name'] = draft.name contract_dict['title'] = draft.title parties = [] for p in draft.parties: parties.append({ 'entity': await Entity.get(p.entity_id), 'part': p.part, 'representative': await Entity.get(p.representative_id) if p.representative_id else None, 'signature_uuid': str(uuid.uuid4()) }) contract_dict['parties'] = parties provisions = [] for p in draft.provisions: p = p.provision provision = await ProvisionTemplate.get(p.provision_template_id) if p.type == 'template' \ else p provisions.append({ 'title': replace_variables_in_value(draft.variables, provision.title), 'body': replace_variables_in_value(draft.variables, provision.body) }) contract_dict['provisions'] = provisions o = await Contract(**contract_dict).create() await draft.update({"$set": {"status": ContractDraftStatus.published}}) return {"message": "Contract Successfully created", "id": o.id} @contract_router.put("/{id}", response_description="") async def update(id: str, contract_form: ContractUpdate, user=Depends(get_current_superuser)) -> ContractRead: raise HTTPException(status_code=400, detail="No modification on contract") @contract_router.get("/signature/{signature_id}", response_description="") async def get_signature(signature_id: str) -> SignatureRead: contract = await Contract.find_by_signature_id(signature_id) signature = contract.get_signature(signature_id) signature_dict = signature.dict() signature_dict['contract_label'] = contract.label return signature_dict @contract_router.post("/signature/{signature_id}", response_description="") async def affix_signature(signature_id: str, signature_file: UploadFile = File(...)) -> bool: contract = await Contract.find_by_signature_id(signature_id) signature_index = contract.get_signature_index(signature_id) signature = contract.parties[signature_index] if signature.signature_affixed: raise HTTPException(status_code=400, detail="Signature already affixed") with open(f'media/signatures/{signature_id}.png', "wb") as buffer: shutil.copyfileobj(signature_file.file, buffer) update_query = {"$set": { f'parties.{signature_index}.signature_affixed': True }} signature.signature_affixed = True if contract.is_signed(): update_query["$set"]['status'] = 'signed' await contract.update(update_query) return True