MOBILE-2061 course: Don't sync completion if modified in the site
This commit is contained in:
		
							parent
							
								
									1c6618b42a
								
							
						
					
					
						commit
						83ef6467c8
					
				| @ -1113,6 +1113,7 @@ | |||||||
|   "core.course.overriddennotice": "grades", |   "core.course.overriddennotice": "grades", | ||||||
|   "core.course.sections": "moodle", |   "core.course.sections": "moodle", | ||||||
|   "core.course.useactivityonbrowser": "local_moodlemobileapp", |   "core.course.useactivityonbrowser": "local_moodlemobileapp", | ||||||
|  |   "core.course.warningmanualcompletionmodified": "local_moodlemobileapp", | ||||||
|   "core.course.warningofflinemanualcompletiondeleted": "local_moodlemobileapp", |   "core.course.warningofflinemanualcompletiondeleted": "local_moodlemobileapp", | ||||||
|   "core.coursedetails": "moodle", |   "core.coursedetails": "moodle", | ||||||
|   "core.courses.allowguests": "enrol_guest", |   "core.courses.allowguests": "enrol_guest", | ||||||
|  | |||||||
| @ -24,5 +24,6 @@ | |||||||
|     "refreshcourse": "Refresh course", |     "refreshcourse": "Refresh course", | ||||||
|     "sections": "Sections", |     "sections": "Sections", | ||||||
|     "useactivityonbrowser": "You can still use it using your device's web browser.", |     "useactivityonbrowser": "You can still use it using your device's web browser.", | ||||||
|  |     "warningmanualcompletionmodified": "The manual completion of an activity was modified on the site.", | ||||||
|     "warningofflinemanualcompletiondeleted": "Some offline manual completion of course '{{name}}' has been deleted. {{error}}" |     "warningofflinemanualcompletiondeleted": "Some offline manual completion of course '{{name}}' has been deleted. {{error}}" | ||||||
| } | } | ||||||
| @ -45,7 +45,7 @@ export class CoreCourseOfflineProvider { | |||||||
|                     type: 'TEXT' |                     type: 'TEXT' | ||||||
|                 }, |                 }, | ||||||
|                 { |                 { | ||||||
|                     name: 'timecreated', |                     name: 'timecompleted', | ||||||
|                     type: 'INTEGER' |                     type: 'INTEGER' | ||||||
|                 } |                 } | ||||||
|             ] |             ] | ||||||
| @ -131,7 +131,7 @@ export class CoreCourseOfflineProvider { | |||||||
|                 completed: completed, |                 completed: completed, | ||||||
|                 courseid: courseId, |                 courseid: courseId, | ||||||
|                 coursename: courseName || '', |                 coursename: courseName || '', | ||||||
|                 timecreated: Date.now() |                 timecompleted: Date.now() | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             return site.getDb().insertRecord(CoreCourseOfflineProvider.MANUAL_COMPLETION_TABLE, entry); |             return site.getDb().insertRecord(CoreCourseOfflineProvider.MANUAL_COMPLETION_TABLE, entry); | ||||||
|  | |||||||
| @ -121,9 +121,14 @@ export class CoreCourseProvider { | |||||||
|      * @param {number} courseId Course ID. |      * @param {number} courseId Course ID. | ||||||
|      * @param {string} [siteId] Site ID. If not defined, current site. |      * @param {string} [siteId] Site ID. If not defined, current site. | ||||||
|      * @param {number} [userId] User ID. If not defined, current user. |      * @param {number} [userId] User ID. If not defined, current user. | ||||||
|  |      * @param {boolean} [forceCache] True if it should return cached data. Has priority over ignoreCache. | ||||||
|  |      * @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down). | ||||||
|  |      * @param {boolean} [includeOffline=true] True if it should load offline data in the completion status. | ||||||
|      * @return {Promise<any>} Promise resolved with the completion statuses: object where the key is module ID. |      * @return {Promise<any>} Promise resolved with the completion statuses: object where the key is module ID. | ||||||
|      */ |      */ | ||||||
|     getActivitiesCompletionStatus(courseId: number, siteId?: string, userId?: number): Promise<any> { |     getActivitiesCompletionStatus(courseId: number, siteId?: string, userId?: number, forceCache: boolean = false, | ||||||
|  |             ignoreCache: boolean = false, includeOffline: boolean = true): Promise<any> { | ||||||
|  | 
 | ||||||
|         return this.sitesProvider.getSite(siteId).then((site) => { |         return this.sitesProvider.getSite(siteId).then((site) => { | ||||||
|             userId = userId || site.getUserId(); |             userId = userId || site.getUserId(); | ||||||
| 
 | 
 | ||||||
| @ -133,10 +138,17 @@ export class CoreCourseProvider { | |||||||
|                     courseid: courseId, |                     courseid: courseId, | ||||||
|                     userid: userId |                     userid: userId | ||||||
|                 }, |                 }, | ||||||
|                 preSets = { |                 preSets: CoreSiteWSPreSets = { | ||||||
|                     cacheKey: this.getActivitiesCompletionCacheKey(courseId, userId) |                     cacheKey: this.getActivitiesCompletionCacheKey(courseId, userId) | ||||||
|                 }; |                 }; | ||||||
| 
 | 
 | ||||||
|  |             if (forceCache) { | ||||||
|  |                 preSets.omitExpires = true; | ||||||
|  |             } else if (ignoreCache) { | ||||||
|  |                 preSets.getFromCache = false; | ||||||
|  |                 preSets.emergencyCache = false; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             return site.read('core_completion_get_activities_completion_status', params, preSets).then((data) => { |             return site.read('core_completion_get_activities_completion_status', params, preSets).then((data) => { | ||||||
|                 if (data && data.statuses) { |                 if (data && data.statuses) { | ||||||
|                     return this.utils.arrayToObject(data.statuses, 'cmid'); |                     return this.utils.arrayToObject(data.statuses, 'cmid'); | ||||||
| @ -144,6 +156,10 @@ export class CoreCourseProvider { | |||||||
| 
 | 
 | ||||||
|                 return Promise.reject(null); |                 return Promise.reject(null); | ||||||
|             }).then((completionStatus) => { |             }).then((completionStatus) => { | ||||||
|  |                 if (!includeOffline) { | ||||||
|  |                     return completionStatus; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 // Now get the offline completion (if any).
 |                 // Now get the offline completion (if any).
 | ||||||
|                 return this.courseOffline.getCourseManualCompletions(courseId, site.id).then((offlineCompletions) => { |                 return this.courseOffline.getCourseManualCompletions(courseId, site.id).then((offlineCompletions) => { | ||||||
|                     offlineCompletions.forEach((offlineCompletion) => { |                     offlineCompletions.forEach((offlineCompletion) => { | ||||||
| @ -686,42 +702,25 @@ export class CoreCourseProvider { | |||||||
| 
 | 
 | ||||||
|         siteId = siteId || this.sitesProvider.getCurrentSiteId(); |         siteId = siteId || this.sitesProvider.getCurrentSiteId(); | ||||||
| 
 | 
 | ||||||
|         // Convenience function to store a message to be synchronized later.
 |         // Convenience function to store a completion to be synchronized later.
 | ||||||
|         const storeOffline = (): Promise<any> => { |         const storeOffline = (): Promise<any> => { | ||||||
|             return this.courseOffline.markCompletedManually(cmId, completed, courseId, courseName, siteId); |             return this.courseOffline.markCompletedManually(cmId, completed, courseId, courseName, siteId); | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         // Check if we already have a completion stored.
 |         // The offline function requires a courseId and it could be missing because it's a calculated field.
 | ||||||
|         return this.courseOffline.getManualCompletion(cmId, siteId).catch(() => { |  | ||||||
|             // No completion stored.
 |  | ||||||
|         }).then((entry) => { |  | ||||||
| 
 |  | ||||||
|             if (entry && completed != entry.completed) { |  | ||||||
|                 // It has changed, this means that the offline data can be deleted because the action was undone.
 |  | ||||||
|                 return this.courseOffline.deleteManualCompletion(cmId, siteId).then(() => { |  | ||||||
|                     return { |  | ||||||
|                         status: true, |  | ||||||
|                         offline: true |  | ||||||
|                     }; |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|         if (!this.appProvider.isOnline() && courseId) { |         if (!this.appProvider.isOnline() && courseId) { | ||||||
|             // App is offline, store the action.
 |             // App is offline, store the action.
 | ||||||
|             return storeOffline(); |             return storeOffline(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // Try to send it to server.
 | ||||||
|         return this.markCompletedManuallyOnline(cmId, completed, siteId).then((result) => { |         return this.markCompletedManuallyOnline(cmId, completed, siteId).then((result) => { | ||||||
|             // Data sent to server, if there is some offline data delete it now.
 |             // Data sent to server, if there is some offline data delete it now.
 | ||||||
|                 if (entry) { |  | ||||||
|             return this.courseOffline.deleteManualCompletion(cmId, siteId).catch(() => { |             return this.courseOffline.deleteManualCompletion(cmId, siteId).catch(() => { | ||||||
|                 // Ignore errors, shouldn't happen.
 |                 // Ignore errors, shouldn't happen.
 | ||||||
|             }).then(() => { |             }).then(() => { | ||||||
|                 return result; |                 return result; | ||||||
|             }); |             }); | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 return result; |  | ||||||
|         }).catch((error) => { |         }).catch((error) => { | ||||||
|             if (this.utils.isWebServiceError(error) || !courseId) { |             if (this.utils.isWebServiceError(error) || !courseId) { | ||||||
|                 // The WebService has thrown an error, this means that responses cannot be submitted.
 |                 // The WebService has thrown an error, this means that responses cannot be submitted.
 | ||||||
| @ -731,7 +730,6 @@ export class CoreCourseProvider { | |||||||
|                 return storeOffline(); |                 return storeOffline(); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -128,10 +128,32 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { | |||||||
|                 return Promise.reject(null); |                 return Promise.reject(null); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  |             // Get the current completion status to check if any completion was modified in web.
 | ||||||
|  |             return this.courseProvider.getActivitiesCompletionStatus(courseId, siteId, undefined, false, true, false) | ||||||
|  |                     .then((onlineCompletions) => { | ||||||
|  | 
 | ||||||
|                 const promises = []; |                 const promises = []; | ||||||
| 
 | 
 | ||||||
|                 // Send all the completions.
 |                 // Send all the completions.
 | ||||||
|                 completions.forEach((entry) => { |                 completions.forEach((entry) => { | ||||||
|  |                     const onlineComp = onlineCompletions[entry.cmid]; | ||||||
|  | 
 | ||||||
|  |                     // Check if the completion was modified in online. If so, discard it.
 | ||||||
|  |                     if (onlineComp && onlineComp.timecompleted * 1000 > entry.timecompleted) { | ||||||
|  |                         promises.push(this.courseOffline.deleteManualCompletion(entry.cmid, siteId).then(() => { | ||||||
|  | 
 | ||||||
|  |                             // Completion deleted, add a warning if the completion status doesn't match.
 | ||||||
|  |                             if (onlineComp.state != entry.completed) { | ||||||
|  |                                 result.warnings.push(this.translate.instant('core.course.warningofflinemanualcompletiondeleted', { | ||||||
|  |                                     name: entry.coursename || courseId, | ||||||
|  |                                     error: this.translate.instant('core.course.warningmanualcompletionmodified') | ||||||
|  |                                 })); | ||||||
|  |                             } | ||||||
|  |                         })); | ||||||
|  | 
 | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|                     promises.push(this.courseProvider.markCompletedManuallyOnline(entry.cmid, entry.completed, siteId).then(() => { |                     promises.push(this.courseProvider.markCompletedManuallyOnline(entry.cmid, entry.completed, siteId).then(() => { | ||||||
|                         result.updated = true; |                         result.updated = true; | ||||||
| 
 | 
 | ||||||
| @ -142,7 +164,7 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { | |||||||
|                             result.updated = true; |                             result.updated = true; | ||||||
| 
 | 
 | ||||||
|                             return this.courseOffline.deleteManualCompletion(entry.cmid, siteId).then(() => { |                             return this.courseOffline.deleteManualCompletion(entry.cmid, siteId).then(() => { | ||||||
|                             // Responses deleted, add a warning.
 |                                 // Completion deleted, add a warning.
 | ||||||
|                                 result.warnings.push(this.translate.instant('core.course.warningofflinemanualcompletiondeleted', { |                                 result.warnings.push(this.translate.instant('core.course.warningofflinemanualcompletiondeleted', { | ||||||
|                                     name: entry.coursename || courseId, |                                     name: entry.coursename || courseId, | ||||||
|                                     error: this.textUtils.getErrorMessageFromError(error) |                                     error: this.textUtils.getErrorMessageFromError(error) | ||||||
| @ -156,6 +178,7 @@ export class CoreCourseSyncProvider extends CoreSyncBaseProvider { | |||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|                 return Promise.all(promises); |                 return Promise.all(promises); | ||||||
|  |             }); | ||||||
|         }).then(() => { |         }).then(() => { | ||||||
|             if (result.updated) { |             if (result.updated) { | ||||||
|                 // Update data.
 |                 // Update data.
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user