docs: def submit_completion(self, user, course_key, block_key, completion):
          """
          Update the completion value for the specified record.
  
          Parameters:
              * user (django.contrib.auth.models.User): The user for whom the
                completion is being submitted.
              * course_key (opaque_keys.edx.keys.CourseKey): The course in
                which the submitted block is found.
              * block_key (opaque_keys.edx.keys.UsageKey): The block that has had
                its completion changed.
              * completion (float in range [0.0, 1.0]): The fractional completion
                value of the block (0.0 = incomplete, 1.0 = complete).
  
          Return Value:
              (BlockCompletion, bool): A tuple comprising the created or updated
              BlockCompletion object and a boolean value indicating whether the
              object was newly created by this call.
  
          Raises:
  
              ValueError:
                  If the wrong type is passed for one of the parameters.
  
              django.core.exceptions.ValidationError:
                  If a float is passed that is not between 0.0 and 1.0.
  
              django.db.DatabaseError:
                  If there was a problem getting, creating, or updating the
                  BlockCompletion record in the database.
  
                  This will also be a more specific error, as described here:
                  https://docs.djangoproject.com/en/1.11/ref/exceptions/#database-exceptions.
                  IntegrityError and OperationalError are relatively common
                  subclasses.
          """
  
          # Raise ValueError to match normal django semantics for wrong type of field.
          if not isinstance(course_key, CourseKey):
              raise ValueError(
                  "course_key must be an instance of `opaque_keys.edx.keys.CourseKey`.  Got {}".format(type(course_key))
              )
          try:
              block_type = block_key.block_type
          except AttributeError:
              raise ValueError(
                  "block_key must be an instance of `opaque_keys.edx.keys.UsageKey`.  Got {}".format(type(block_key))
              )
          if waffle.waffle().is_enabled(waffle.ENABLE_COMPLETION_TRACKING):
              try:
                  with transaction.atomic():
                      obj, is_new = self.get_or_create(  # pylint: disable=unpacking-non-sequence
                          user=user,
                          course_key=course_key,
                          block_key=block_key,
                          defaults={
                              'completion': completion,
                              'block_type': block_type,
                          },
                      )
              except IntegrityError:
                  # The completion was created concurrently by another process
                  log.info(
                      "An IntegrityError was raised when trying to create a BlockCompletion for %s:%s:%s.  "
                      "Falling back to get().",
                      user,
                      course_key,
                      block_key,
                  )
                  obj = self.get(
                      user=user,
                      course_key=course_key,
                      block_key=block_key,
                  )
                  is_new = False
              if not is_new and obj.completion != completion:
                  obj.completion = completion
                  obj.full_clean()
                  obj.save(update_fields={'completion', 'modified'})
          else:
              # If the feature is not enabled, this method should not be called.
              # Error out with a RuntimeError.
              raise RuntimeError(
                  "BlockCompletion.objects.submit_completion should not be \
                  called when the feature is disabled."
              )
          return obj, is_new