A department sits between a company and the people in it #137

Closed
opened 2026-09-09 10:36:55 +00:00 by tiagoagueda · 1 comment
Owner

Observation

parent company > child company > departement > person of contact

Prerequisite for the employer-tree plugin. Three of those four exist; the department does
not, and it is the one that changes an existing model rather than adding beside it.

What exists

Contact — "Someone at a company: a recruiter, a hiring manager, a friend on the
inside"
— hangs directly off Company through a nullable foreign key, and carries a free
text role. There is no department anywhere in the codebase.

So the structure a person can record today is two levels: a company, and the people at it.
Which team those people are in is either in role ("Engineering — hiring manager"), in
notes, or nowhere.

What this asks for

A department between the two, so that a contact belongs to a team and an application can
name the team it was for.

Worth being careful about

A department is not a small company, and modelling it as one would be tempting. It has
no website, no logo, no identifiers, no industries, and no postings of its own that are not
also the company's. If it is a Company with a parent, then the companies list fills with
things nobody applied to and every count has to learn to exclude them. A separate model is
more code and fewer lies.

Free text already holds this, badly. Some people have been putting the team in role
because there was nowhere else. A department that arrives with no way to promote that text
leaves the data in two places for ever; a migration cannot parse it, but the contact form
can offer it once, beside the new field.

Nullable in both directions, and that is the normal case. Most contacts will never have
a department, and a department with no contacts is perfectly ordinary — it is a team you
applied to before you knew anybody there. Neither side may be required.

Deleting. A department going away must not take its contacts with it: SET_NULL, so the
people survive with their company intact. A company going away already cascades to its
contacts, and departments follow that.

Uniqueness per company, per owner. Two departments called Engineering at one company
is a mistake worth refusing; the same name at two companies is not. Company already has
UniqueConstraint(fields=("owner", "name")) as the precedent.

This is one of the models the plugin would own, so what happens to a department when the
plugin is uninstalled is #128's question and not answerable here.

## Observation > parent company > child company > departement > person of contact Prerequisite for the employer-tree plugin. Three of those four exist; the department does not, and it is the one that changes an existing model rather than adding beside it. ## What exists `Contact` — *"Someone at a company: a recruiter, a hiring manager, a friend on the inside"* — hangs directly off `Company` through a nullable foreign key, and carries a free text `role`. There is no department anywhere in the codebase. So the structure a person can record today is two levels: a company, and the people at it. Which team those people are in is either in `role` ("Engineering — hiring manager"), in `notes`, or nowhere. ## What this asks for A department between the two, so that a contact belongs to a team and an application can name the team it was for. ## Worth being careful about **A department is not a small company, and modelling it as one would be tempting.** It has no website, no logo, no identifiers, no industries, and no postings of its own that are not also the company's. If it is a `Company` with a parent, then the companies list fills with things nobody applied to and every count has to learn to exclude them. A separate model is more code and fewer lies. **Free text already holds this, badly.** Some people have been putting the team in `role` because there was nowhere else. A department that arrives with no way to promote that text leaves the data in two places for ever; a migration cannot parse it, but the contact form can offer it once, beside the new field. **Nullable in both directions, and that is the normal case.** Most contacts will never have a department, and a department with no contacts is perfectly ordinary — it is a team you applied to before you knew anybody there. Neither side may be required. **Deleting.** A department going away must not take its contacts with it: `SET_NULL`, so the people survive with their company intact. A company going away already cascades to its contacts, and departments follow that. **Uniqueness per company, per owner.** Two departments called *Engineering* at one company is a mistake worth refusing; the same name at two companies is not. `Company` already has `UniqueConstraint(fields=("owner", "name"))` as the precedent. **This is one of the models the plugin would own**, so what happens to a department when the plugin is uninstalled is #128's question and not answerable here.
tiagoagueda added this to the 0.3.0 milestone 2026-09-09 10:36:55 +00:00
Author
Owner

Department sits between a company and the people in it: typed on the contact form, reused when the name already exists, cleared by emptying the box.

Deliberately not a company with a parent, though the relation from #55 was right there. A department has no website, no logo, no identifiers, no industries and no postings of its own; modelling it as a company would fill the companies list with things nobody applied to and teach every count to exclude them.

Both ends optional. A department deleted leaves its people where they work; a company deleted takes its departments. A contact cannot borrow another company's department, and saying so is a sentence rather than a silent correction. Fifteen tests.

Shipped in 74b353d on 0.3.0, with main kept level.

`Department` sits between a company and the people in it: typed on the contact form, reused when the name already exists, cleared by emptying the box. Deliberately not a company with a parent, though the relation from #55 was right there. A department has no website, no logo, no identifiers, no industries and no postings of its own; modelling it as a company would fill the companies list with things nobody applied to and teach every count to exclude them. Both ends optional. A department deleted leaves its people where they work; a company deleted takes its departments. A contact cannot borrow another company's department, and saying so is a sentence rather than a silent correction. Fifteen tests. Shipped in `74b353d` on `0.3.0`, with `main` kept level.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
Postulo/postulo#137
No description provided.