Your model includes referential cycles. This comes up quite a bit when you're modeling and you haven't worked through the differences between what relationships exist and what relationships are important to your system.
Without knowing more about your business rules and their justification, I would suggest that you consider dropping teachers.topic_id
and possibly also teachers.subject_id
.
Your lessons
table relates subjects and topics. Since you have a many-to-many relationship between teachers and lessons, you can use lessons
(via teachers_and_lessons
) to tell you which teachers can teach which topics and which subjects.
I doubt that neither teachers.topic_id
nor teachers.subject_id
are correct anyway, since this would imply that any given teacher can only teach one topic and one subject. I don't know about your school, but it sounds much too specialized to me!
Edit: Recognizing Teaching Qualifications
Based on a comment by OP (below) the question is how can a teacher be recognized as being qualified to teach a topic without there being an actual lesson assignment made (yet)?
Issue 1: The relationship of topics to subjects:
It isn't clear from the original question whether topics belong to one subject or possibly to multiple subjects. If topics (e.g. fractions) belong to only one subject (e.g. math) then there should be a foreign key like so: topics.subject_id
. If this were so, then lessons.subject_id
would be redundant and could also be dropped. This would simplify the model and make things much clearer while reducing the risk of inconsistent foreign keys.
Issue 2: What teachers can do vs. what they are doing:
The teachers_and_lessons
table shows which lessons teachers are actually teaching. Before this assignment is made, OP would like to be able to record which topics a teacher is qualified to teach. This could be done with a second M:N intersection, like so:
teacher_qualifications:
(teacher_id (PK/FK), topic_id (PK/FK))
This design assumes the simplification suggested under Issue 1, above. One potential drawback of this simplistic solution is that there is no constraint against assigning a teacher to teach a lesson for which they are unqualified. This constraint, if it is important, could be accommodated by replacing the teacher_qualifications
and the teachers_and_lessons
tables with new tables as follows:
teacher_qualifications:
(qualification_id (PK), teacher_id (FK,UN1), topic_id (FK,UN1))
lesson_instructor:
(qualification_id (PK,FK), lessons_id (PK,FK))
Again, these tables assume the simplification from Issue 1. Even without that simplification, these tables could be amended to use an analogous approach.
In addition to seconding Joel Brown's comment I would like to suggest a couple things to help.
If this is for internal use only start with open source accounting and ERP db's. For example, LedgerSMB or Adempiere. Also do this if you are releasing open source. If you are not releasing open source, consider interoperating with such software for billing. I would be happy to help (conflict of interest alert).
Look specifically at batch processing and review requirements. This allows human review as to how much money is owed before the money hits the books.
One thing we are doing in LedgerSMB is to have the possibility of "template transactions" which can then be copied out and filled in (possibly by automatic processes).
Accounting is a large field but if you are handling billing you really need to know it.
Along these lines, I don't really see anything wrong with what you have posted but it is quite incomplete. You need line items for the invoices, and you need line items for the payments. In this way it becomes a lot simpler to track how much is owed. You may also want to separate out students from customers in case one parent has multiple children enrolled in the school.
Best Answer
To your specific question of (easily satisfied) plausibility, the answer is yes. Since you seem to be looking for a broader critique. You seem to be mostly on the right track, but a few things are making your description overly complex.
It looks like your Classes table is more like what I would consider a course to be and your departments_teachers_and_classes is more of what I would expect a Classes table to be. A course would be Math, but a class would be the Math course taught by a particular teacher during a particular school term. A class is like an instance of a course.
To carry this change through, your departments_teachers_classes_and_students could simply be ClassStudents.
It seems as though you are using the department concept on several different levels. You should decide where the department belongs and stop referencing it everywhere else. You've said that a teacher can teach for multiple departments, so we can't put the department in the teachers table. This leaves Classes and Courses. Whichever you decide, it need only have a foreign key to the Departments table (unless you decide that one can be in multiple Departments). This eliminates the Departments_and_teachers table.
Teachers_and_Students could be replaced with a teacher foreign key in the Classes table and students/classes foreign keys in a ClassStudents table.
In short, for the portion of the design you have described, you probably need the following tables: