Contracts
Overview
The Contracts module in ALP (Australian Legal Practice) provides comprehensive contract management capabilities, including creation, tracking, digital signing, and lifecycle management of legal contracts.
Features
Contract Management
- Create and manage contracts
- Track contract status and lifecycle
- Link contracts to matters, clients, or projects
- Digital signature integration with DocuSeal
- Document management and version control
Contract Statuses
- Draft: Initial contract creation stage
- Only contracts in Draft status can be deleted
- Can be submitted for digital signing
- Contract Design: Contract is in design phase and being prepared
- Waiting For Client Signature: Contract has been submitted for client signature
- Signed: Contract has been signed by all parties
- For digital contracts, Signed status can only be changed to Expired
- For non-digital contracts, can be changed to any status
- Declined: Contract has been declined by one or more parties
- Expired: Contract has reached its end date or manually marked as expired
- For digital contracts, this is the only available status after Signed
- Cannot be Terminated or Archived
Digital Signing Process
Contract Creation and Design
- Create contract in Draft status
- Prepare contract documents and content
- Move to Contract Design status when ready
Submission Process
- Submit contract for signing from Contract Design status
- Status changes to Waiting For Client Signature
- Add signing parties with contact details
- Track signing progress
Signing Status Flow
- When all parties sign: Status changes to Signed
- If any party declines: Status changes to Declined
- For digital contracts:
- Once Signed, can only be changed to Expired
- Cannot be Terminated or Archived
- For non-digital contracts:
- Can be changed to any status
Contract Completion
- Digital contracts: Can only be marked as Expired after Signed
- Non-digital contracts: Can be updated to any status based on business needs
User Interface
Contract List View
- View all contracts with filtering and search
- Sort by status, date, or contract type
- Quick access to contract actions
- Bulk status updates
Contract Detail View
Basic Information
- Contract name and description
- Contract type and status
- Start and end dates
- Contract amount and currency
- Related entity (Matter/Client/Project) information
Documents Section
- Upload and manage contract documents
- View document history
- Download documents
- Submit documents for signing
Digital Signature Section
- Create signature templates
- View signing submissions
- Track signing progress
- Access signed documents
Permissions
Contract View (ContractView)
- View contract details
- Access contract documents
- View signing status
Contract Create (ContractCreate)
- Create new contracts
- Import contracts
- Create from templates
Contract Edit (ContractEdit)
- Update contract details
- Change contract status
- Add/remove documents
- Submit for signing
- Manage contract parties
Contract Delete (ContractDelete)
- Delete contracts (Draft status only)
Contract Types
- Service Agreement
- Employment Contract
- Non-Disclosure Agreement
- Partnership Agreement
- License Agreement
- And more...
Best Practices
Contract Creation
- Start with appropriate contract type
- Fill in all required information
- Attach necessary documents
- Review before submission
- Set up digital signing if required
Digital Signing
- Ensure all documents are finalized
- Verify party information
- Set up signature template correctly
- Submit for signing
- Monitor signing progress
Document Management
- Use clear file names
- Maintain version control
- Keep signed copies secure
- Archive old versions
- Track document changes
Integration Points
Matter Integration
- Link contracts to legal matters
- Track matter-specific contracts
- Share documents between matter and contract
Client Integration
- Associate contracts with clients
- Track client-specific agreements
- Manage client signing process
Project Integration
- Connect contracts to projects
- Track project-related agreements
- Manage project documentation
Technical Details
API Endpoints
Contract Management
http
GET /api/contracts # List contracts
GET /api/contracts/{id} # Get contract details
POST /api/contracts # Create contract
PUT /api/contracts/{id} # Update contract
DELETE /api/contracts/{id} # Delete contract (Draft only)Digital Signing
http
GET /api/contracts/{id}/template # Get signature template
GET /api/contracts/{id}/submissions # Get signing submissions
POST /api/contracts/docuseal/{id}/submitForSigning # Submit for signing
POST /api/contracts/{id}/submission/create # Create signing submissionSecurity Considerations
- Role-based access control
- Document encryption
- Secure digital signing
- Audit trail of all actions
- Data privacy compliance
Troubleshooting
Common Issues
Cannot Delete Contract
- Verify contract is in Draft status
- Check user permissions
- Ensure no active signing process
Digital Signing Issues
- Verify document format
- Check party contact information
- Confirm template setup
- Validate submission details
Document Management
- Check file size limits
- Verify supported formats
- Ensure proper permissions
Support Resources
- Technical support contact
- Documentation updates
- Training materials
- Help desk tickets
Future Enhancements
- AI-powered contract analysis
- Automated contract review
- Risk assessment automation
- Enhanced template management
- Advanced reporting features
Code Specifications
Data Models
Contract Model
csharp
public class Contract : BaseEntity
{
public string ContractUUId { get; set; }
public string ContractName { get; set; }
public string ContractDescription { get; set; }
public ContractType ContractType { get; set; }
public ContractStatus Status { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public decimal? Amount { get; set; }
public string Currency { get; set; }
public bool IsSigned { get; set; }
public string Comments { get; set; }
// Related Entities
public int? MatterId { get; set; }
public int? ClientId { get; set; }
public int? ProjectId { get; set; }
// Digital Signing
public string DigitalContractId { get; set; }
public string DigitalContractSubmissionId { get; set; }
}Contract DTOs
csharp
public class ContractDto
{
public int Id { get; set; }
public string ContractUUId { get; set; }
public string ContractName { get; set; }
public ContractType ContractType { get; set; }
public ContractStatus Status { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public decimal? Amount { get; set; }
public string Currency { get; set; }
// ... other properties
}
public class CreateContractInput
{
public string ContractName { get; set; }
public string ContractDescription { get; set; }
public ContractType ContractType { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public decimal? Amount { get; set; }
public string Currency { get; set; }
// ... other properties
}
public class UpdateContractInput
{
public string ContractName { get; set; }
public string ContractDescription { get; set; }
public ContractStatus Status { get; set; }
// ... other properties
}Frontend Components
Contract List Component
vue
<!-- Contracts.vue -->
<template>
<div class="p-4">
<shad-card class="w-full">
<shad-card-header>
<shad-card-title>Contracts</shad-card-title>
<shad-card-description>Manage your legal contracts</shad-card-description>
</shad-card-header>
<shad-card-content>
<shad-data-table
:columns="columns"
:data="contracts"
:searchValue="search"
@search="handleSearch"
>
<!-- Table content -->
</shad-data-table>
</shad-card-content>
</shad-card>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useStore } from 'vuex';
import { ContractStore } from '@/store/modules/contracts';
const store = useStore();
const search = ref('');
const columns = [
{ key: 'contractName', label: 'Contract Name' },
{ key: 'contractType', label: 'Type' },
{ key: 'status', label: 'Status' },
{ key: 'startDate', label: 'Start Date' },
{ key: 'endDate', label: 'End Date' },
{ key: 'actions', label: 'Actions' }
];
// ... component logic
</script>Contract Detail Component
vue
<!-- Contract.vue -->
<template>
<master-detail :backLink="{ name: 'Contracts' }">
<div class="flex items-center justify-between">
<div class="flex items-center">
<span class="text-lg font-semibold">{{ contract?.contractName }}</span>
</div>
<!-- Status Badge and Actions -->
<div class="flex items-center">
<!-- Submit for Signing Button (Draft only) -->
<shad-button
v-if="contract?.status == ContractStatus.Draft"
variant="outline"
size="sm"
class="mr-2"
:disabled="state.submitting"
@click="submitForSigning"
>
<iconify-icon
:icon="state.submitting ? 'lucide:loader-circle' : 'lucide:signature'"
class="mr-2"
:class="{ 'fa-spin': state.submitting }"
/>
{{ state.submitting ? "Submitting..." : "Submit for Signing" }}
</shad-button>
<!-- Status Badge -->
<shad-button
variant="outline"
size="sm"
@click="showUpdateStatusModal = true"
>
{{ contract?.status }}
</shad-button>
</div>
</div>
</master-detail>
</template>
<script setup lang="ts">
import { ref, computed, reactive } from 'vue';
import { useStore } from 'vuex';
import { ContractStore } from '@/store/modules/contracts';
import { ContractStatus } from '@/network/dtos/enumTypes';
// ... component logic
</script>Contract Status Update Component
vue
<!-- UpdateContractStatus.vue -->
<template>
<Dialog>
<DialogContent>
<DialogHeader>
<DialogTitle>Update Contract Status</DialogTitle>
<DialogDescription>
For digital contracts, only Signed contracts can be changed to Expired status.
Contracts without a Digital Contract ID can be changed to any status.
</DialogDescription>
</DialogHeader>
<!-- Status selection UI -->
<div class="flex w-full items-center gap-2">
<!-- Status steps based on contract type -->
<template v-for="status in visibleStatusSteps">
<div class="flex flex-col items-center">
<Button
:disabled="isStatusDisabled(status.value)"
@click="updateStatus"
>
{{ status.label }}
</Button>
</div>
</template>
</div>
</DialogContent>
</Dialog>
</template>API Integration
Contract Service Interface
csharp
public interface IContractService
{
Task<PaginatedDto<ContractListDto>> GetContracts(ContractFilterInput input, ContractRelatedEntity? relatedEntity);
Task<ContractDto> GetById(int id);
Task<ContractDto> CreateContract(CreateContractInput input);
Task<ContractDto> UpdateContract(int id, UpdateContractInput input);
Task DeleteContract(int id);
Task ChangeStatus(List<int> ids, ContractStatus status);
Task<DocuSealSubmission> HandleDigitalSigningProcess(int id, List<int> documentIds);
// ... other methods
}Vuex Store Module
typescript
// contracts.ts
export const ContractStore = {
state: {
contracts: [],
currentContract: null,
loading: false,
error: null
},
getters: {
GET_CONTRACTS: "GET_CONTRACTS",
GET_CONTRACT: "GET_CONTRACT",
// ... other getters
},
mutations: {
SET_CONTRACTS: "SET_CONTRACTS",
SET_CONTRACT: "SET_CONTRACT",
SET_LOADING: "SET_LOADING",
SET_ERROR: "SET_ERROR"
},
actions: {
GET_CONTRACTS: "GET_CONTRACTS",
GET_CONTRACT: "GET_CONTRACT",
CREATE_CONTRACT: "CREATE_CONTRACT",
UPDATE_CONTRACT: "UPDATE_CONTRACT",
DELETE_CONTRACT: "DELETE_CONTRACT",
SUBMIT_CONTRACT_FOR_SIGNING: "SUBMIT_CONTRACT_FOR_SIGNING"
}
};Digital Signing Integration
DocuSeal Service Interface
csharp
public interface IDocuSealService
{
Task<string> GetDocusealFormBuilderToken(int contractId);
Task<DocuSealTemplateDto> GetDocusealTemplate(int id);
Task<DocuSealSubmissionsResponse> GetDocusealSubmissions(string contractId);
Task<DocuSealSubmission> CreateSubmission(string contractId, DocuSealCreateSubmissionInput submission);
}Digital Signing DTOs
csharp
public class DocuSealSubmitter
{
public string Email { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public bool SendEmail { get; set; }
public bool SendSms { get; set; }
}
public class DocuSealSubmissionItem
{
public List<DocuSealSubmitter> Submitters { get; set; }
}
public class DocuSealCreateSubmissionInput
{
public int TemplateId { get; set; }
public List<DocuSealSubmissionItem> Submission { get; set; }
public bool SendEmail { get; set; }
public bool SendSms { get; set; }
public string Order { get; set; }
}Error Handling
Backend Error Handling
csharp
public async Task<ContractDto> CreateContract(CreateContractInput input)
{
try
{
// Validation
if (input == null)
throw new ArgumentNullException(nameof(input));
if (string.IsNullOrEmpty(input.ContractName))
throw new ValidationException("Contract name is required");
// Create contract
var contract = _mapper.Map<Contract>(input);
contract.Status = ContractStatus.Draft;
await _contractRepository.InsertAsync(contract);
await _unitOfWork.SaveChangesAsync();
return _mapper.Map<ContractDto>(contract);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating contract");
throw;
}
}Frontend Error Handling
typescript
async function submitForSigning() {
if (!contract.value?.id) return;
state.submitting = true;
try {
await store.dispatch(ContractStore.actions.SUBMIT_CONTRACT_FOR_SIGNING, {
id: contract.value.id.toString()
});
await fetchContract(); // Refresh contract data
fireSuccessToast("Contract submitted for signing successfully");
} catch (error) {
fireErrorToast("Failed to submit contract for signing. Please try again.");
console.error('Failed to submit contract for signing:', error);
} finally {
state.submitting = false;
}
}Security Implementation
Permission Attributes
csharp
[HttpGet]
[Can(Permissions.ContractView)]
public async Task<PaginatedDto<ContractListDto>> GetList([FromQuery] ContractFilterInput filterInput)
{
return await _contractService.GetContracts(filterInput, filterInput.RelatedEntity);
}
[HttpDelete("{id}")]
[Can(Permissions.ContractDelete)]
public async Task Delete(int id)
{
var contract = await _contractService.GetById(id);
if (contract.Status != ContractStatus.Draft)
throw new ValidationException("Only contracts in Draft status can be deleted");
await _contractService.DeleteContract(id);
}Frontend Permission Checks
vue
<template>
<div class="flex justify-end mt-4 space-x-2">
<alp-can permission="ContractEdit">
<shad-button variant="outline" @click="editContract">
<font-awesome-icon icon="fa-solid fa-edit" class="mr-2" />
Edit Contract
</shad-button>
</alp-can>
<alp-can permission="ContractDelete">
<shad-button
variant="destructive"
@click="showDeleteWarning"
v-if="contract?.status === ContractStatus.Draft"
>
<font-awesome-icon icon="fa-solid fa-trash" class="mr-2" />
Delete Contract
</shad-button>
</alp-can>
</div>
</template>