Feature #859 » INTEGRATION_GUIDE.md
DentPal — Perio Chart Feature Scaffold
Integration Guide
Stack: ABP 8.x · EF Core · Angular Standard · LeptonX · Multi-tenant
File Map
csharp/
Domain/
PatientPerioExam.cs ← Aggregate root entity (IMultiTenant)
PatientPerioMeasurement.cs ← Measurement row entity + MeasurementTypes constants
IPerioExamRepository.cs ← Repository interfaces
Application/
PerioChartDto.cs ← All DTOs (PerioExamSummaryDto, PerioChartDto, ToothChartDto, SideMeasurementsDto)
PerioChartTransformService.cs ← Pivot + calculation logic (AG, CAL)
IPerioChartAppService.cs ← Service interface
PerioChartAppService.cs ← Implementation (2 endpoints)
Permissions/
DentPalPermissions.cs ← Permission constants + PermissionDefinitionProvider
angular/
models/
perio-chart.model.ts ← TypeScript interfaces (mirrors C# DTOs)
pipes/
pd-color.pipe.ts ← 8 pipes: pdColor, mgjColor, agColor, calColor, recColor, furcColor, mobColor, perioDash
services/
perio-chart.service.ts ← HTTP service (ABP RestService pattern)
perio-chart.component.ts ← Main component class + stats calculation
perio-chart.component.helpers.ts ← Helper methods to add to component class
perio-chart.component.html ← OD-convention layout template
perio-chart.component.scss ← LeptonX-aware styles
perio-chart.module.ts ← Feature module + routing + usage notes
Step-by-Step Integration
1. C# — Add EF Core DbSet entries
In your DentPalDbContext.cs:
public DbSet<PatientPerioExam> PerioExams { get; set; }
public DbSet<PatientPerioMeasurement> PerioMeasurements { get; set; }
2. C# — Configure entities in OnModelCreating
builder.Entity<PatientPerioExam>(b => {
b.ToTable("PerioExams");
b.ConfigureByConvention();
b.Property(e => e.PMSPerioExamID).HasMaxLength(100).IsRequired();
b.Property(e => e.ProviderId).HasMaxLength(100).IsRequired();
b.Property(e => e.Note).HasMaxLength(2000);
b.HasIndex(e => new { e.PatientId, e.ExamDate });
});
builder.Entity<PatientPerioMeasurement>(b => {
b.ToTable("PerioMeasurements");
b.ConfigureByConvention();
b.Property(e => e.MeasurementType).HasMaxLength(50).IsRequired();
b.Property(e => e.SurfaceCode).HasMaxLength(5);
b.Property(e => e.MeasurementValue).HasPrecision(5, 2);
b.HasIndex(e => new { e.PerioExamId, e.ToothNum, e.SurfaceCode, e.MeasurementType })
.IsUnique();
});
3. C# — Implement repositories
Create EfCorePerioExamRepository.cs and EfCorePerioMeasurementRepository.cs
implementing the interfaces in IPerioExamRepository.cs.
Use EfCoreRepository<DentPalDbContext, T, Guid> as base class (ABP pattern).
4. C# — Register services in DependencyInjection
// In your ApplicationModule or DomainModule ConfigureServices:
context.Services.AddTransient<PerioChartTransformService>();
ABP auto-registers PerioChartAppService via convention — no manual registration needed.
5. C# — Add permissions to your existing provider
Do NOT create a new PermissionDefinitionProvider — add the perio group to your
existing DentPalPermissionDefinitionProvider.Define() using the snippet in
DentPalPermissions.cs.
6. C# — Add migration
cd src/DentPal.EntityFrameworkCore
dotnet ef migrations add AddPerioChartTables
dotnet ef database update
7. Angular — Copy files into your project
Copy the angular/ folder contents into:
src/app/perio-chart/
8. Angular — Merge helper methods into component
Open perio-chart.component.ts and add all methods from
perio-chart.component.helpers.ts into the PerioChartComponent class.
Also add the DotsData interface at the top of the component file.
9. Angular — Add lazy route
In app-routing.module.ts:
{
path: 'patients/:patientId/perio-chart',
loadChildren: () =>
import('./perio-chart/perio-chart.module').then(m => m.PerioChartModule),
canActivate: [authGuard],
data: { requiredPolicy: 'DentPal.PerioChart.View' },
},
10. Angular — Split routing module
Create perio-chart-routing.module.ts by uncommenting the block at the bottom of
perio-chart.module.ts and removing the inline comment markers.
11. Angular — Embed in patient page
<app-perio-chart
[patientId]="patient.id"
[patientName]="patient.fullName">
</app-perio-chart>
API Endpoints (auto-generated by ABP)
| Method | URL | Permission |
|---|---|---|
| GET | /api/app/perio-chart/patients/{patientId}/exams |
DentPal.PerioChart.View |
| GET | /api/app/perio-chart/exams/{examId}/chart |
DentPal.PerioChart.View |
Both appear automatically in Swagger once the AppService is registered.
Key Design Decisions (OD Convention Applied)
| Decision | Value | Source |
|---|---|---|
| Upper jaw graph direction | Bars hang DOWN ▼ | OD screenshot Q1 |
| Lower jaw graph direction | Bars grow UP ▲ | OD screenshot Q1 |
| Furcation color threshold | Red if ≥ 1 | OD right panel Q2 |
| Mobility color threshold | Red if ≥ 1 | OD right panel Q3 |
| BleedSupPlaqCalc storage | 4 separate boolean rows per surface | OD dots Q4 |
| Missing surface | null → dash (–) displayed | Spec Q5 |
| Negative AG display | Shown as-is, amber (no blocking) | OD chart Q6 |
| Tooth numbering | Universal 1–32 | OD tooth row Q7 |
| Exam note display | Banner below exam selector | OD left panel Q8 |
| Recession vs GingMargin | Two separate measurement rows | OD row labels Q9 |
| Graph Y-axis scale | None (proportional bars only) | OD screenshot Q10 |
Calculation Rules (backend — PerioChartTransformService.cs)
Attached Gingiva = MGJ − PD
→ Negative result: amber warning in UI, no clamping
CAL (apical) = PD + Recession (when Recession > 0)
CAL (overgrowth) = max(0, PD − |GM|) (when GingMargin < 0)
CAL (at CEJ) = PD (when GM = 0)
Analyzed : 11 Mar 2026 | DentPal Perio Chart v3 | ABP 8.x + EF Core + Angular