diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 18f93f3dc5e..9b86d1444f1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,7 @@ +# ⛔️ MAIN BRANCH WARNING! 2U EMPLOYEES must make branches against the 2u/main BRANCH + +- [ ] I have checked the branch to which I would like to merge. + # ⛔️ DEPRECATION WARNING **This repository is deprecated and in maintainence-only operation while we work on a replacement, please see [this announcement](https://discuss.openedx.org/t/deprecation-removal-ecommerce-service-depr-22/6839) for more information.** diff --git a/Dockerfile b/Dockerfile index 5eeb76fe686..8a06c2ad9b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,9 @@ FROM ubuntu:focal as app ENV DEBIAN_FRONTEND noninteractive # System requirements. RUN apt update && \ - apt-get install -qy \ + apt-get install -qy \ curl \ + gettext \ git \ language-pack-en \ build-essential \ diff --git a/Makefile b/Makefile index f12310e0016..ac03fab4661 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,13 @@ compile_translations: requirements.tox fake_translations: extract_translations dummy_translations compile_translations pull_translations: +ifeq ($(OPENEDX_ATLAS_PULL),) cd ecommerce && tx pull -a -f -t --mode reviewed +else + find ecommerce/conf/locale -mindepth 1 -maxdepth 1 -type d -exec rm -r {} \; + atlas pull $(OPENEDX_ATLAS_ARGS) translations/ecommerce/ecommerce/conf/locale:ecommerce/conf/locale + python manage.py compilemessages +endif push_translations: cd ecommerce && tx push -s diff --git a/README.rst b/README.rst index c9e3b80f814..0362f1987fb 100644 --- a/README.rst +++ b/README.rst @@ -30,9 +30,11 @@ The code in this repository is licensed under version 3 of the AGPL unless other How To Contribute ----------------- -Anyone merging to this repository is expected to `release and monitor their changes `__; if you are not able to do this DO NOT MERGE, please coordinate with someone who can to ensure that the changes are released. +Notice: Internal 2U contributions should be made against the ``2u/main`` branch. Open source contributions should continue to be made against the ``master`` branch. -Please also read `How To Contribute `__. +Anyone merging to the ``2u/main`` branch of this repository is expected to `release and monitor their changes `__ (2U-private link); if you are not able to do this DO NOT MERGE, please coordinate with someone who can to ensure that the changes are released. + +Please also read `How To Contribute `__. Even though it was written with ``edx-platform`` in mind, these guidelines should be followed for Open edX code in general. Reporting Security Issues ------------------------- diff --git a/db_keyword_overrides.yml b/db_keyword_overrides.yml index a7c5b1e9492..2be0cc06e43 100644 --- a/db_keyword_overrides.yml +++ b/db_keyword_overrides.yml @@ -13,5 +13,10 @@ MYSQL: - ShippingEvent.lines - PaymentEvent.lines - ProductAlert.key + - HistoricalOption.order + - Option.order SNOWFLAKE: + - HistoricalOption.order + - Option.order + STITCH: diff --git a/docs/decisions/0008-master-branch-split.rst b/docs/decisions/0008-master-branch-split.rst new file mode 100644 index 00000000000..8c8bcecc0d2 --- /dev/null +++ b/docs/decisions/0008-master-branch-split.rst @@ -0,0 +1,52 @@ +8. Master branch split from 2u/main +------------------------------------------------------------ + +Status +------ + +Accepted + +Context +------- + +Both 2U and the Open edX community use ecommerce's master branch for releases. Occasionally, changes +specific to 2U's business case are merged into code, which also influences the structure +of the code that the community runs, even if the changes are not relevant or beneficial +to the community at large. + +Additionally, 2U has internal compliance checks that can slow the release cycle of +major changes to ecommerce (for example, the upgrade to Django 4.2). This puts the Open edX community at risk of releasing +with deprecated packages. + +Decision +-------- + +A new protected branch will be created named "2u/main", which 2U will continue to use +as its own main branch, while leaving the "master" branch for use by the community. + +Consequences +------------ + +This allows the community to move forward with contributions on "master" without risk of +breaking functionality for 2U or 2U committing changes to "master" that are irrelevant or +otherwise inappropriate for the community's use case. + +Because protected branches in ecommerce require a user with Write access to the repository, +the "master" branch will now require someone from the community to review and manage +code contributions to that branch. + +Rejected Alternatives +--------------------- + +Repo fork +~~~~~~~~~ + +Why not fork the repo entirely? 2U and the community use a shared set of tools for +working in development environments. While working from separate branches and repo +forks are functionally equivalent, working in separate branches allows for +minimal updates to shared tooling to support this change. One can simply checkout a +branch name, without needing the tooling to be updated to know about non-openedx +git remotes. + +This is not a one way door, and if we decide later the a proper repo fork is a better +solution, then we are open to making adjustments. diff --git a/ecommerce/conf/locale/config.yaml b/ecommerce/conf/locale/config.yaml index 7467d5281e7..c65c70a84d2 100644 --- a/ecommerce/conf/locale/config.yaml +++ b/ecommerce/conf/locale/config.yaml @@ -92,5 +92,6 @@ ignore_dirs: - i18n - assets - node_modules + - tests - static/bower_components - static/build diff --git a/ecommerce/extensions/basket/migrations/0016_make_lineattribute_value_json_compatible.py b/ecommerce/extensions/basket/migrations/0016_make_lineattribute_value_json_compatible.py new file mode 100644 index 00000000000..f33922b9a44 --- /dev/null +++ b/ecommerce/extensions/basket/migrations/0016_make_lineattribute_value_json_compatible.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from django.core.paginator import Paginator +from django.db import migrations + + +def make_lineattribute_value_json_compatible(apps, schema_editor): + """ + Makes line attribute value json compatible. + """ + LineAttribute = apps.get_model("basket", "LineAttribute") + attributes = LineAttribute.objects.order_by('id') + paginator = Paginator(attributes, 1000) + + for page_number in paginator.page_range: + page = paginator.page(page_number) + updates = [] + + for obj in page.object_list: + obj.value = '"{}"'.format(obj.value) + updates.append(obj) + + LineAttribute.objects.bulk_update(updates, ['value']) + + +class Migration(migrations.Migration): + + dependencies = [ + ('basket', '0015_add_paymentintentid'), + ] + + operations = [ + migrations.RunPython(make_lineattribute_value_json_compatible, migrations.RunPython.noop), + ] diff --git a/ecommerce/extensions/basket/migrations/0017_alter_lineattribute_value.py b/ecommerce/extensions/basket/migrations/0017_alter_lineattribute_value.py new file mode 100644 index 00000000000..9f0683ae049 --- /dev/null +++ b/ecommerce/extensions/basket/migrations/0017_alter_lineattribute_value.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.20 on 2023-12-05 10:34 + +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('basket', '0016_make_lineattribute_value_json_compatible'), + ] + + operations = [ + migrations.AlterField( + model_name='lineattribute', + name='value', + field=models.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder, verbose_name='Value'), + ), + ] diff --git a/ecommerce/extensions/catalogue/migrations/0057_auto_20231205_1034.py b/ecommerce/extensions/catalogue/migrations/0057_auto_20231205_1034.py new file mode 100644 index 00000000000..3c25f70a8ec --- /dev/null +++ b/ecommerce/extensions/catalogue/migrations/0057_auto_20231205_1034.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.20 on 2023-12-05 10:34 + +from django.db import migrations, models +import django.db.models.deletion +import oscar.models.fields.slugfield + + +class Migration(migrations.Migration): + + dependencies = [ + ('catalogue', '0056_auto_20231108_1355'), + ] + + operations = [ + migrations.AlterModelOptions( + name='option', + options={'ordering': ['order', 'name'], 'verbose_name': 'Option', 'verbose_name_plural': 'Options'}, + ), + migrations.AddField( + model_name='historicaloption', + name='help_text', + field=models.CharField(blank=True, help_text='Help text shown to the user on the add to basket form', max_length=255, null=True, verbose_name='Help text'), + ), + migrations.AddField( + model_name='historicaloption', + name='option_group', + field=models.ForeignKey(blank=True, db_constraint=False, help_text='Select an option group if using type "Option" or "Multi Option"', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='catalogue.attributeoptiongroup', verbose_name='Option Group'), + ), + migrations.AddField( + model_name='historicaloption', + name='order', + field=models.IntegerField(blank=True, db_index=True, help_text='Controls the ordering of product options on product detail pages', null=True, verbose_name='Ordering'), + ), + migrations.AddField( + model_name='option', + name='help_text', + field=models.CharField(blank=True, help_text='Help text shown to the user on the add to basket form', max_length=255, null=True, verbose_name='Help text'), + ), + migrations.AddField( + model_name='option', + name='option_group', + field=models.ForeignKey(blank=True, help_text='Select an option group if using type "Option" or "Multi Option"', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_options', to='catalogue.attributeoptiongroup', verbose_name='Option Group'), + ), + migrations.AddField( + model_name='option', + name='order', + field=models.IntegerField(blank=True, db_index=True, help_text='Controls the ordering of product options on product detail pages', null=True, verbose_name='Ordering'), + ), + migrations.AlterField( + model_name='historicaloption', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('integer', 'Integer'), ('boolean', 'True / False'), ('float', 'Float'), ('date', 'Date'), ('select', 'Select'), ('radio', 'Radio'), ('multi_select', 'Multi select'), ('checkbox', 'Checkbox')], default='text', max_length=255, verbose_name='Type'), + ), + migrations.AlterField( + model_name='historicalproduct', + name='slug', + field=oscar.models.fields.slugfield.SlugField(allow_unicode=True, max_length=255, verbose_name='Slug'), + ), + migrations.AlterField( + model_name='option', + name='type', + field=models.CharField(choices=[('text', 'Text'), ('integer', 'Integer'), ('boolean', 'True / False'), ('float', 'Float'), ('date', 'Date'), ('select', 'Select'), ('radio', 'Radio'), ('multi_select', 'Multi select'), ('checkbox', 'Checkbox')], default='text', max_length=255, verbose_name='Type'), + ), + migrations.AlterField( + model_name='product', + name='slug', + field=oscar.models.fields.slugfield.SlugField(allow_unicode=True, max_length=255, verbose_name='Slug'), + ), + migrations.AlterUniqueTogether( + name='productattribute', + unique_together={('code', 'product_class')}, + ), + ] diff --git a/ecommerce/extensions/order/migrations/0027_alter_lineattribute_value.py b/ecommerce/extensions/order/migrations/0027_alter_lineattribute_value.py new file mode 100644 index 00000000000..4bd6caa08e0 --- /dev/null +++ b/ecommerce/extensions/order/migrations/0027_alter_lineattribute_value.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.20 on 2023-12-05 10:34 + +import django.core.serializers.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('order', '0026_auto_20231108_1355'), + ] + + operations = [ + migrations.AlterField( + model_name='lineattribute', + name='value', + field=models.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder, verbose_name='Value'), + ), + ] diff --git a/ecommerce/templates/oscar/dashboard/orders/order_detail.html b/ecommerce/templates/oscar/dashboard/orders/order_detail.html index 8c9e72ce6c1..af4d64b07c5 100644 --- a/ecommerce/templates/oscar/dashboard/orders/order_detail.html +++ b/ecommerce/templates/oscar/dashboard/orders/order_detail.html @@ -86,6 +86,11 @@

{% trans "Order Details" %}

{% trans "Order contents" %} +