learning-credentials 0.2.0rc1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. learning_credentials/__init__.py +3 -0
  2. learning_credentials/admin.py +263 -0
  3. learning_credentials/apps.py +24 -0
  4. learning_credentials/compat.py +117 -0
  5. learning_credentials/exceptions.py +9 -0
  6. learning_credentials/generators.py +224 -0
  7. learning_credentials/migrations/0001_initial.py +205 -0
  8. learning_credentials/migrations/0002_migrate_to_learning_credentials.py +32 -0
  9. learning_credentials/migrations/0003_rename_certificates_to_credentials.py +128 -0
  10. learning_credentials/migrations/0004_replace_course_keys_with_learning_context_keys.py +59 -0
  11. learning_credentials/migrations/0005_rename_processors_and_generators.py +106 -0
  12. learning_credentials/migrations/__init__.py +0 -0
  13. learning_credentials/models.py +381 -0
  14. learning_credentials/processors.py +306 -0
  15. learning_credentials/settings/__init__.py +1 -0
  16. learning_credentials/settings/common.py +12 -0
  17. learning_credentials/settings/production.py +13 -0
  18. learning_credentials/tasks.py +53 -0
  19. learning_credentials/templates/learning_credentials/base.html +22 -0
  20. learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/body.html +22 -0
  21. learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/head.html +0 -0
  22. learning_credentials/urls.py +9 -0
  23. learning_credentials/views.py +1 -0
  24. learning_credentials-0.2.0rc1.dist-info/METADATA +204 -0
  25. learning_credentials-0.2.0rc1.dist-info/RECORD +34 -0
  26. learning_credentials-0.2.0rc1.dist-info/WHEEL +6 -0
  27. learning_credentials-0.2.0rc1.dist-info/entry_points.txt +3 -0
  28. learning_credentials-0.2.0rc1.dist-info/licenses/LICENSE.txt +664 -0
  29. learning_credentials-0.2.0rc1.dist-info/top_level.txt +2 -0
  30. openedx_certificates/__init__.py +1 -0
  31. openedx_certificates/apps.py +11 -0
  32. openedx_certificates/migrations/0001_initial.py +206 -0
  33. openedx_certificates/migrations/__init__.py +0 -0
  34. openedx_certificates/models.py +38 -0
@@ -0,0 +1,12 @@
1
+ """App-specific settings for all environments."""
2
+
3
+ from django.conf import Settings
4
+
5
+
6
+ def plugin_settings(settings: Settings):
7
+ """Add `django_celery_beat` to `INSTALLED_APPS`."""
8
+ if 'django_celery_beat' not in settings.INSTALLED_APPS:
9
+ settings.INSTALLED_APPS += ('django_celery_beat',)
10
+ # Temporary app to handle migrations.
11
+ if 'openedx_certificates' not in settings.INSTALLED_APPS:
12
+ settings.INSTALLED_APPS += ('openedx_certificates',)
@@ -0,0 +1,13 @@
1
+ """App-specific settings for production environments."""
2
+
3
+ from django.conf import Settings
4
+
5
+
6
+ def plugin_settings(settings: Settings):
7
+ """
8
+ Use the database scheduler for Celery Beat.
9
+
10
+ The default scheduler is celery.beat.PersistentScheduler, which stores the schedule in a local file. It does not
11
+ work in a multi-server environment, so we use the database scheduler instead.
12
+ """
13
+ settings.CELERYBEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
@@ -0,0 +1,53 @@
1
+ """Asynchronous Celery tasks."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+
7
+ from learning_credentials.compat import get_celery_app
8
+ from learning_credentials.models import CredentialConfiguration
9
+
10
+ app = get_celery_app()
11
+ log = logging.getLogger(__name__)
12
+
13
+
14
+ @app.task
15
+ def generate_credential_for_user_task(config_id: int, user_id: int):
16
+ """
17
+ Celery task for processing a single user's credential.
18
+
19
+ :param config_id: The ID of the CredentialConfiguration object to process.
20
+ :param user_id: The ID of the user to process the credential for.
21
+ """
22
+ config = CredentialConfiguration.objects.get(id=config_id)
23
+ config.generate_credential_for_user(user_id, generate_credential_for_user_task.request.id)
24
+
25
+
26
+ @app.task
27
+ def generate_credentials_for_config_task(config_id: int):
28
+ """
29
+ Celery task for processing a single context's credentials.
30
+
31
+ :param config_id: The ID of the CredentialConfiguration object to process.
32
+ """
33
+ config = CredentialConfiguration.objects.get(id=config_id)
34
+ user_ids = config.get_eligible_user_ids()
35
+ log.info("The following users are eligible in %s: %s", config.learning_context_key, user_ids)
36
+ filtered_user_ids = config.filter_out_user_ids_with_credentials(user_ids)
37
+ log.info("The filtered users eligible in %s: %s", config.learning_context_key, filtered_user_ids)
38
+
39
+ for user_id in filtered_user_ids:
40
+ generate_credential_for_user_task.delay(config_id, user_id)
41
+
42
+
43
+ @app.task
44
+ def generate_all_credentials_task():
45
+ """
46
+ Celery task for initiating the processing of credentials for all enabled contexts.
47
+
48
+ This function fetches all enabled CredentialConfiguration objects,
49
+ and initiates a separate Celery task for each of them.
50
+ """
51
+ config_ids = CredentialConfiguration.get_enabled_configurations().values_list('id', flat=True)
52
+ for config_id in config_ids:
53
+ generate_credentials_for_config_task.delay(config_id)
@@ -0,0 +1,22 @@
1
+
2
+ {% comment %}
3
+ As the developer of this package, don't place anything here if you can help it
4
+ since this allows developers to have interoperability between your template
5
+ structure and their own.
6
+
7
+ Example: Developer melding the 2SoD pattern to fit inside with another pattern::
8
+
9
+ {% extends "base.html" %}
10
+ {% load static %}
11
+
12
+ <!-- Their site uses old school block layout -->
13
+ {% block extra_js %}
14
+
15
+ <!-- Your package using 2SoD block layout -->
16
+ {% block javascript %}
17
+ <script src="{% static 'js/ninja.js' %}" type="text/javascript"></script>
18
+ {% endblock javascript %}
19
+
20
+ {% endblock extra_js %}
21
+ {% endcomment %}
22
+
@@ -0,0 +1,22 @@
1
+ {% load i18n %}{% autoescape off %}
2
+
3
+ <p>
4
+ {% blocktrans %}Thank you for your participation in {{ course_name }} at {{ platform_name }}!{% endblocktrans %}
5
+ </p>
6
+
7
+ <p>
8
+ {% blocktrans %}We are happy to inform you that you have earned a certificate. You should feel very proud of the work you have done in this course. We congratulate you on your efforts and your learning.{% endblocktrans %}
9
+ </p>
10
+
11
+ <p>
12
+ {% trans "To view and download your certificate, please click on the following link:" %}
13
+ </p>
14
+ <p><a href="{{ certificate_link }}">View and download your certificate</a></p>
15
+
16
+ <div>
17
+ <div>
18
+ {% blocktrans %}Thank you for choosing {{ platform_name }} for your learning journey. We look forward to seeing you in more courses in the future.{% endblocktrans %}
19
+ </div>
20
+ </div>
21
+
22
+ {% endautoescape %}
@@ -0,0 +1,9 @@
1
+ """URLs for learning_credentials."""
2
+
3
+ # from django.urls import re_path # noqa: ERA001, RUF100
4
+ # from django.views.generic import TemplateView # noqa: ERA001, RUF100
5
+
6
+ urlpatterns = [ # pragma: no cover
7
+ # TODO: Fill in URL patterns and views here.
8
+ # re_path(r'', TemplateView.as_view(template_name="learning_credentials/base.html")), # noqa: ERA001, RUF100
9
+ ]
@@ -0,0 +1 @@
1
+ """TODO."""
@@ -0,0 +1,204 @@
1
+ Metadata-Version: 2.4
2
+ Name: learning-credentials
3
+ Version: 0.2.0rc1
4
+ Summary: A pluggable service for preparing Open edX credentials.
5
+ Home-page: https://github.com/open-craft/learning-credentials
6
+ Author: OpenCraft
7
+ Author-email: help@opencraft.com
8
+ License: AGPL 3.0
9
+ Keywords: Python edx
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: Django
12
+ Classifier: Framework :: Django :: 4.2
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
15
+ Classifier: Natural Language :: English
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/x-rst
21
+ License-File: LICENSE.txt
22
+ Requires-Dist: celery
23
+ Requires-Dist: django
24
+ Requires-Dist: django-celery-beat
25
+ Requires-Dist: django-model-utils
26
+ Requires-Dist: django-object-actions
27
+ Requires-Dist: django_reverse_admin
28
+ Requires-Dist: djangorestframework
29
+ Requires-Dist: edx-opaque-keys
30
+ Requires-Dist: edx_ace
31
+ Requires-Dist: learning-paths-plugin==0.3.0rc1
32
+ Requires-Dist: openedx-completion-aggregator
33
+ Requires-Dist: pypdf
34
+ Requires-Dist: reportlab
35
+ Dynamic: author
36
+ Dynamic: author-email
37
+ Dynamic: classifier
38
+ Dynamic: description
39
+ Dynamic: description-content-type
40
+ Dynamic: home-page
41
+ Dynamic: keywords
42
+ Dynamic: license
43
+ Dynamic: license-file
44
+ Dynamic: requires-dist
45
+ Dynamic: requires-python
46
+ Dynamic: summary
47
+
48
+ learning-credentials
49
+ ####################
50
+
51
+ |pypi-badge| |ci-badge| |codecov-badge| |doc-badge| |pyversions-badge|
52
+ |license-badge| |status-badge| |visualization-badge|
53
+
54
+ Purpose
55
+ *******
56
+
57
+ A pluggable service for preparing Open edX credentials.
58
+
59
+ This is focused on the use cases of our client but designed to be a flexible foundation for any Open edX credential
60
+ needs. It natively supports generating PDF credentials, but can be extended to support other formats.
61
+
62
+ For the details about the purpose of this repository, please see the `the following ADR`_.
63
+
64
+ .. _the following ADR: https://learning-credentials.readthedocs.io/en/latest/decisions/0001-purpose-of-this-repo.html
65
+
66
+ Documentation
67
+ *************
68
+
69
+ Start by going through `the documentation`_.
70
+
71
+ .. _the documentation: https://learning-credentials.readthedocs.io/en/latest
72
+
73
+ Getting Help
74
+ ************
75
+
76
+ If you're having trouble, we have discussion forums at
77
+ https://discuss.openedx.org where you can connect with others in the
78
+ community.
79
+
80
+ Our real-time conversations are on Slack. You can request a `Slack
81
+ invitation`_, then join our `community Slack workspace`_.
82
+
83
+ For anything non-trivial, the best path is to open an issue in this
84
+ repository with as many details about the issue you are facing as you
85
+ can provide.
86
+
87
+ https://github.com/open-craft/learning-credentials/issues
88
+
89
+ For more information about these options, see the `Getting Help <https://openedx.org/getting-help>`__ page.
90
+
91
+ .. _Slack invitation: https://openedx.org/slack
92
+ .. _community Slack workspace: https://openedx.slack.com/
93
+
94
+ License
95
+ *******
96
+
97
+ The code in this repository is licensed under the AGPL 3.0 unless
98
+ otherwise noted.
99
+
100
+ Please see `LICENSE.txt <LICENSE.txt>`_ for details.
101
+
102
+ Contributing
103
+ ************
104
+
105
+ Contributions are very welcome.
106
+ Please read `How To Contribute <https://openedx.org/r/how-to-contribute>`_ for details.
107
+
108
+ This project is currently accepting all types of contributions, bug fixes,
109
+ security fixes, maintenance work, or new features. However, please make sure
110
+ to have a discussion about your new feature idea with the maintainers prior to
111
+ beginning development to maximize the chances of your change being accepted.
112
+ You can start a conversation by creating a new issue on this repo summarizing
113
+ your idea.
114
+
115
+ The Open edX Code of Conduct
116
+ ****************************
117
+
118
+ All community members are expected to follow the `Open edX Code of Conduct`_.
119
+
120
+ .. _Open edX Code of Conduct: https://openedx.org/code-of-conduct/
121
+
122
+ People
123
+ ******
124
+
125
+ .. TODO: Add the maintainers.
126
+
127
+ The assigned maintainers for this component and other project details may be
128
+ found in `Backstage`_. Backstage pulls this data from the ``catalog-info.yaml``
129
+ file in this repo.
130
+
131
+ .. _Backstage: https://backstage.openedx.org/catalog/default/component/learning-credentials
132
+
133
+ Reporting Security Issues
134
+ *************************
135
+
136
+ Please do not report security issues in public. Please email security@openedx.org.
137
+
138
+ .. |pypi-badge| image:: https://img.shields.io/pypi/v/learning-credentials.svg
139
+ :target: https://pypi.python.org/pypi/learning-credentials/
140
+ :alt: PyPI
141
+
142
+ .. |ci-badge| image:: https://github.com/open-craft/learning-credentials/workflows/Python%20CI/badge.svg?branch=main
143
+ :target: https://github.com/open-craft/learning-credentials/actions
144
+ :alt: CI
145
+
146
+ .. |codecov-badge| image:: https://codecov.io/github/open-craft/learning-credentials/coverage.svg?branch=main
147
+ :target: https://codecov.io/github/open-craft/learning-credentials?branch=main
148
+ :alt: Codecov
149
+
150
+ .. |doc-badge| image:: https://readthedocs.org/projects/learning-credentials/badge/?version=latest
151
+ :target: https://learning-credentials.readthedocs.io/en/latest
152
+ :alt: Documentation
153
+
154
+ .. |pyversions-badge| image:: https://img.shields.io/pypi/pyversions/learning-credentials.svg
155
+ :target: https://pypi.python.org/pypi/learning-credentials/
156
+ :alt: Supported Python versions
157
+
158
+ .. |license-badge| image:: https://img.shields.io/github/license/open-craft/learning-credentials.svg
159
+ :target: https://github.com/open-craft/learning-credentials/blob/main/LICENSE.txt
160
+ :alt: License
161
+
162
+ .. |status-badge| image:: https://img.shields.io/badge/Status-Experimental-yellow
163
+ :alt: Status
164
+
165
+ .. https://githubnext.com/projects/repo-visualization/
166
+ .. |visualization-badge| image:: https://img.shields.io/badge/Repo%20Visualization-8A2BE2
167
+ :target: https://mango-dune-07a8b7110.1.azurestaticapps.net/?repo=open-craft/learning-credentials
168
+ :alt: Visualization
169
+
170
+
171
+ Change Log
172
+ ##########
173
+
174
+ ..
175
+ All enhancements and patches to learning_credentials will be documented
176
+ in this file. It adheres to the structure of https://keepachangelog.com/ ,
177
+ but in reStructuredText instead of Markdown (for ease of incorporation into
178
+ Sphinx documentation and the PyPI description).
179
+
180
+ This project adheres to Semantic Versioning (https://semver.org/).
181
+
182
+ .. There should always be an "Unreleased" section for changes pending release.
183
+
184
+ Unreleased
185
+ **********
186
+
187
+ *
188
+
189
+ 0.2.0 – 2025-03-31
190
+ ******************
191
+
192
+ Added
193
+ =====
194
+
195
+ * Initial implementation of the certificates app.
196
+
197
+
198
+ 0.1.0 – 2025-01-29
199
+ ******************
200
+
201
+ Added
202
+ =====
203
+
204
+ * Initial implementation of the certificates app.
@@ -0,0 +1,34 @@
1
+ learning_credentials/__init__.py,sha256=VP6jLAbAcydui1q8-rUc2a3RBFNikScVyKa7zStUqCg,88
2
+ learning_credentials/admin.py,sha256=zES_NeA4yS3b0NcRIErA6nkX7xpphRzb_Dk1R_sfFKE,10293
3
+ learning_credentials/apps.py,sha256=AA6JYUyqKYvNJ5POtQKw_s1g1VrUXuQI96hbea9H220,761
4
+ learning_credentials/compat.py,sha256=3SE0CwWJHSNHlRMOm2NZd8zzIY3DKSBCRPBXi7QrWUY,4524
5
+ learning_credentials/exceptions.py,sha256=UaqBVXFMWR2Iob7_LMb3j4NNVmWQFAgLi_MNMRUvGsI,290
6
+ learning_credentials/generators.py,sha256=nktM3gDFv66BzXDJ8wjmjlIz9KWMmBPGlD93jS1WgcU,8821
7
+ learning_credentials/models.py,sha256=28IKCRKXXILRRLCIQxTMasSn7s1m2n8Jf-0euvw6T-A,16035
8
+ learning_credentials/processors.py,sha256=VoM7ybSSiC2kakNHep6PeZkWFE7FZeYdhdU97IOJ0vw,12466
9
+ learning_credentials/tasks.py,sha256=byoFEUvN_ayVaU5K5SlEiA7vu9BRPaSSmKnB9g5toec,1927
10
+ learning_credentials/urls.py,sha256=2YLZZW738D7Afyzq6hr5ajWIl6azmX-hNDGUg_8AFpE,370
11
+ learning_credentials/views.py,sha256=1iBgQYelVHO_QWtoUZfVeyUc0o89IxQWAIwjPjaYaBQ,12
12
+ learning_credentials/migrations/0001_initial.py,sha256=8ycj1lIoI1OG0Pzk3HdB6N94KLe78rUJh9KhqOxlxK4,8444
13
+ learning_credentials/migrations/0002_migrate_to_learning_credentials.py,sha256=B6csbk6yedautmkVwk4PL0k0Yyf9dak-kFFBKUytriw,2006
14
+ learning_credentials/migrations/0003_rename_certificates_to_credentials.py,sha256=YqSaHTB60VNc9k245um2GYVDH6J0l9BrN3ak6WKljjk,4677
15
+ learning_credentials/migrations/0004_replace_course_keys_with_learning_context_keys.py,sha256=5KaXvASl69qbEaHX5_Ty_3Dr7K4WV6p8VWOx72yJnTU,1919
16
+ learning_credentials/migrations/0005_rename_processors_and_generators.py,sha256=5UCqjq-CBJnRo1qBAoWs91ngyEuSMN8_tQtfzsuR5SI,5271
17
+ learning_credentials/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ learning_credentials/settings/__init__.py,sha256=tofc5eg3Q2lV13Ff_jjg1ggGgWpKYoeESkP1qxl3H_A,29
19
+ learning_credentials/settings/common.py,sha256=_-HsQFH39LoxivuZKGxdfGAxU9T0WR2Iep0E6sWqkqM,467
20
+ learning_credentials/settings/production.py,sha256=yEvsCldHOdsIswW7TPLW__b9YNEK-Qy05rX5WSAcEeo,484
21
+ learning_credentials/templates/learning_credentials/base.html,sha256=wtjBYqfHmOnyEY5tN3VGOmzYLsOD24MXdEUhTZ7OmwI,662
22
+ learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/body.html,sha256=o-tfFQSNf-tuu_YzPosm0SFxUXe9oPh17PyjdiVSBhQ,811
23
+ learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/head.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ learning_credentials-0.2.0rc1.dist-info/licenses/LICENSE.txt,sha256=GDpsPnW_1NKhPvZpZL9imz25P2nIpbwJPEhrlq4vPAU,34523
25
+ openedx_certificates/__init__.py,sha256=8OoQEjyyrcDZkrdGAWZ5TcmTJf7orJNJKo83-DFQRXo,85
26
+ openedx_certificates/apps.py,sha256=KZ27RPqxCM-DxBftfAsPrToprUh1yPVPQPBV3qgTJXo,287
27
+ openedx_certificates/models.py,sha256=O749LzwZr7O5js_21Ca_nUGJr-y3WJs__OrjBYXnZ-I,1131
28
+ openedx_certificates/migrations/0001_initial.py,sha256=8pN1xEEecBrXKIleuKbZ_FTlTMoOOGiC0Ibk0tDzriM,8522
29
+ openedx_certificates/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ learning_credentials-0.2.0rc1.dist-info/METADATA,sha256=vQv3xj4X8io3NFfQMDWx95iQu8jUfRpbPXUTVxTbH1U,6621
31
+ learning_credentials-0.2.0rc1.dist-info/WHEEL,sha256=MAQBAzGbXNI3bUmkDsiV_duv8i-gcdnLzw7cfUFwqhU,109
32
+ learning_credentials-0.2.0rc1.dist-info/entry_points.txt,sha256=Ll51HUyeZ2UnWjOXHSx09FPTFs9VMIwDccq-mn2wFEc,166
33
+ learning_credentials-0.2.0rc1.dist-info/top_level.txt,sha256=IC4tbU9MNfH-NkPgSUzE0UEurEMTpK3TJPHmeRf7kVQ,42
34
+ learning_credentials-0.2.0rc1.dist-info/RECORD,,
@@ -0,0 +1,6 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (78.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py2-none-any
5
+ Tag: py3-none-any
6
+
@@ -0,0 +1,3 @@
1
+ [lms.djangoapp]
2
+ learning_credentials = learning_credentials.apps:LearningCredentialsConfig
3
+ openedx_certificates = openedx_certificates.apps:OpenEdxCertificatesConfig