# Implementing enterprise functionalities in OpenedX

**URL:** <https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332>\
**Category:** Site Operators\
**Tags:** how-to, tutor, enterprise\
**Created:** [January 28, 2026, 9:52am UTC](https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332 "2026-01-28T09:52:26Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jakubkl](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/jakubkl/32/9205_2.png) [@jakubkl](https://discuss.openedx.org/u/jakubkl)\
**Post date:** [January 28, 2026, 9:52am UTC](https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332/1 "2026-01-28T09:52:26Z")

</div>

Hello,

we are at the stage of implementing enterprise functionliaties. Our goals are:

- view only the courses relevant for a company’s member at the learner-dashboard

- automatically enroll users into the relevant courses based on their SSO choice or a slug found in the email (i.e. [firstnamelastname@comany.com](mailto:firstnamelastname@comany.com))

As an end result the user just logs in, is instantly at the learner-dashboard and has to press on the chosen course from the list to start learning.

We are using the teak release (tutor version 20.0.1).

As of now I have found

- edx-enterprise (which is part of the old pre-tutor devstack) [GitHub - openedx/edx-enterprise](https://github.com/openedx/edx-enterprise)

- course discovery on which edx-enterprise relies that is about to be discontinued [[DEPR]: Course Discovery Service · Issue #4449 · openedx/course-discovery · GitHub](https://github.com/openedx/course-discovery/issues/4449)

- enterprise-catalog that has some commits about deprecation as well [GitHub - openedx/enterprise-catalog: A Django-based microservice for handling Enterprise catalogs, associating enterprise customers with curated courses from the full course catalog.](https://github.com/openedx/enterprise-catalog)

Another promising looking project I found is [GitHub - openedx/frontend-app-learner-portal-enterprise: Enterprise Learner Portal](https://github.com/openedx/frontend-app-learner-portal-enterprise). After setting up CORS via plugins, modifying .env.development accordingly, ensuring ENABLE\_ENTERPRISE\_INTEGRATIONS is on and running _./manage.py lms seed\_enterprise\_devstack\_data_ in the lms container i do not get a log in page as stated in the README - instead i am being redirected to the learner dashboard immediately. The README mentions edx-enterprise, the old devstack and the lms container script partially failed cause it can’t find the catalog microservice - which once again is soon to be deprecated?

I am also aware that some Enterprise functionality is baked in by default into the Open edX image in the newer verisons. Via the Django admin panel I am able to successfully create an _Enterprise Customer_ and an _Enterprise Catalog Query_ however when I try to create an _Enterprise Customer Catalog_ (based on the two previously mentioned) with courses linked to that customer i get an error:

```auto
AttributeError at /admin/enterprise/enterprisecustomercatalog/add/

‘NoneType’ object has no attribute ‘username"‘

```

I am a bit confused - to me it seems like as if the Enterprise functionality is only partially available in the newer tutor versions of open edx and still not whole without some of the old devstack services somehow integrated with the tutor deployment.

If anyone’s been through a similar issue I would be very thankful for any tips on how to tackle this problem or help in achieving my goal (I’ve also considered Django signals yet I leave that as a last resort).

---

<div class="post-metadata">

**Author:** ![farhaanbukhsh](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/farhaanbukhsh/32/1503_2.png) [@farhaanbukhsh](https://discuss.openedx.org/u/farhaanbukhsh)\
**Post date:** [January 28, 2026, 10:35am UTC](https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332/2 "2026-01-28T10:35:19Z")

</div>

cc: @arunmozhi

---

<div class="post-metadata">

**Author:** ![arunmozhi](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/arunmozhi/32/3600_2.png) [@arunmozhi](https://discuss.openedx.org/u/arunmozhi)\
**Post date:** [January 29, 2026, 9:04am UTC](https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332/3 "2026-01-29T09:04:30Z")

</div>

Hi @jakubkl, the enterprise stack is a bit complex. It’s hard to pin point what could be going wrong without access to the system.

I am currently working on getting it functional for Ulmo here → [feat: upgrade to Ulmo by tecoholic · Pull Request #4 · open-craft/tutor-contrib-enterprisecatalog · GitHub](https://github.com/open-craft/tutor-contrib-enterprisecatalog/pull/4) and am in the final stages.

If you are interested, you can watch that PR for updates.

* * *

However, I would really recommend finding an alternate solution that doesn’t involve the enterprise stack if possible. As you have noted, multiple services are somewhere in the deprecation path and they are at the moment built primarily for the needs of [edx.org](http://edx.org) and can be best described as “source available”.

From your goals, I think the `openedx-filters` would be a great choice in the backend. It already has [hooks to modify the behaviour of the platform during user registration, login, enrollment ..etc.,](https://github.com/openedx/openedx-filters/blob/main/openedx_filters/learning/filters.py) and you can contribute new extension points to the platform, if they don’t meet your needs.

Similarly, you can modify the behaviour of the learner dashboard using the plugin slots in the MFE. For example, you can write a `wrap` plugin for the [Course List Slot](https://github.com/openedx/frontend-app-learner-dashboard/tree/master/src/plugin-slots/CourseListSlot) of the _learner dashboard_ that filters the courses visible to the learner based on the data from any source.

---

<div class="post-metadata">

**Author:** ![jakubkl](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/jakubkl/32/9205_2.png) [@jakubkl](https://discuss.openedx.org/u/jakubkl)\
**Post date:** [February 4, 2026, 11:15am UTC](https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332/4 "2026-02-04T11:15:05Z")

</div>

Hey @arunmozhi, thanks for the answer and leading me towards the right direction. I have managed to add the wanted functionality by doing the following (assuming courses are created with the proper organization assigned):

**Case A: User Logs In**

1. Using a filter _org.openedx.learning.student.login.requested.v1_ I run a pipeline that extracts the company’s slug from the user’s email field.
2. Grab all courses from the DB and filter out the ones that don’t match the user’s organization.
3. If user not yet enrolled in any of the courses from the filtered list then enroll the user  
_(that’s signing up handled, now for the showing part)_
4. Using another filter _org.openedx.learning.home.enrollment.api.rendered.v1_ I “stamp” all the courses by modifying the (hijacked) field ‘mode’ of the course to **some\_specific\_value**  
Then in the _learner-dashboard MFE_ I modified the CourseCard component (just a guard clause - 1 if statement) to now show the course only if it’s ‘mode’ field is set to that **some\_specific\_value**.

I really thought about using the plugin slot you recommended here however it implies using own components and I am fine with the existing one. If I wanted to use the plugin I’d therefore have to re-implement/flatten the entire _CourseCard_ logic into the plugin config to keep the original look and feel. Modifying it directly felt like a pragmatic choice at this point.  
—  
Unfortunately the log in filter is not called upon registration and the existing filter for registration _org.openedx.learning.student.registration.requested.v1_ happens before the user is saved to the database which makes it imposible to use it to register a user to a course.

I had **Case B: User Registers** solved by creating a basic post\_save signal that goes by the same logic. Both cases need to be handled since automatic registration would be required if a new course is rolled out to existing customers.

---

<div class="post-metadata">

**Author:** ![arunmozhi](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.openedx.org/arunmozhi/32/3600_2.png) [@arunmozhi](https://discuss.openedx.org/u/arunmozhi)\
**Post date:** [February 4, 2026, 12:08pm UTC](https://discuss.openedx.org/t/implementing-enterprise-functionalities-in-openedx/18332/5 "2026-02-04T12:08:29Z")

</div>

I am happy my comments were helpful and you have the functionality you wanted.

> [@jakubkl](#):
>
> If I wanted to use the plugin I’d therefore have to re-implement/flatten the entire _CourseCard_ logic into the plugin config to keep the original look and feel. Modifying it directly felt like a pragmatic choice at this point.

> [@jakubkl](#):
>
> Unfortunately the log in filter is not called upon registration and the existing filter for registration _org.openedx.learning.student.registration.requested.v1_ happens before the user is saved to the database which makes it impossible to use it to register a user to a course.

In both of these scenarios, if you think there adding an extension point the MFE and the platform would be helpful, I would highly recommend contributing them upstream. It could reduce the code-drift maintenance burden for you in the future upgrades and make it available for others who wish to customize their user flows.
