Skip to content

cranleighschool/diplomas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cranleighschool/diplomas

A Laravel package for managing Cranleigh School Diploma tracking — Sixth Form, Intermediate, and Junior diplomas all on shared tables. Diploma types are represented as a PHP backed enum rather than a database table.


Requirements

  • PHP 8.5+
  • Laravel 12 or 13

Installation

1. Add the package via Composer

If hosted on a private VCS (e.g. GitHub), add the repository to your main project's composer.json first:

"repositories": [
    {
        "type": "vcs",
        "url": "https://github.com/cranleighschool/diplomas"
    }
]

Then require it:

composer require cranleighschool/diplomas

The service provider is auto-discovered — no manual registration needed.


2. Publish the config

php artisan vendor:publish --tag=diplomas-config

Edit config/diplomas.php to point at your Pupil model and table if they differ from the defaults:

'pupil_model' => App\Models\Pupil::class,
'pupil_table' => 'pupils',

Or via .env:

DIPLOMAS_PUPIL_MODEL=App\Models\Pupil
DIPLOMAS_PUPIL_TABLE=pupils

3. Run the migrations

php artisan migrate

To publish migrations into your project for customisation:

php artisan vendor:publish --tag=diplomas-migrations
php artisan migrate

4. Add the trait to your Pupil model

use CranleighSchool\Diplomas\Traits\HasDiplomas;

class Pupil extends Model
{
    use HasDiplomas;
}

5. Seed the Sixth Form Diploma data

php artisan db:seed --class="CranleighSchool\Diplomas\Database\Seeders\SixthFormDiplomaSeeder"

Or from your DatabaseSeeder:

use CranleighSchool\Diplomas\Database\Seeders\SixthFormDiplomaSeeder;

public function run(): void
{
    $this->call(SixthFormDiplomaSeeder::class);
}

The DiplomaType Enum

Diploma types are a PHP backed string enum — no diploma_types table needed.

use CranleighSchool\Diplomas\Enums\DiplomaType;

DiplomaType::SixthForm->value;     // 'sixth-form'
DiplomaType::Intermediate->value;  // 'intermediate'
DiplomaType::Junior->value;        // 'junior'

DiplomaType::SixthForm->label();    // 'Sixth Form Diploma'
DiplomaType::SixthForm->subtitle(); // 'Future Ready – World Ready – Life Ready'

DiplomaType::options();
// ['sixth-form' => 'Sixth Form Diploma', 'intermediate' => 'Intermediate Diploma', ...]

Usage

Enrol a pupil onto a diploma

use CranleighSchool\Diplomas\Enums\DiplomaType;

$pupil->enrolOnDiploma(DiplomaType::SixthForm);

enrolOnDiploma() is idempotent — calling it twice won't create duplicate records or entries.


Access a pupil's diploma

$diploma = $pupil->sixthFormDiploma;                       // HasOne shorthand
$diploma = $pupil->diploma(DiplomaType::SixthForm);        // Or by enum
$diplomas = $pupil->diplomas;                              // All enrolments

Mark a category as complete

$entry = $diploma->entries()
    ->whereHas('category', fn($q) => $q->where('name', 'Mock Interview'))
    ->first();

$entry->markComplete('Completed via careers portal');

// Or mark incomplete
$entry->markIncomplete();

Points are recalculated automatically on the parent PupilDiploma.


Check progress

$diploma->total_points;           // int — current earned points
$diploma->progressPercentage();   // float — e.g. 67.3
$diploma->isComplete();           // bool — all required sections satisfied
$diploma->progressBySections();   // Collection — section-by-section breakdown

progressBySections() returns a collection of arrays:

[
    [
        'section'          => DiplomaSection,
        'required'         => 5,
        'completed'        => 3,
        'section_complete' => false,
        'entries'          => Collection<PupilDiplomaCategoryEntry>,
    ],
    // ...
]

Award a diploma

if ($diploma->isComplete()) {
    $diploma->award(); // Sets awarded_at to now()
}

Adding new diploma types (Intermediate / Junior)

The DiplomaType enum already includes Intermediate and Junior cases. Just create a new seeder following the same pattern as SixthFormDiplomaSeeder, using the appropriate enum value:

DiplomaSection::create([
    'diploma_type' => DiplomaType::Intermediate->value,
    'name'         => 'Your Section Name',
    // ...
]);

No schema changes required.


Database Tables

Table Purpose
diploma_sections Sections per diploma type (stores enum value as string), with optional required_count
diploma_categories Individual activities/items with points, per section
pupil_diplomas One record per pupil per diploma type — the enrolment anchor
pupil_diploma_category_entries Per-category completion record per pupil

Models & Enums

Class Namespace
DiplomaType CranleighSchool\Diplomas\Enums
DiplomaSection CranleighSchool\Diplomas\Models
DiplomaCategory CranleighSchool\Diplomas\Models
PupilDiploma CranleighSchool\Diplomas\Models
PupilDiplomaCategoryEntry CranleighSchool\Diplomas\Models
HasDiplomas (trait) CranleighSchool\Diplomas\Traits

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages