<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 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