Skip to content

Instantly share code, notes, and snippets.

@hpainter
Last active August 29, 2015 14:26
Show Gist options
  • Save hpainter/3e4b90c24de86e6c957f to your computer and use it in GitHub Desktop.
Save hpainter/3e4b90c24de86e6c957f to your computer and use it in GitHub Desktop.
SM Company Users
## SM Company Users
### Requirements Summary
- All ScoopMonkey users must be affiliated with a valid FMCSA record through a ScoopMonkey Company record.
- An FMCSA record may have one and only one corresponding ScoopMonkey company record. The SmCompany record allows for user customization of FMCSA data (company name, address, etc) while still letting us maintain a clean copy of the FMCSA data.
- An SmCompany record will have one and only one user designated as it's 'Manager'. The managing user is responsible for billing and all company-related changes.
- Multiple users may belong to the same company, within quota limits defined by the managing user's subscription package.
- Users who wish to join a company that already exists in the ScoopMonkey system must request to be added by the company manager.
- Non-managing users do not get billed for a subscription, but they do inherit subscription permissions from the manager account.
- Users who are unaffiliated with a company (either because they were removed by the manager or because their join request is still pending) will not have full access until they join an SmCompany [^footnote]
- Users may switch to a new company at any time from their account profile page.
The implemention changes for these requirements are below.
[^footnote]: A discussed 7-day grace period can be implemented in a later stage, but supporting this now would require substantial changes to the way the app currently operates. Posting reviews, viewing the dashboard, and other features all depend on the existence of a valid SmCompany record that these users will not have. Further, allowing a grace period opens a wide avenue for abuse where a user can gain full unpaid site access by repeatedly requesting to join companies.
### Signup Flow
``` flow
st=>start: www.scoopmonkey.com
login_page=>subroutine: Login Page
signup_page=>subroutine: Signup Page
dashboard_page=>subroutine: Dashboard Page
unaffiliated_page=>subroutine: Affiliation Required Page
switch_page=>subroutine: Choose New Company Page
claim_check=>condition: FMCSA record has Users?
join_request=>condition: Request to to join company?
is_affiliated=>condition: User has a Company?
become_mgr=>operation: User becomes manager for SmCompany
create_request=>operation: Create new JoinRequest record
st->signup_page->claim_check
claim_check(no)->become_mgr->dashboard_page
claim_check(yes,right)->switch_page->join_request
join_request(no)->unaffiliated_page
join_request(yes,right)->create_request->unaffiliated_page
unaffiliated_page()->switch_page()->join_request
```
### User Login Flow
``` flow
st=>start: www.scoopmonkey.com
login_page=>subroutine: Login Page
signup_page=>subroutine: Signup Page
dashboard_page=>subroutine: Dashboard Page
unaffiliated_page=>subroutine: Affiliation Required Page
switch_page=>subroutine: Choose New Company Page
claim_check=>condition: FMCSA record has Users?
join_request=>condition: Request to to join company?
is_new_user=>condition: New User?
is_affiliated=>condition: User has a Company?
become_mgr=>operation: User becomes manager for SmCompany
create_request=>operation: Create new JoinRequest record
st->login_page->is_affiliated
is_affiliated(yes)->dashboard_page
is_affiliated(no)->unaffiliated_page
join_request(yes)->create_request->unaffiliated_page
join_request(no)->unaffiliated_page
unaffiliated_page->switch_page->join_request
```
### New Page: Choose New Company
**Routes:**
| Req Method | URL | Handler |
|-----------|----------------------------|------------------|
| GET,POST | /account/choose_company | account.choose_company() |
| POST | /company/add_user | company.add_user() |
| POST | /joinrequests/create | joinrequest.create() |
**Views:**
- /views/accounts/choose_company.html.php. View contains a self-posting search input, and displays a list of matching companies with either a 'Claim Company' button (for unclaimed companies) or a 'Submit Join Request' button (claimed companies).
**Notes:**
After switching, any SmCompany records that have no remaining users will still remain in place with any edits the user may have previously made.
### New Page: Company Affiliation Required
**Routes:**
| Req Method | URL | Handler |
|------------|----------------------------|------------------|
| GET | /account/unaffiliated | account.unaffiliated() |
**Views:**
/views/account/unaffiliated.html.php. Displayed for any request made by a user that has no current company affiliation. Contains only a description and a link to the 'Choose New Company' page.
### New Page: Manage Users
**Routes:**
| Req Method | URL | Handler |
|------------|----------------------------|------------------|
| GET | /account/managed_users | account.managed_users() |
| POST | /company/remove_user | company.remove_user() |
| POST | /joinrequests/(:id)/approve | joinrequests.approve($id) |
| POST | /joinrequests/(:id)/deny | joinrequests.deny($id) |
**Views:**
- /views/account/managed_users.html.php. Display index list of all users affiliated with the current user's company, along with a 'Remove' link for each. Page is restricted to access by company managers. If there are pending requests to join the company, they are displayed here.
- /views/joinrequests/_show.html.php. Partial to display individual join request, included by managed_users view. Contains 'Approve' and 'Deny' links that post to joinrequests controller.
### Updated Page: Account Profile
- Add 'Choose New Company' Link (All users)
- Add 'Manage Users' Link (Managers/Admins only)
- 'Edit Company Profile' Link (Managers/Admins only).
### New Model: JoinRequest
**Attributes:**
- id
- sm_user_id - requester
- sm_company_id - request recipient
- status - 'pending','approved','denied'
- create_date
- resolution_date
**Associations:**
SmCompany has_many JoinRequests
SmUser has_one JoinRequest
**Scaffolding:**
joinrequests.php - Only contains create(), approve() and deny() methods. Has just one view, a _show partial used by Manage Users page.
### Other Changes
- SmUser update to support 'non-paying' user types.
- SmCompany update to add 'manager' property.
- During Stripe updates, copy all data changes for managers to the other users in the same company.
- Store per-plan user account limits somewhere
- In API, ensure that addaccount() requests don't succeed for claimed companies.
- On login, add flash nag message if user is a manager and there are pending join requests.
### Edge Cases
There are a few edge case scenarios that this won't handle. I suggest dealing with them manually if they ever arise.
- If a manager switches companies, it will leave the other users for the old company abandoned. We have no process for automatically promoting another user to the manager role. This is especially tricky since the new manager will be responsible for billing.
- Absentee managers could become an issue (abandoned trials, active accounts that are rarely used, etc).
- Squatters are a risk. We don't know if a user is really the owner for a company, so a person could just block out the actual owner if they so choose.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment