fccn / ecommerce-plugin-paygate Goto Github PK
View Code? Open in Web Editor NEWPayGate payment processor for Open edX Ecommerce used by NAU Ecommerce
License: GNU Affero General Public License v3.0
PayGate payment processor for Open edX Ecommerce used by NAU Ecommerce
License: GNU Affero General Public License v3.0
The AMA PPAP PayGate instance that we will use isn't registered on the DNS.
Or we add a custom configuration to docker-compose current installation and in future on the Kubernetes pod, or we change it using software (on python code).
https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/
We need to implement a Django command that recovers the failed success callbacks that the Paygate should have sent, but for one or another reason could deliver.
We already has an empty command:
https://github.com/fccn/ecommerce-plugin-paygate/blob/main/paygate/management/commands/failed_server_callbacks.py
This script then need to be executed at least daily by a cron based software.
Use Paygate web method /api/MarkTestPaymentAsPaid
to mark a transaction as payed.
This use case could be hidden using a setting. So we can hide it on PROD.
We have a django command that checks by date, the last transactions have been payed on Paygate.
To test more easy we should add it to the Django UI.
Error during logging a message on Paygate.
2024-01-25 09:02:58,103 INFO 11 [paygate.processors] /openedx/venv/lib/python3.8/site-packages/paygate/processors.py:531 - PayGate calling 'https://lab.optimistic.blue/paygateWS/api/CheckOut' with payload {'ACCESS_TOKEN': 'd031063d-5bee-44ec-b351-XXXXXX', 'MERCHANT_CODE': 'XXXX', 'IS_RECURRENT': False, 'CLIENT_NAME': 'XXXXX', 'EMAIL': '[email protected]', 'LANGUAGE': 'pt', 'PAYMENT_REF': 'OPENEDX-100029', 'TRANSACTION_DESC': "Seat in Ivo's Sandbox with verified certificate", 'CURRENCY': 'EUR', 'TOTAL_AMOUNT': Decimal('1.00'), 'PAYMENT_TYPES': ['VISA', 'MASTERCARD', 'PAYPAL', 'MBWAY', 'REFMB'], 'CALLBACK_SUCCESS_URL': 'https://ecommerce.dev.nau.fccn.pt/payment/paygate/callback/success/', 'CALLBACK_CANCEL_URL': 'https://ecommerce.dev.nau.fccn.pt/payment/paygate/callback/cancel/', 'CALLBACK_FAILURE_URL': 'https://ecommerce.dev.nau.fccn.pt/payment/paygate/callback/failure/', 'CALLBACK_SERVER_URL': 'https://ecommerce.dev.nau.fccn.pt/payment/paygate/callback/server/', 'CALLBACK_SERVER_PARMS': [{'key': 'course_id', 'value': 'course-v1:FCT+IVOSAND+2021_T2'}]}
--- Logging error ---
Traceback (most recent call last):
File "/usr/lib/python3.8/logging/__init__.py", line 1085, in emit
msg = self.format(record)
File "/usr/lib/python3.8/logging/__init__.py", line 929, in format
return fmt.format(record)
File "/usr/lib/python3.8/logging/__init__.py", line 668, in format
record.message = record.getMessage()
File "/usr/lib/python3.8/logging/__init__.py", line 373, in getMessage
msg = msg % self.args
TypeError: %d format: a number is required, not NoneType
Call stack:
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/wsgi.py", line 133, in __call__
response = self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 130, in get_response
response = self._middleware_chain(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/edx_django_utils/monitoring/internal/middleware.py", line 41, in __call__
response = self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/basket/middleware.py", line 61, in __call__
response = self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
response = response or self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/crum/__init__.py", line 97, in __call__
response = self.get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/openedx/ecommerce/./ecommerce/extensions/api/v2/views/checkout.py", line 60, in post
parameters = payment_processor.get_transaction_parameters(basket, request=request)
File "/openedx/venv/lib/python3.8/site-packages/paygate/processors.py", line 351, in get_transaction_parameters
logger.info(
Message: 'PayGate payment: basket=%d obtained paygate payment id=%d'
Arguments: (29, None)
2024-04-18T11:13:22.376487270+01:00 2024-04-18 10:13:22,374 ERROR 7 [ecommerce.extensions.checkout.mixins] /openedx/ecommerce/./ecommerce/extensions/checkout/mixins.py:321 - Order Failure: Paygate payment was received, but an order for basket [45] could not be placed.
2024-04-18T11:13:22.376537143+01:00 Traceback (most recent call last):
2024-04-18T11:13:22.376558610+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute
2024-04-18T11:13:22.376574957+01:00 return self.cursor.execute(query, args)
2024-04-18T11:13:22.376589596+01:00 File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 209, in execute
2024-04-18T11:13:22.376620542+01:00 res = self._query(query)
2024-04-18T11:13:22.376633159+01:00 File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 315, in _query
2024-04-18T11:13:22.376639972+01:00 db.query(q)
2024-04-18T11:13:22.376649166+01:00 File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/connections.py", line 239, in query
2024-04-18T11:13:22.376661779+01:00 _mysql.connection.query(self, query)
2024-04-18T11:13:22.376673976+01:00 MySQLdb._exceptions.OperationalError: (1048, "Column 'label' cannot be null")
2024-04-18T11:13:22.376690315+01:00
2024-04-18T11:13:22.376699505+01:00 During handling of the above exception, another exception occurred:
2024-04-18T11:13:22.376710545+01:00
2024-04-18T11:13:22.376729291+01:00 Traceback (most recent call last):
2024-04-18T11:13:22.376761235+01:00 File "/openedx/ecommerce/./ecommerce/extensions/checkout/mixins.py", line 71, in create_order
2024-04-18T11:13:22.376774498+01:00 order = self.handle_order_placement(
2024-04-18T11:13:22.376787734+01:00 File "/openedx/ecommerce/./ecommerce/extensions/checkout/mixins.py", line 182, in handle_order_placement
2024-04-18T11:13:22.376798741+01:00 order = self.place_order(
2024-04-18T11:13:22.376809527+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/checkout/mixins.py", line 150, in place_order
2024-04-18T11:13:22.376821181+01:00 self.save_payment_details(order)
2024-04-18T11:13:22.376832444+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/checkout/mixins.py", line 204, in save_payment_details
2024-04-18T11:13:22.376845964+01:00 self.save_payment_sources(order)
2024-04-18T11:13:22.376857564+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/checkout/mixins.py", line 230, in save_payment_sources
2024-04-18T11:13:22.376868414+01:00 source.save()
2024-04-18T11:13:22.376882573+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/payment/abstract_models.py", line 123, in save
2024-04-18T11:13:22.376894200+01:00 super().save(*args, **kwargs)
2024-04-18T11:13:22.376906546+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 739, in save
2024-04-18T11:13:22.376917350+01:00 self.save_base(using=using, force_insert=force_insert,
2024-04-18T11:13:22.376931316+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 776, in save_base
2024-04-18T11:13:22.376944180+01:00 updated = self._save_table(
2024-04-18T11:13:22.376957656+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 881, in _save_table
2024-04-18T11:13:22.376968780+01:00 results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
2024-04-18T11:13:22.376981892+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 919, in _do_insert
2024-04-18T11:13:22.376993379+01:00 return manager._insert(
2024-04-18T11:13:22.377003652+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
2024-04-18T11:13:22.377014795+01:00 return getattr(self.get_queryset(), name)(*args, **kwargs)
2024-04-18T11:13:22.377025995+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1270, in _insert
2024-04-18T11:13:22.377036019+01:00 return query.get_compiler(using=using).execute_sql(returning_fields)
2024-04-18T11:13:22.377049009+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
2024-04-18T11:13:22.377064889+01:00 cursor.execute(sql, params)
2024-04-18T11:13:22.377077278+01:00 File "/openedx/venv/lib/python3.8/site-packages/sentry_sdk/integrations/django/__init__.py", line 641, in execute
2024-04-18T11:13:22.377087738+01:00 result = real_execute(self, sql, params)
2024-04-18T11:13:22.377101174+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
2024-04-18T11:13:22.377111988+01:00 return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
2024-04-18T11:13:22.377122938+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
2024-04-18T11:13:22.377134282+01:00 return executor(sql, params, many, context)
2024-04-18T11:13:22.377154814+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
2024-04-18T11:13:22.377165498+01:00 return self.cursor.execute(sql, params)
2024-04-18T11:13:22.377177101+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 78, in execute
2024-04-18T11:13:22.377190357+01:00 raise IntegrityError(*tuple(e.args))
2024-04-18T11:13:22.377201683+01:00 django.db.utils.IntegrityError: (1048, "Column 'label' cannot be null")
2024-04-18T11:13:22.434425744+01:00 2024-04-18 10:13:22,429 ERROR 7 [paygate.views] /openedx/venv/lib/python3.8/site-packages/paygate/views.py:195 - PayGate server callback error while creating order for basket [45]
2024-04-18T11:13:22.434498387+01:00 Traceback (most recent call last):
2024-04-18T11:13:22.434516643+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute
2024-04-18T11:13:22.434530907+01:00 return self.cursor.execute(query, args)
2024-04-18T11:13:22.434543416+01:00 File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 209, in execute
2024-04-18T11:13:22.434561146+01:00 res = self._query(query)
2024-04-18T11:13:22.434573546+01:00 File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 315, in _query
2024-04-18T11:13:22.434585946+01:00 db.query(q)
2024-04-18T11:13:22.434598312+01:00 File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/connections.py", line 239, in query
2024-04-18T11:13:22.434892776+01:00 _mysql.connection.query(self, query)
2024-04-18T11:13:22.434906880+01:00 MySQLdb._exceptions.OperationalError: (1048, "Column 'label' cannot be null")
2024-04-18T11:13:22.434924056+01:00
2024-04-18T11:13:22.434936042+01:00 During handling of the above exception, another exception occurred:
2024-04-18T11:13:22.434950189+01:00
2024-04-18T11:13:22.434961569+01:00 Traceback (most recent call last):
2024-04-18T11:13:22.434973525+01:00 File "/openedx/venv/lib/python3.8/site-packages/paygate/views.py", line 193, in post
2024-04-18T11:13:22.434984955+01:00 order = self.create_order(request, basket)
2024-04-18T11:13:22.434996065+01:00 File "/openedx/ecommerce/./ecommerce/extensions/checkout/mixins.py", line 71, in create_order
2024-04-18T11:13:22.435007712+01:00 order = self.handle_order_placement(
2024-04-18T11:13:22.435018845+01:00 File "/openedx/ecommerce/./ecommerce/extensions/checkout/mixins.py", line 182, in handle_order_placement
2024-04-18T11:13:22.435030534+01:00 order = self.place_order(
2024-04-18T11:13:22.435041861+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/checkout/mixins.py", line 150, in place_order
2024-04-18T11:13:22.435052354+01:00 self.save_payment_details(order)
2024-04-18T11:13:22.435062324+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/checkout/mixins.py", line 204, in save_payment_details
2024-04-18T11:13:22.435076634+01:00 self.save_payment_sources(order)
2024-04-18T11:13:22.435087464+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/checkout/mixins.py", line 230, in save_payment_sources
2024-04-18T11:13:22.435098452+01:00 source.save()
2024-04-18T11:13:22.435109662+01:00 File "/openedx/venv/lib/python3.8/site-packages/oscar/apps/payment/abstract_models.py", line 123, in save
2024-04-18T11:13:22.435121814+01:00 super().save(*args, **kwargs)
2024-04-18T11:13:22.435132437+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 739, in save
2024-04-18T11:13:22.435143751+01:00 self.save_base(using=using, force_insert=force_insert,
2024-04-18T11:13:22.435158727+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 776, in save_base
2024-04-18T11:13:22.435170723+01:00 updated = self._save_table(
2024-04-18T11:13:22.435182603+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 881, in _save_table
2024-04-18T11:13:22.435196351+01:00 results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
2024-04-18T11:13:22.435208851+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 919, in _do_insert
2024-04-18T11:13:22.435224407+01:00 return manager._insert(
2024-04-18T11:13:22.435238366+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
2024-04-18T11:13:22.435251100+01:00 return getattr(self.get_queryset(), name)(*args, **kwargs)
2024-04-18T11:13:22.435262936+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1270, in _insert
2024-04-18T11:13:22.435273870+01:00 return query.get_compiler(using=using).execute_sql(returning_fields)
2024-04-18T11:13:22.435285866+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
2024-04-18T11:13:22.435296776+01:00 cursor.execute(sql, params)
2024-04-18T11:13:22.435308326+01:00 File "/openedx/venv/lib/python3.8/site-packages/sentry_sdk/integrations/django/__init__.py", line 641, in execute
2024-04-18T11:13:22.435318710+01:00 result = real_execute(self, sql, params)
2024-04-18T11:13:22.435329622+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
2024-04-18T11:13:22.435349189+01:00 return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
2024-04-18T11:13:22.435362809+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
2024-04-18T11:13:22.435375385+01:00 return executor(sql, params, many, context)
2024-04-18T11:13:22.435386589+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
2024-04-18T11:13:22.435397375+01:00 return self.cursor.execute(sql, params)
2024-04-18T11:13:22.435437078+01:00 File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 78, in execute
2024-04-18T11:13:22.435448511+01:00 raise IntegrityError(*tuple(e.args))
2024-04-18T11:13:22.435460064+01:00 django.db.utils.IntegrityError: (1048, "Column 'label' cannot be null")
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.