Title: TradeSchool Manager
Author: CJ Burleigh
Published: <strong>June 13, 2026</strong>
Last modified: September 19, 2026

---

Search plugins

![](https://ps.w.org/tradeschool-manager/assets/banner-772x250.png?rev=3571204)

![](https://ps.w.org/tradeschool-manager/assets/icon-256x256.png?rev=3571204)

# TradeSchool Manager

 By [CJ Burleigh](https://profiles.wordpress.org/cburleigh/)

[Download](https://downloads.wordpress.org/plugin/tradeschool-manager.1.1.25.zip)

 * [Details](https://li.wordpress.org/plugins/tradeschool-manager/#description)
 * [Reviews](https://li.wordpress.org/plugins/tradeschool-manager/#reviews)
 *  [Installation](https://li.wordpress.org/plugins/tradeschool-manager/#installation)
 * [Development](https://li.wordpress.org/plugins/tradeschool-manager/#developers)

 [Support](https://wordpress.org/support/plugin/tradeschool-manager/)

## Description

**TradeSchool Manager** is a purpose-built student-information and gradebook plugin
for trade schools, vocational programs, certification academies, apprenticeships,
and hands-on training providers. Everything runs inside your own WordPress install–
no SaaS accounts, no per-student fees, no monthly subscriptions for the free core.

Built and maintained by **CJs Web Service** ([cjswebservice.com](https://cjswebservice.com/)).
Product home, demos, and documentation live at [tradeschoolmanager.com](https://tradeschoolmanager.com/).

#### Why TradeSchool Manager?

Most school plugins are built for K-12 or higher-ed and bury trade-school workflows
under features you’ll never use. TradeSchool Manager starts from the trade-school
workflow:

 * Cohort-based **programs** that run across **school years**, with a one-click 
   rollover that copies class definitions and assignments into the new year while
   preserving every prior year’s grades, rosters, and attendance untouched.
 * A **gradebook** that supports points, weighted categories, **and pass/fail** (
   because hands-on competencies aren’t a percentage).
 * A global **Active School Year** switcher so dashboards, rosters, and gradebooks
   always reflect the year you’re actually working in.
 * Admin-side, branded, print-ready **PDF report cards and class rosters** out of
   the box.
 * **Student and teacher portals** as front-end shortcodes you drop onto any WordPress
   page – no separate app to host.

#### What’s in the free core

 * **Students & Teachers** – Profiles with school-assigned Student Numbers, photos,
   emergency contacts, and portal credentials.
 * **Sponsors & Authorized Contacts** – Optional accounts for family members, employers,
   sponsors, or other approved contacts linked to one or more students.
 * **Programs & School Years** – Multi-year programs with enrollment, GPA computation,
   year rollover, and historical preservation.
 * **Classes & Gradebook** – Points-based, weighted-category, or pass/fail grading;
   assignment categories; extra credit; teacher-scoped views.
 * **Attendance** – Daily attendance tracking with per-class and per-student reports.
 * **Announcements** – Post school-wide or class-specific announcements visible 
   in the portals.
 * **Student, Teacher, and Sponsor Portals** – Front-end shortcodes for grades, 
   assignments, rosters, payments, and linked-student access.
 * **CSV Import/Export** – Move students, classes, class enrollments, assignments,
   and grades without lock-in.
 * **Admin PDF Reports** – Unified PDF engine renders administrator report cards,
   class rosters, and statements on your school letterhead.
 * **Active School Year context** – One global switcher scopes every list, dashboard,
   and gradebook.
 * **Email delivery via Brevo** – Built-in, optional. 300 transactional emails/day
   on Brevo’s free plan; automatic fallback to native `wp_mail()` if the daily cap
   is reached. You can also skip Brevo entirely and use whatever SMTP plugin you
   already run.

#### Optional paid add-ons

The free core is fully functional on its own. These capabilities ship as separate
add-on plugins from [tradeschoolmanager.com](https://tradeschoolmanager.com/) and
are detected at runtime – any UI tied to an add-on stays hidden when that add-on
isn’t installed.

 * **Certificates** – Auto-issued PDF certificates of completion with reminder emails.
 * **Reports & Transcripts** – Multi-year transcripts, summary report cards, GPA,
   credits.
 * **Workshops** – Short-form, year-agnostic courses with their own gradebook and
   completion certificates.
 * **Applications** – Public application forms and an admissions pipeline.
 * **Invoicing & Contracts** – Tuition invoicing, payment plans, e-sign contracts,
   and optional Stripe checkout.
 * **Custom Fields & Student Documents** – Per-program metadata plus audit-logged
   document uploads for government compliance.

#### Who it’s for

 * Trade schools (electrical, plumbing, HVAC, welding, automotive, construction)
 * Cosmetology, esthetics, and barbering schools
 * CDL, heavy-equipment, and aviation training
 * Allied health, nursing assistant, and phlebotomy programs
 * Coding bootcamps and short-form vocational programs
 * Apprenticeship and union training programs
 * Anyone running cohort-based, hands-on training out of WordPress

#### External services

The free plugin makes **no calls to external services** until you opt in to Brevo
email delivery (which requires a free Brevo account and an API key). Optional add-
ons may integrate with Stripe (payments); those add-ons are downloaded separately
and have their own privacy disclosures.

 * Brevo (optional, free core): Transactional email via the Brevo HTTP API. Only
   the message payload (to/from/subject/body) is sent, and only when you supply 
   an API key in **TradeSchool > Settings > Email**. Brevo terms: [brevo.com/legal/termsofuse](https://www.brevo.com/legal/termsofuse/).
   Privacy: [brevo.com/legal/privacypolicy](https://www.brevo.com/legal/privacypolicy/).

#### Support & contributing

 * Product site, demos, docs: [tradeschoolmanager.com](https://tradeschoolmanager.com/)
 * Author: CJs Web Service – [cjswebservice.com](https://cjswebservice.com/)
 * Issues and feature requests: through the WordPress.org support forum for this
   plugin

## Screenshots

[⌊Admin dashboard with class averages and active-school-year context.⌉⌊Admin dashboard
with class averages and active-school-year context.⌉[

Admin dashboard with class averages and active-school-year context.

[⌊Student profile management with enrollment, class, and portal account details.⌉⌊
Student profile management with enrollment, class, and portal account details.⌉[

Student profile management with enrollment, class, and portal account details.

[⌊Gradebook entry with weighted categories and extra credit.⌉⌊Gradebook entry with
weighted categories and extra credit.⌉[

Gradebook entry with weighted categories and extra credit.

[⌊Program setup with schedule, passing percentage, and tuition defaults.⌉⌊Program
setup with schedule, passing percentage, and tuition defaults.⌉[

Program setup with schedule, passing percentage, and tuition defaults.

[⌊Attendance session history with roster status details.⌉⌊Attendance session history
with roster status details.⌉[

Attendance session history with roster status details.

[⌊Student portal payments and profile overview in the focused portal layout.⌉⌊Student
portal payments and profile overview in the focused portal layout.⌉[

Student portal payments and profile overview in the focused portal layout.

[⌊Teacher portal class assignment view with workshop access and grading actions.⌉⌊
Teacher portal class assignment view with workshop access and grading actions.⌉[

Teacher portal class assignment view with workshop access and grading actions.

## Installation

 1. Upload the plugin via **Plugins > Add New > Upload Plugin**, or extract to `/wp-
    content/plugins/tradeschool-manager/`.
 2. Activate **TradeSchool Manager** through the **Plugins** screen.
 3. Visit **TradeSchool > Settings** to set your school name, logo, currency, and email-
    from address.
 4. Create your first **School Year**, then your first **Program** and **Classes**.
 5. Create dedicated WordPress pages for the portals and add the shortcodes (see **
    TradeSchool > About** for the full list):
 6.  * `[tsm_student_portal]`
     * `[tsm_teacher_portal]`
     * `[tsm_parent_portal]`

## FAQ

### How do I upgrade to 1.1.25 with the paid add-ons?

Back up the database and uploads, then test on a staging copy. Replace the core 
plugin in place; keep the folder `tradeschool-manager` and do not uninstall it. 
Update installed Certificates to 1.3.19, Workshops to 1.0.25, Custom Fields & Student
Documents to 1.2.18, and Invoicing & Contracts to 1.1.10 as part of the same upgrade.
Internal IDs and existing add-on relationships do not change.

Permanent deletion now requires InnoDB storage for the affected tables and an updated,
active cleanup provider when related add-on records exist. If a provider is unavailable,
deletion stops instead of abandoning its records. Use Drop/Archive when you want
to keep history. Archived academic records must be unarchived before permanent deletion.
Related private files are removed only after the database commit; failed removals
are queued for retry.

### How do I import students and enrollments without changing their identifiers?

For new students, leave `id` blank, place your school’s ID in `student_number`, 
and supply at least a first or last name, or an email. Student Number is optional
and unique when nonblank. Keep identifier columns formatted as Text in spreadsheet
software so it does not remove leading zeros.

For an existing student, enable **Update existing** and identify the student by 
internal `id`, `student_number`, or email. A supplied internal `id` must already
exist. Conflicting identifiers skip the row. To change only a phone number, for 
example, include only `student_number,phone`; omitted columns (including photos)
are preserved. A supplied blank cell clears that field, except a blank password 
never clears the password.

Class Enrollments links existing students to existing classes. Use one student identifier(`
student_id`, `student_number`, or `student_email`), and either `class_id` or `class_name`
plus the visible `school_year` name. If you supply extra identifiers, all must exist
and agree. Clear unused columns and remove example rows. Invalid IDs do not fall
back to names. Assignment imports follow the same class-matching rule in both import
screens. Enrollment imports are additive; they do not unenroll students missing 
from the file.

New exports include `_tsm_csv_encoding=tsm-v1` so spreadsheet-safe apostrophe escaping
can be reversed when re-imported. Keep this column and the escape characters unchanged
when editing an export. For IDs with intentional leading apostrophes, the export
doubles that first apostrophe. Do not add the encoding column to files from another
platform. Older/unmarked files are read literally; check formula-prefixed IDs in
old exports before importing. Spreadsheet software can still change text/number 
formatting, so review the CSV before importing.

### Does the free plugin require a license key or external account?

No. The free plugin runs entirely on your own WordPress install with no key validation
and no calls home. Email via Brevo is opt-in and requires only a free Brevo account.

### Can I migrate to a new school year without losing history?

Yes. The Year Rollover tool copies class definitions and assignments into a new 
year while preserving the source year’s roster, grades, and attendance exactly as
they were. Prior-year report cards and reports continue to render correctly forever.

### Can students see only their own data?

Yes. The student portal authenticates against the student record and scopes every
query to that student. Teachers similarly only see their assigned classes. Sponsors
and authorized contacts only see students they’re linked to.

### Does it support pass/fail grading?

Yes. Each class can use points, weighted categories, or pass/fail. Pass/fail classes
with no graded work display ” – ” rather than a misleading “Fail”.

### How do I take payments or issue tuition invoices?

Install the optional **Invoicing & Contracts** add-on from [tradeschoolmanager.com](https://tradeschoolmanager.com/).
The free plugin does not handle invoicing or payments.

### Where are student documents stored?

Document uploads ship in the optional **Custom Fields & Student Documents** add-
on. When installed, files are stored in a private `tsm-private/student-docs/` directory
inside `wp-content/uploads`, protected by an `.htaccess` deny rule and SHA-prefixed
filenames, with a full upload/download/delete audit log for government chain-of-
custody.

### Does it work with my theme?

Yes. The portals render inside your active theme via shortcodes and inherit your
theme’s colors and typography. Optional portal-theme polish is built in and can 
be disabled per page.

### Is it translation-ready?

Yes. All user-facing strings use the `tradeschool-manager` text domain. WordPress
4.6+ auto-loads translations hosted on WordPress.org.

### Can the Students CSV importer assign existing students to classes?

Class assignments use the separate **Class Enrollments** tab under **TradeSchool
> Import / Export**. Identify a student with `student_id` (TradeSchool Manager’s
internal ID), `student_number` (your school’s ID), or `student_email`. Identify 
a class with `class_id`, or with both `class_name` and `school_year`. The `school_year`
value is the visible school-year name. Imports are additive and never unenroll students
whose rows are absent.

### How do I migrate existing student numbers from another platform?

Download the Students template under **TradeSchool > Import / Export > Students**.
Leave the `id` column blank for new records and place the previous platform’s identifier
in `student_number`. Student Numbers are optional text values up to 100 characters,
so values such as `STU-00087` are supported. Each nonblank Student Number must be
unique. When working in Excel or another spreadsheet application, format the `student_number`
column as Text before pasting numeric identifiers so the spreadsheet does not remove
leading zeros.

When **Update existing students** is selected, matching is performed by internal`
id`, then `student_number`, then email. If supplied identifiers point to different
students, the row is skipped rather than merging records. After importing students,
the same `student_number` values can be used in the Class Enrollments CSV.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“TradeSchool Manager” is open source software. The following people have contributed
to this plugin.

Contributors

 *   [ CJ Burleigh ](https://profiles.wordpress.org/cburleigh/)

[Translate “TradeSchool Manager” into your language.](https://translate.wordpress.org/projects/wp-plugins/tradeschool-manager)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/tradeschool-manager/),
check out the [SVN repository](https://plugins.svn.wordpress.org/tradeschool-manager/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/tradeschool-manager/)
by [RSS](https://plugins.trac.wordpress.org/log/tradeschool-manager/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.1.25

 * Corrected the WordPress.org release packaging: added all five required PHP files
   and the program enrollment guide to version control so they are included in the
   distributed plugin.
 * Aligned the plugin version, runtime version and Stable tag with the release tag.
   Fixes the missing-file startup fatal error in the incomplete 1.1.22 through 1.1.24
   packages.
 * No additional database migration or academic, billing, or add-on behavior changes
   from the complete 1.1.22 build.

#### 1.1.23

 * Emergency packaging release: includes five required PHP files omitted from the
   WordPress.org 1.1.22 download, resolving the resulting missing-file fatal error
   during plugin startup.
 * Restored the program enrollment documentation omitted from that download. No 
   additional database migration or academic, billing, or add-on behavior changes
   from the complete 1.1.22 build.

#### 1.1.22

 * Addressed Plugin Check findings: escaped exception messages, unslashed and strictly
   validated portal session cookies, clarified exact-input validation and dynamic
   prepared-query checks, corrected reset-form scanner annotations, and normalized
   shortcode line endings. Enrollment, billing, and add-on record identifiers are
   unchanged.
 * Added Reactivate to completed, withdrawn, and archived program enrollments in
   the student editor, with or without the Invoicing add-on. Restores the existing
   enrollment without changing student status, class rosters, or billing; existing
   archived-year and duplicate-active-enrollment protections still apply.
 * Fixed weighted-category field indexes after removing and adding rows, so valid
   totals save without one category overwriting another.
 * Wrapped the admin header, notices, and school-year switcher on narrow screens
   to prevent phone-width horizontal page overflow.
 * Hardened student password resets: save new token digests before returning email
   links, accept exact single-use credentials, and atomically update the password
   while consuming the token. Existing unexpired legacy links remain compatible.
 * Invalidated pending reset links when passwords change through the portal or student
   editor; rejected stale reset submissions and stopped displaying success after
   failed saves.
 * Built reset-email links from the configured student login page (site-home fallback),
   not the incoming Host header. Clarified generic email-delivery messaging and 
   reset-save errors.
 * Bound student and teacher portal sessions to their current password: password
   changes and student resets reject older sessions on their next request. Portal
   password changes sign out the current browser and return to the configured login
   page. Existing portal sessions require a fresh sign-in once after upgrading; 
   IDs and add-on relationships are unchanged.
 * Checked session persistence before accepting login, rotated browser session tokens
   on sign-in, and set HttpOnly/SameSite cookies (Secure on HTTPS). Sponsor and 
   WordPress user sessions are unchanged.
 * Made student Drop/Reinstate actions check reads and writes, reject invalid IDs/
   dates, and report failure accurately. Conditional status updates prevent stale
   requests from overwriting a different current status.
 * Made repeated Drop/Reinstate requests no-ops: preserve the original drop date/
   reason and avoid duplicate extension notifications. Existing public drop/reinstate
   methods retain boolean results.
 * Clarified that Drop/Reinstate preserves records and does not cancel class/program
   enrollments, billing, payment plans, or student portal access. Reinstatement 
   clears the current drop date/reason without changing enrollment or financial 
   records.
 * Hardened assignment saves with checked transactions, protected graded assignments
   from moving classes, and rejected missing/archived parents and existing class/
   year mismatches without migrating history.
 * Preserved omitted assignment fields in partial model/CSV updates, rejected ambiguous
   Class + Title CSV matches, and validated real dates, nonnegative finite points,
   and boolean flags. Teacher-portal input now reaches model validation without 
   silently clearing malformed dates.
 * Added assignment-save notices and class-move guidance; preserved the existing
   Required flag in the admin editor and retained Pass/Fail normalization.
 * Prevented class school-year changes from relocating academic/financial history:
   assignments, enrollment, attendance, program links, invoices, and class certificates
   block the move. Completed/archived classes remain in their original year; use
   Rollover for a new year.
 * Kept year corrections available for unused classes, validated destination year
   IDs, and applied the same checks to class CSV updates. Added class-editor guidance;
   existing mismatched records are not automatically migrated.
 * Made class fields and primary/co-teacher selections save in one checked transaction.
   Failed link writes restore the original class and teacher links; class-saved 
   hooks run only after a successful commit.
 * Validated selected teacher IDs, protected archived-year co-teacher editing, and
   preserved unchanged co-teacher link IDs and omitted teacher selections in class
   CSV updates. Existing co-teacher dropdown selections now render without JavaScript.
 * Added a visible Active/Inactive teacher portal-access setting. Inactive teachers
   cannot log in, and existing sessions are rejected on their next request; teaching
   history and credentials are retained.
 * Protected teachers linked to classes, co-teaching, or workshops from permanent
   deletion, including inactive Workshops installations. Unassigned teacher deletion
   now uses checked transactions and accurate admin notices.
 * Made existing-enrollment billing replacement and signed-contract synchronization
   transactional; protected invoices with payment/refund/closed-history records 
   from automatic regeneration and prevented duplicate charges.
 * Validated signed-contract ownership, dates, and schedule totals; Full billing
   now charges total tuition rather than subtracting an unbilled deposit.
 * Made program fields and class-link changes atomic, preserved omitted settings
   and other-year links, and checked enrollment status/removal results. Programs
   with historical enrollment/invoice/certificate records must be archived instead
   of deleted.
 * Protected class enrollments with grade/attendance history and program enrollments
   linked to invoices/contracts from removal; clear result notices replace false
   success.
 * Hardened standalone invoice creation, edits, deletion, and voiding with checked
   transactions; protected payment history and reported email/status-save failures
   accurately.
 * Added keyboard-accessible horizontal scrolling to Students, Teachers, School 
   Years, Classes, Programs, and Assignments tables.
 * Added collapsible mobile navigation with accessible expanded-state and focus 
   handling; navigation remains available without JavaScript.
 * Added visible attendance-pill and navigation/table keyboard focus, consolidated
   status-pill styles, and replaced the focus-mode text icon with WordPress Dashicons.
 * Expanded deletion/removal warnings, moved repeated layout styles into reusable
   classes, and made bundled documentation navigation responsive. Added Program 
   Enrollments & Billing to the documentation index.
 * Cleaned up Students list/add/edit styling: grouped row actions, labeled action
   columns, consistent photo previews and Drop/Reinstate cards, and wrapping profile
   details/buttons on smaller screens. Associated built-in field labels and help
   text with their controls. Student fields, save actions, and add-on hooks are 
   unchanged.
 * Cleaned up student enrollment/billing and document panels with keyboard-scrollable
   tables, grouped actions, consistent textual status pills, labeled billing/upload
   controls, and reusable layout classes. Corrected the empty enrollment row’s column
   span when billing is off. Existing billing defaults, upload/download actions,
   and license restrictions are unchanged.
 * Cleaned up Teachers add/edit/list screens with associated field labels and password
   guidance, consistent input widths, wrapping form actions, readable Active/Inactive
   badges, grouped row actions, and scoped reusable styles. Teacher access rules,
   creation locks, and class/workshop relationships are unchanged.
 * Cleaned up Classes add/edit/list and roster layouts: labeled form fields and 
   dynamic row controls, scrollable co-teacher/category editors, responsive enrollment
   controls, and an explicit empty-roster message. Category totals now announce 
   updates to assistive technology. Grading calculations, category visibility, teacher
   selections, school-year protections, and enrollment actions are unchanged.
 * Cleaned up School Years, Year Rollover, and Archive with labeled fields/class
   selections, consistent Current/Archived badges, named scroll regions, reusable
   spacing, and empty-list messages. Source-year selection now stays on Year Rollover
   and provides a Load classes button without JavaScript; corrected the database
   variable scope used to display source assignment counts. Copy, archive, and deletion
   rules are unchanged.
 * Made new program enrollments transactional across roster links and requested 
   invoices; failed reads, writes, license checks, and commits no longer leave a
   partially created enrollment or fire success hooks.
 * Requires the rebuilt Invoicing & Contracts 1.1.10 for automatic new-enrollment
   billing; Manual billing remains available without the add-on. Invoice numbers
   are reserved before the transaction, so failed attempts may leave numbering gaps.
 * Validated enrollment dates, monetary values, school-year/class relationships,
   and signed-contract ownership; rejected duplicate active enrollment in the same
   program/year and reuse of an already-linked contract.
 * Preserved the Applications workflow for contracts signed before student creation
   by binding an unassigned signed contract only to a matching student email and
   program.
 * Corrected installment cent allocation so the final installment cannot become 
   negative from accumulated rounding; existing stored invoices are not changed.
 * Added program-enrollment failure notices, including when the student was saved
   but their initial enrollment failed. Contract signing now distinguishes a saved
   signature from failed automatic enrollment/billing.
 * Made class/program completion transactional: checks linked records and school
   years, rolls back failed cascades, and sends completion hooks only after commit.
   Requires InnoDB for completion-related tables.
 * Preserved original completion dates on repeat requests and reported failed completion
   in the admin instead of showing success. Already-completed linked classes remain
   unchanged; unfinished archived-year classes block program completion.
 * Preserved enrollment IDs and original enrollment dates when reactivating class
   enrollments, and added an admin enrollment result notice.
 * Coordinated with Certificates 1.3.19 to connect automatic issuance to core’s 
   actual completion hooks while retaining legacy integration hooks.
 * Validated attendance relationships, dates, and statuses; archived years are read-
   only in both the admin and teacher portal, and failed writes no longer display
   success.
 * Fixed teacher attendance notes not being saved and preserved existing notes/record
   IDs for status-only updates.
 * Preserved omitted class settings during edits/imports and expanded class CSV 
   exports to include description, status, passing threshold, credits, and weighted-
   category configuration.
 * Rejected invalid or ambiguous class-definition CSV identifiers instead of silently
   updating another class; checked class save results.
 * Restricted school-year deletion to empty years so classes, assignments, and program
   enrollments cannot be orphaned; added date/save validation and recovery from 
   a deleted active-year selection.
 * Preserved passing thresholds and credits during year rollover and reported incomplete
   copies with a warning instead of implying all records were copied.
 * Validated teacher profile emails before saving, handled failed photo/profile/
   password saves, preserved omitted teacher fields, and rejected deleted-teacher
   sessions.
 * Hardened deletion across core and updated add-ons: checks database operations
   and commit results, requires transactional tables, blocks missing cleanup providers,
   and defers file removal until commit using a durable retry queue.
 * Protected archived academic history from permanent student/class/assignment deletion,
   including assignments cascaded from a class and student-linked audit records.
 * Fixed class certificate cleanup so workshop certificates with the same numeric
   scope ID are preserved; shared certificate files and certificate template files
   are retained.
 * Consolidated both assignment CSV import screens onto one strict class resolver;
   invalid or conflicting supplied IDs no longer fall back to another record.
 * Preserved omitted student fields during partial imports, allowed Student Number-
   only updates, and added reversible formula-safe CSV export encoding.
 * Checked assignment and grade persistence results, corrected import/rollover counts,
   and suppressed successful grade notifications when a write fails.
 * Revoked deleted-student sessions, validated profile emails before sanitizing,
   and retained failed profile form values privately for ten minutes.
 * Added an optional, unique Student Number for school-assigned or legacy platform
   identifiers without changing TradeSchool Manager’s internal student IDs.
 * Added Student Number to student forms, profiles, admin tables, and Students CSV
   import/export while preserving leading zeros and alphanumeric values.
 * Added Student Number matching to Class Enrollments imports and exports.
 * Added safe import conflict detection so mismatched internal IDs, Student Numbers,
   and email addresses cannot merge different students.
 * Kept all core and add-on relationships on the existing internal student ID for
   backward compatibility.
 * Fixed permanent student deletion so core enrollments, grades, attendance, billing
   records, notes, custom values, program enrollments, and parent links are removed
   before the student record.
 * Added coordinated add-on deletion providers and post-commit lifecycle hooks for
   related records and files.
 * Added clear success and failure notices for permanent deletion.
 * Fixed permanent class deletion so enrollments, assignments, grades, attendance,
   program mappings, announcements, and active add-on records are cleaned up while
   financial history is preserved.
 * Replaced the vague class deletion prompt with an explicit description of what
   is removed and retained.
 * Fixed permanent assignment deletion so associated grades and audit history are
   removed before the assignment.
 * Added post-commit assignment-deletion hooks (also used during class deletion),
   clear result notices, and an explicit irreversible-action warning.
 * Fixed assignment CSV matching so class names must be paired with the visible 
   school-year name when class_id is not supplied, preventing assignments from being
   imported into a same-named class from another year.
 * Added school_year to assignment CSV templates and exports and rejects ambiguous
   duplicate class matches instead of guessing.
 * Added central grade relationship validation so CSV and other grade writes reject
   missing assignments, missing students, and students who are not enrolled in the
   assignment class.
 * Allows grades for inactive historical enrollment records while preventing unrelated
   student and class IDs from creating orphaned grade data.
 * Fixed student portal profile updates so success appears only after the database
   update succeeds.
 * Added clear portal errors for invalid or duplicate email addresses, failed photo
   uploads, and database failures, and removes a newly uploaded photo if its profile
   update cannot be saved.

#### 1.1.21

 * Added Class Enrollments CSV import and export for linking existing students to
   existing classes.
 * Added student and class IDs to the first column of their admin tables for CSV
   reference, and made Class Enrollments use the visible school-year name instead
   of requiring its internal ID.
 * Added ID-first matching with email and class-name/year fallbacks, archived-year
   protection, and safe handling of existing enrollments.
 * Reworked the admin Setup Checklist with clean completion indicators and properly
   spaced action links.
 * Fixed the Focus Mode “Exit to WordPress” button so its security nonce and dashboard
   redirect are handled correctly.
 * Updated Class Enrollments queries to use WordPress-recognized fixed plugin table
   names for Plugin Check compliance.
 * Updated tested compatibility for WordPress 7.1.

#### 1.1.19

 * Fixed PDF generation when the saved school logo URL cannot be read by TCPDF on
   the server.
 * Shared PDF headers now resolve Media Library images to local upload paths and
   fall back to the school name when needed.
 * Added admin download buttons for core report-card PDFs and class roster PDFs 
   under Gradebook > Class Reports.
 * Kept student-facing report-card downloads reserved for the Reports & Transcripts
   add-on.

#### 1.1.18

 * Reordered the branded admin sidebar into Manage, Add-ons, and System sections.
 * Added core fallback sidebar entries for installed add-ons so Certificates and
   Applications appear consistently.
 * Hid the default WordPress admin footer on TradeSchool Manager screens.

#### 1.1.17

 * Fixed student portal tab actions so links and panels initialize reliably in the
   focused portal layout.
 * Fixed teacher portal subtab initialization timing for class and add-on views.

#### 1.1.16

 * Converted remaining first-party inline portal, sponsor, email, add-on, and admin
   UI assets to WordPress enqueue APIs.
 * Updated extension hook names and uninstall cleanup symbols to the long `tradeschool_manager_`
   prefix for Plugin Check.
 * Updated bundled Chart.js to 4.5.1 and TCPDF to 6.11.3.
 * Kept first-run and add-on notices limited to TradeSchool Manager admin screens.

#### 1.1.15

 * Limited first-run and add-on data notices to TradeSchool Manager admin screens.
 * Converted reviewer-named inline portal/theme, feedback, attendance, page-title,
   and focus-mode assets to WordPress enqueue APIs.
 * Sanitized grade, class, student, and program hook payloads before passing data
   to extension hooks.
 * Sanitized preserved active-year request values before reuse.
 * Added the requested WordPress.org contributor username to the readme.

#### 1.1.14

 * Added narrow PHPCS suppressions for intentional public extension hooks that Plugin
   Check does not accept through its inferred prefix.

#### 1.1.13

 * Updated custom extension hooks to start with the literal `tradeschool-manager`
   plugin slug used by Plugin Check.
 * Scoped uninstall cleanup variables inside a local closure so the uninstall routine
   does not declare temporary globals.

#### 1.1.12

 * Updated extension hook names and uninstall helper names to the long `tradeschoolmanager_`
   prefix used for Plugin Check inference.

#### 1.1.11

 * Renamed core extension hooks to a registered plugin prefix for WordPress Plugin
   Check compliance.
 * Cleaned uninstall-only variable and helper names so the uninstall routine passes
   prefix checks.

#### 1.1.10

 * Updated the Add-ons settings screen to use stable Freemius license routes for
   Reports & Transcripts and Workshops.

#### 1.1.9

 * Resolved WordPress Plugin Check naming warnings for core teacher portal and grade-
   save hooks.
 * Cleaned uninstall helper naming to use the full TradeSchool Manager prefix.
 * Normalized the main plugin file line endings for repository checks.

#### 1.1.8

 * Added invoice context fields so add-ons can link invoices to a specific workshop
   instance or other future record.

#### 1.1.7

 * Moved the core class report into a Gradebook tab.
 * The dedicated Reports navigation now appears only when the Reports & Transcripts
   add-on is installed.

#### 1.1.6

 * Added teacher portal extension hooks for add-ons.
 * Enables the Workshops add-on to show assigned workshop dashboards inside the 
   teacher portal.

#### 1.1.5

 * Improved the shared PDF engine so add-ons can render wide reports in landscape
   layout.
 * Aligned the plugin header version and runtime version constant.

#### 1.1.4

 * Moved Stripe setup out of core Settings navigation and pointed administrators
   to Invoicing > Stripe.

#### 1.1.3

 * Updated the Add-ons settings screen to use Freemius license popup triggers for
   inactive registered add-ons, matching the working Plugins screen activation flow.

#### 1.1.2

 * Improved the Add-ons settings screen so inactive Freemius add-ons point to license-
   key activation and show the correct inactive state.

#### 1.1.1

 * Updated the Add-ons dashboard to use stable add-on license management pages instead
   of direct Freemius account URLs.

#### 1.1.0

 * Stable launch release of TradeSchool Manager.
 * Students, teachers, classes, programs, school years, and year rollover.
 * Status-driven gradebook with weighted categories, bonus, late penalty, and per-
   assignment entry screens (admin + teacher portal).
 * Student, teacher, and sponsor portals with branded layouts, password management,
   and portal page setup.
 * Attendance, assignments, announcements, and built-in PDF engine for report cards
   and transcripts.
 * CSV import/export for students, classes, class enrollments, assignments, and 
   grades.
 * Email notifications with native wp_mail() delivery settings, sender identity 
   controls, template review, and activity logging.
 * Setup Checklist, in-admin Documentation, and Shortcodes reference on the About
   page.
 * Add-on framework for optional Certificates, Reports & Transcripts, Workshops,
   Applications, Invoicing & Contracts, and Custom Fields & Student Documents.

## Meta

 *  Version **1.1.25**
 *  Last updated **2 weeks ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 5.8 or higher **
 *  Tested up to **7.1.3**
 *  PHP version ** 7.4 or higher **
 *  Language
 * [English (US)](https://wordpress.org/plugins/tradeschool-manager/)
 * Tags
 * [attendance](https://li.wordpress.org/plugins/tags/attendance/)[GradeBook](https://li.wordpress.org/plugins/tags/gradebook/)
   [lms](https://li.wordpress.org/plugins/tags/lms/)[school](https://li.wordpress.org/plugins/tags/school/)
   [students](https://li.wordpress.org/plugins/tags/students/)
 *  [Advanced View](https://li.wordpress.org/plugins/tradeschool-manager/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/tradeschool-manager/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/tradeschool-manager/reviews/)

## Contributors

 *   [ CJ Burleigh ](https://profiles.wordpress.org/cburleigh/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/tradeschool-manager/)

## Donate

Would you like to support the advancement of this plugin?

 [ Donate to this plugin ](https://tradeschoolmanager.com/)