Contract Drafts modules

This commit is contained in:
2023-02-11 18:07:50 +01:00
parent cb3af5bcf2
commit a288d32ec9
10 changed files with 187 additions and 44 deletions

View File

@@ -1,16 +1,9 @@
from datetime import datetime from typing import List, Literal
from typing import List
from enum import Enum from enum import Enum
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from beanie import Document
from ..entity.models import Entity from ..core.models import CrudDocument, RichtextSingleline, RichtextMultiline, DictionaryEntry
class ContractType(str, Enum):
employment = 'employment'
location = 'location'
class ContractStatus(str, Enum): class ContractStatus(str, Enum):
@@ -20,21 +13,54 @@ class ContractStatus(str, Enum):
executed = 'executed' executed = 'executed'
class ContractDraftStatus(str, Enum):
draft = 'draft'
created = 'created'
class Party(BaseModel): class Party(BaseModel):
entity: Entity entity_id: str = Field(
foreignKey={
"reference": {
"resource": "entity",
"schema": "Entity",
}
}
)
part: str part: str
class Clause(BaseModel): class ProvisionGenuine(BaseModel):
type: Literal['genuine'] = 'genuine'
title: str = RichtextSingleline(props={"parametrized": True})
body: str = RichtextMultiline(props={"parametrized": True})
class ContractProvisionTemplateReference(BaseModel):
type: Literal['template'] = 'template'
provision_template_id: str = Field(
foreignKey={
"reference": {
"resource": "template/provision",
"schema": "ProvisionTemplate",
"displayedFields": ['title', 'body']
},
},
props={"parametrized": True}
)
class DraftProvision(BaseModel):
provision: ContractProvisionTemplateReference | ProvisionGenuine = Field(..., discriminator='type')
class ContractDraft(CrudDocument):
name: str name: str
body: str title: str
class Contract(Document):
_id: str
type: ContractType
parties: List[Party] parties: List[Party]
clauses: List[Clause] provisions: List[DraftProvision]
status: ContractStatus = Field(default=ContractStatus.new) variables: List[DictionaryEntry] = Field(
created_at: datetime = Field(default=datetime.utcnow(), nullable=False) default=[],
updated_at: datetime = Field(default_factory=datetime.utcnow, nullable=False) format="dictionary",
)
status: ContractDraftStatus = Field(default=ContractDraftStatus.draft)

View File

@@ -1,5 +1,5 @@
from ..core.routes import get_crud_router from ..core.routes import get_crud_router
from .models import Contract from .models import ContractDraft
from .schemas import ContractCreate, ContractRead, ContractUpdate from .schemas import ContractDraftCreate, ContractDraftRead, ContractDraftUpdate
router = get_crud_router(Contract, ContractCreate, ContractRead, ContractUpdate) router = get_crud_router(ContractDraft, ContractDraftCreate, ContractDraftRead, ContractDraftUpdate)

View File

@@ -1,36 +1,36 @@
import uuid
from datetime import datetime
from typing import List from typing import List
from pydantic import BaseModel, validator from pydantic import Field
from beanie import PydanticObjectId from .models import ContractDraft, DraftProvision, Party
from .models import Contract, ContractType, Clause
from ..entity.models import Entity from ..entity.models import Entity
from ..core.schemas import Writer from ..core.schemas import Writer
from ..core.models import DictionaryEntry
class ContractRead(Contract): class ContractDraftRead(ContractDraft):
pass pass
class PartyCreate(BaseModel): class ContractDraftCreate(Writer):
entity: PydanticObjectId name: str
part: str title: str
parties: List[Party]
provisions: List[DraftProvision]
class ContractCreate(Writer): variables: List[DictionaryEntry] = Field(
type: ContractType default=[],
parties: List[PartyCreate] format="dictionary",
clauses: List[Clause] )
async def validate_foreign_key(self): async def validate_foreign_key(self):
return
for p in self.parties: for p in self.parties:
p.entity = await Entity.get(p.entity) p.entity = await Entity.get(p.entity)
if p.entity is None: if p.entity is None:
raise ValueError raise ValueError
class ContractUpdate(BaseModel): class ContractDraftUpdate(ContractDraftCreate):
status: str pass

View File

@@ -6,7 +6,7 @@ from .user import User, AccessToken
from .entity.models import Entity from .entity.models import Entity
from .template.models import ContractTemplate, ProvisionTemplate from .template.models import ContractTemplate, ProvisionTemplate
from .order.models import Order from .order.models import Order
from .contract.models import Contract from .contract.models import ContractDraft
DATABASE_URL = "mongodb://root:example@mongo:27017/" DATABASE_URL = "mongodb://root:example@mongo:27017/"
@@ -17,5 +17,5 @@ async def init_db():
) )
await init_beanie(database=client.db_name, await init_beanie(database=client.db_name,
document_models=[User, AccessToken, Entity, ContractTemplate, ProvisionTemplate, Order, Contract, ], document_models=[User, AccessToken, Entity, ContractTemplate, ProvisionTemplate, ContractDraft, ],
allow_index_dropping=True) allow_index_dropping=True)

View File

@@ -25,7 +25,7 @@ app.include_router(user_router, prefix="/users", tags=["users"], )
app.include_router(entity_router, prefix="/entity", tags=["entity"], ) app.include_router(entity_router, prefix="/entity", tags=["entity"], )
app.include_router(order_router, prefix="/order", tags=["order"], ) app.include_router(order_router, prefix="/order", tags=["order"], )
app.include_router(template_router, prefix="/template", tags=["template"], ) app.include_router(template_router, prefix="/template", tags=["template"], )
app.include_router(contract_router, prefix="/contract", tags=["contract"], ) app.include_router(contract_router, prefix="/contract-draft", tags=["contract-draft"], )
if __name__ == '__main__': if __name__ == '__main__':
import uvicorn import uvicorn

View File

@@ -1,5 +1,6 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import {ContractsModule} from "./views/contracts/contracts.module";
const routes: Routes = [ const routes: Routes = [
{ {
@@ -29,6 +30,11 @@ const routes: Routes = [
loadChildren: () => loadChildren: () =>
import('./views/templates/templates.module').then((m) => m.TemplatesModule) import('./views/templates/templates.module').then((m) => m.TemplatesModule)
}, },
{
path: 'contract-drafts',
loadChildren: () =>
import('./views/contracts/contracts.module').then((m) => m.ContractsModule)
},
] ]
} }
]; ];

View File

@@ -31,6 +31,11 @@ export class SidenavComponent {
link: "/templates/contracts", link: "/templates/contracts",
icon: IconNamesEnum.FileCodeFill icon: IconNamesEnum.FileCodeFill
}, },
{
title: "Contracts Drafts",
link: "/contract-drafts",
icon: IconNamesEnum.PencilSquare
},
] ]
} }

View File

@@ -0,0 +1,44 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { DraftCardComponent, DraftListComponent, DraftNewComponent } from "./drafts.component";
const routes: Routes = [
{
path: '',
data: {
title: 'Entities',
},
children: [
{ path: '', redirectTo: 'list', pathMatch: 'full' },
{
path: 'list',
component: DraftListComponent,
data: {
title: 'List',
},
},
{
path: 'new',
component: DraftNewComponent,
data: {
title: 'New',
},
},
{
path: ':id',
component: DraftCardComponent,
data: {
title: 'Card',
},
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ContractsRoutingModule {}

View File

@@ -0,0 +1,23 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ContractsRoutingModule } from './contracts-routing.module';
import { CrudModule } from '@common/crud/crud.module'
import { DraftCardComponent, DraftListComponent, DraftNewComponent } from "./drafts.component";
@NgModule({
imports: [
CommonModule,
CrudModule,
ContractsRoutingModule
],
declarations: [
DraftListComponent,
DraftNewComponent,
DraftCardComponent,
]
})
export class ContractsModule {
}

View File

@@ -0,0 +1,39 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
export class BaseEntitiesComponent {
protected resource: string = "contract-draft";
protected schema: string = "ContractDraft";
}
@Component({
template: '<crud-list [resource]="this.resource" [schema]="this.schema" [columns]="this.columns"></crud-list>'
})
export class DraftListComponent extends BaseEntitiesComponent {
columns = ['label', 'address', 'entity_data.type']
}
@Component({
template: '<crud-card [resource]="this.resource" [schema]="this.schema"></crud-card>'
})
export class DraftNewComponent extends BaseEntitiesComponent {
}
@Component({
template: '<crud-card [resource]="this.resource" [resource_id]="this.resource_id" [schema]="this.schema"></crud-card>'
})
export class DraftCardComponent extends BaseEntitiesComponent implements OnInit {
resource_id: string | null = null;
constructor(private route: ActivatedRoute,) {
super();
}
ngOnInit(): void {
this.route.paramMap.subscribe((params: ParamMap) => {
this.resource_id = params.get('id')
})
}
}