Code Monkey home page Code Monkey logo

avni-server's People

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

avni-server's Issues

Unknown error while syncing individuals from app to server. [Server side error handling]

Speculation: there is a bug in server API side and/or mobile app side.
There is no error logging in server side for tx data POST apis, at least for /individuals API. See : server code. So, we dont know what went wrong over there.
Also, the app side the response handler not reading the error message properly. See: mobile app code. Which should have been something like instance.message = response.message | response.body | response.data.message.
We need to fix both the sides to log and notify bugsnag with proper error message.

This unknown bug cannot be fixed immediately. Need to fix the error logging first.
relevant server log (Note: error happened after /Individuals? API)

2019-10-21 06:43:14.437  INFO 2093 --- [http-nio-8021-exec-3] o.o.f.security.AuthenticationFilter      : Processing POST /syncTelemetry?null User: .........
2019-10-21 06:43:14.446  INFO 2093 --- [http-nio-8021-exec-3] o.o.f.security.AuthenticationFilter      : Processed POST /syncTelemetry?null User: .........
2019-10-21 06:43:14.710  INFO 2093 --- [http-nio-8021-exec-13] o.o.f.security.AuthenticationFilter      : Processing POST /me?null User: .........
2019-10-21 06:43:14.729  INFO 2093 --- [http-nio-8021-exec-13] o.o.f.security.AuthenticationFilter      : Processed POST /me?null User: .........
2019-10-21 06:43:14.972  INFO 2093 --- [http-nio-8021-exec-10] o.o.f.security.AuthenticationFilter      : Processing POST /individuals?null User: .........
2019-10-21 06:43:15.823  INFO 2093 --- [http-nio-8021-exec-10] o.o.f.security.AuthenticationFilter      : Processed POST /individuals?null User: .........
2019-10-21 06:43:15.986  INFO 2093 --- [http-nio-8021-exec-8] o.o.f.security.AuthenticationFilter      : Processing POST /individuals?null User: .........
2019-10-21 06:43:16.255  INFO 2093 --- [http-nio-8021-exec-8] o.o.f.security.AuthenticationFilter      : Processed POST /individuals?null User: .........

relevant bugsnag log for client app

Error
/Users/vinay/code/sf/openchs-client/packages/openchs-android/src/service/ServerError.js:10

Oct 21st, 2019, 12:13:17 IST

STACKTRACE

Error
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/src/service/ServerError.js:10:4 ServerError
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/src/framework/http/requests.js:19:54 
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/promise/setimmediate/core.js:37:14 tryCallOne
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/promise/setimmediate/core.js:123:25 
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/Core/Timers/JSTimers.js:152:6 _callTimer
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/Core/Timers/JSTimers.js:200:17 _callImmediatesPass
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/Core/Timers/JSTimers.js:473:11 callImmediates
    [native code] callImmediates
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:337:11 value
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:135:11 
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:314:8 value
    /Users/vinay/code/sf/openchs-client/packages/openchs-android/node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:134:17 value
    [native code] value
    [native code] value

THREADS

Thread 2
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    ActivityThread.java:6762 android.app.ActivityThread.main
    Method.java:-2 java.lang.reflect.Method.invoke
    RuntimeInit.java:493 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run
    ZygoteInit.java:858 com.android.internal.os.ZygoteInit.main
Thread 2364
Thread 2365
Thread 2366
    Object.java:-2 java.lang.Object.wait
    Daemons.java:180 java.lang.Daemons$ReferenceQueueDaemon.runInternal
    Daemons.java:105 java.lang.Daemons$Daemon.run
    Thread.java:764 java.lang.Thread.run
Thread 2367
    Object.java:-2 java.lang.Object.wait
    Object.java:422 java.lang.Object.wait
    ReferenceQueue.java:188 java.lang.ref.ReferenceQueue.remove
    ReferenceQueue.java:209 java.lang.ref.ReferenceQueue.remove
    Daemons.java:234 java.lang.Daemons$FinalizerDaemon.runInternal
    Daemons.java:105 java.lang.Daemons$Daemon.run
    Thread.java:764 java.lang.Thread.run
Thread 2368
    Thread.java:-2 java.lang.Thread.sleep
    Thread.java:373 java.lang.Thread.sleep
    Thread.java:314 java.lang.Thread.sleep
    Daemons.java:344 java.lang.Daemons$FinalizerWatchdogDaemon.sleepFor
    Daemons.java:366 java.lang.Daemons$FinalizerWatchdogDaemon.waitForFinalization
    Daemons.java:283 java.lang.Daemons$FinalizerWatchdogDaemon.runInternal
    Daemons.java:105 java.lang.Daemons$Daemon.run
    Thread.java:764 java.lang.Thread.run
Thread 2369
Thread 2370
Thread 2371
Thread 2372
Thread 2374
Thread 2378
Thread 2380
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    HandlerThread.java:65 android.os.HandlerThread.run
Thread 2381
    Object.java:-2 java.lang.Object.wait
    Object.java:422 java.lang.Object.wait
    ReferenceQueue.java:188 java.lang.ref.ReferenceQueue.remove
    ReferenceQueue.java:209 java.lang.ref.ReferenceQueue.remove
    Unknown:4 com.facebook.jni.a$1.run
Thread 2382
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    AbstractQueuedSynchronizer.java:2101 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos
    LinkedBlockingQueue.java:467 java.util.concurrent.LinkedBlockingQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2383
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    HandlerThread.java:65 android.os.HandlerThread.run
Thread 2384
    Unknown:-2 com.facebook.react.bridge.queue.NativeRunnable.run
    Handler.java:873 android.os.Handler.handleCallback
    Handler.java:99 android.os.Handler.dispatchMessage
    Unknown com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage
    Looper.java:193 android.os.Looper.loop
    Unknown:37 com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run
    Thread.java:764 java.lang.Thread.run
Thread 2388
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:190 java.util.concurrent.locks.LockSupport.park
    AbstractQueuedSynchronizer.java:2059 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
    LinkedBlockingQueue.java:442 java.util.concurrent.LinkedBlockingQueue.take
    ThreadPoolExecutor.java:1092 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2389
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:190 java.util.concurrent.locks.LockSupport.park
    AbstractQueuedSynchronizer.java:2059 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
    LinkedBlockingQueue.java:442 java.util.concurrent.LinkedBlockingQueue.take
    ThreadPoolExecutor.java:1092 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2390
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:190 java.util.concurrent.locks.LockSupport.park
    AbstractQueuedSynchronizer.java:2059 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
    LinkedBlockingQueue.java:442 java.util.concurrent.LinkedBlockingQueue.take
    ThreadPoolExecutor.java:1092 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2391
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:190 java.util.concurrent.locks.LockSupport.park
    AbstractQueuedSynchronizer.java:2059 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
    LinkedBlockingQueue.java:442 java.util.concurrent.LinkedBlockingQueue.take
    ThreadPoolExecutor.java:1092 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2392
    LocalSocketImpl.java:-2 android.net.LocalSocketImpl.readba_native
    LocalSocketImpl.java:36 android.net.LocalSocketImpl.access$300
    LocalSocketImpl.java:110 android.net.LocalSocketImpl$SocketInputStream.read
    DpmTcmClient.java:144 com.qti.tcmclient.DpmTcmClient$TcmReceiver.run
    Thread.java:764 java.lang.Thread.run
Thread 2394
    Object.java:-2 java.lang.Object.wait
    ConnectionPool.java:103 com.android.okhttp.ConnectionPool$1.run
    ThreadPoolExecutor.java:1167 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2396
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    AbstractQueuedSynchronizer.java:2101 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos
    ArrayBlockingQueue.java:402 java.util.concurrent.ArrayBlockingQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    PG:2 hJ0.run
    Thread.java:764 java.lang.Thread.run
Thread 2399
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    HandlerThread.java:65 android.os.HandlerThread.run
Thread 2400
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    AbstractQueuedSynchronizer.java:2101 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos
    ArrayBlockingQueue.java:402 java.util.concurrent.ArrayBlockingQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    PG:2 hJ0.run
    Thread.java:764 java.lang.Thread.run
Thread 2401
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    HandlerThread.java:65 android.os.HandlerThread.run
Thread 2402
Thread 2403
Thread 2404
Thread 2405
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    HandlerThread.java:65 android.os.HandlerThread.run
Thread 2406
    MessageQueue.java:-2 android.os.MessageQueue.nativePollOnce
    MessageQueue.java:326 android.os.MessageQueue.next
    Looper.java:160 android.os.Looper.loop
    HandlerThread.java:65 android.os.HandlerThread.run
Thread 2408
Thread 2409
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    AbstractQueuedSynchronizer.java:2101 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos
    LinkedBlockingQueue.java:467 java.util.concurrent.LinkedBlockingQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2410
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    AbstractQueuedSynchronizer.java:2101 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos
    LinkedBlockingQueue.java:467 java.util.concurrent.LinkedBlockingQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2411
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    AbstractQueuedSynchronizer.java:2101 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos
    LinkedBlockingQueue.java:467 java.util.concurrent.LinkedBlockingQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2412
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    SynchronousQueue.java:461 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill
    SynchronousQueue.java:362 java.util.concurrent.SynchronousQueue$TransferStack.transfer
    SynchronousQueue.java:937 java.util.concurrent.SynchronousQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2413
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    SynchronousQueue.java:461 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill
    SynchronousQueue.java:362 java.util.concurrent.SynchronousQueue$TransferStack.transfer
    SynchronousQueue.java:937 java.util.concurrent.SynchronousQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2414
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    SynchronousQueue.java:461 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill
    SynchronousQueue.java:362 java.util.concurrent.SynchronousQueue$TransferStack.transfer
    SynchronousQueue.java:937 java.util.concurrent.SynchronousQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2415
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    SynchronousQueue.java:461 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill
    SynchronousQueue.java:362 java.util.concurrent.SynchronousQueue$TransferStack.transfer
    SynchronousQueue.java:937 java.util.concurrent.SynchronousQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2417
    NativeCrypto.java:-2 com.android.org.conscrypt.NativeCrypto.SSL_read
    NativeSsl.java:399 com.android.org.conscrypt.NativeSsl.read
    ConscryptFileDescriptorSocket.java:546 com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLInputStream.read
    Unknown:37 d.l$2.read
    Unknown:7 d.a$2.read
    Unknown:24 d.o.b
    Unknown d.o.a
    Unknown:5 okhttp3.internal.http2.Http2Reader.nextFrame
    Unknown:12 okhttp3.internal.http2.Http2Connection$ReaderRunnable.execute
    Unknown:17 okhttp3.internal.NamedRunnable.run
    Thread.java:764 java.lang.Thread.run
Thread 2418
    Object.java:-2 java.lang.Object.wait
    Unknown:37 okhttp3.ConnectionPool$1.run
    ThreadPoolExecutor.java:1167 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2419
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:190 java.util.concurrent.locks.LockSupport.park
    AbstractQueuedSynchronizer.java:2059 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await
    ScheduledThreadPoolExecutor.java:1120 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take
    ScheduledThreadPoolExecutor.java:849 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take
    ThreadPoolExecutor.java:1092 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run
Thread 2420
    Object.java:-2 java.lang.Object.wait
    Thread.java:2137 java.lang.Thread.parkFor$
    Unsafe.java:358 sun.misc.Unsafe.park
    LockSupport.java:230 java.util.concurrent.locks.LockSupport.parkNanos
    SynchronousQueue.java:461 java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill
    SynchronousQueue.java:362 java.util.concurrent.SynchronousQueue$TransferStack.transfer
    SynchronousQueue.java:937 java.util.concurrent.SynchronousQueue.poll
    ThreadPoolExecutor.java:1091 java.util.concurrent.ThreadPoolExecutor.getTask
    ThreadPoolExecutor.java:1152 java.util.concurrent.ThreadPoolExecutor.runWorker
    ThreadPoolExecutor.java:641 java.util.concurrent.ThreadPoolExecutor$Worker.run
    Thread.java:764 java.lang.Thread.run

Improve /search/concept API

We want to use it in UI Designer to allow user to choose a concept and answers. Current API do not return partial matches e.g. for text "Vita" you get no results.

API to GET operational modules

Desc:

This will be used for different use cases on a client

  1. Find out all operational programs
  2. Find out registration, enrolment, exit and encounter type forms for each program/subject type.
  3. Fetch related forms.

URL: /web/operationalModules
Access: user

Sample response:
{
  "programs": [
    {
      "operationalProgramName": "Eligible couple",
      "uuid": "fdf5c253-c49f-43e1-9591-4556a3ea36d4",
      "colour": "orangered",
      "programSubjectLabel": "Eligible couple",
      "name": "Eligible couple",
      "id": 4
    }
  ],
  "encounterTypes": [
    {
      "operationalEncounterTypeName": "Asha Inputs",
      "uuid": "7d38fd0e-94c5-48c1-9e3c-1719189cbea2",
      "name": "Asha Inputs",
      "id": 1
    }
  ],
  "subjectTypes": [
    {
      "operationalSubjectTypeName": "Individual",
      "uuid": "9f2af1f9-e150-4f8e-aad3-40bb7eb05aa3",
      "name": "Individual",
      "id": 1
    }
  ],
  "forms": [
    {
      "subjectTypeId": 1,
      "uuid": "56f03670-fd8c-4ea9-b82d-57b99df5c1ea",
      "encounterTypeId": 22,
      "programId": null,
      "formId": 21,
      "id": 35
    }
  ]
}
Testing:
# run the following and get the token
cd <workspace>/openchs-client
make get-token-staging username=xxx password=xxx
# copy the token and run the following
curl 'https://staging.openchs.org/web/operationalModules' -H "AUTH-TOKEN:  paste-the-token-here"

API to retrieve individual

Add new API to retrieve all details of an individual. This includes

  • everything in individual
  • everything in enrolment
  • encounter date times and types, and names

Encounters can be a lot, hence we will not fetch all of them.
Observations will be fetched as is, and the client can figure out how to show them by calling the /form fetch API.

This will be a separate API, unrelated to the existing individual GET.
This url will have a prefix of /web. In this case, it will be /web/individual/{uuid}
Restricted for "user" role.

New API to create Locations by uploading CSV file

We will ask user to upload file with single hierarchy.
File header will have location types. e.g. if hierarchy is PHC -> Subcenter -> Village then the file header will be PHC, Subcenter, Village.

Examples of different hierarchies:

PHC -> Subcenter -> Village https://docs.google.com/spreadsheets/d/1klWTBj_cVLuc80sIRPYcpZllxVuea0o4GEO3v5C9o0s/edit#gid=35219761

PHC -> Slum
https://docs.google.com/spreadsheets/d/1klWTBj_cVLuc80sIRPYcpZllxVuea0o4GEO3v5C9o0s/edit#gid=487758300

School
https://docs.google.com/spreadsheets/d/1klWTBj_cVLuc80sIRPYcpZllxVuea0o4GEO3v5C9o0s/edit#gid=1811103748

#Testing:

cd openchs-client
make get-token-staging username=ck-admin password=xxxx
#cop the token
curl -X POST -F 'file=@/tmp/sampel.csv' 'https://staging.openchs.org/import?type=locations' -H "AUTH-TOKEN: put_the_token_here"
#where the /tmp/sample.csv file is simillar to one of the examples above
#then login as CK-admin on staging webapp and you should see the locations there
Acceptance Criteria -
  1. It should accept the file only if that is in the format.
  2. It should provide the errors if the file failed to upload. - Failed
  3. It should give the progress/status of the file upload.
  4. It should take the locations and update the list of locations.
  5. If Empty table is uploaded, it shows 0 rows done.

DB performance issue on locations sync (Sickle Cell)

Right now when we do the first time sync of Sickle Cell, the server takes long time to respond and also CPU spikes up leading to a choke up.

We have to see how can we improve the performance.
Query on ltree could be a way to fix it.

Import/Export translation file to server (Spike)

  • Allow admin/org-admin to import or export translation file into server.
  • In server translations will be stored per organization basis on translation table.
  • Code is pushed in branch translation-import-export.

Below are some bench-marking results

ab -n 10 -c 1 http://localhost:8021/translationExport?fileName=translajj.json

Document Path:          /translationExport?fileName=translajj.json
Document Length:        472648 bytes

Concurrency Level:      1
Time taken for tests:   0.925 seconds
Complete requests:      10
Failed requests:        0
Total transferred:      4730010 bytes
HTML transferred:       4726480 bytes
Requests per second:    10.81 [#/sec] (mean)
Time per request:       92.483 [ms] (mean)
Time per request:       92.483 [ms] (mean, across all concurrent requests)
Transfer rate:          4994.60 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    38   92  99.3     69     372
Waiting:       33   81  96.5     57     353
Total:         38   92  99.3     69     372

Percentage of the requests served within a certain time (ms)
  50%     69
  66%     72
  75%     78
  80%     80
  90%    372
  95%    372
  98%    372
  99%    372
 100%    372 (longest request)

ab -n 100 -c 10 http://localhost:8021/translationExport?fileName=translajj.json

Document Path:          /translationExport?fileName=translajj.json
Document Length:        472648 bytes

Concurrency Level:      10
Time taken for tests:   2.080 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      47300100 bytes
HTML transferred:       47264800 bytes
Requests per second:    48.09 [#/sec] (mean)
Time per request:       207.951 [ms] (mean)
Time per request:       20.795 [ms] (mean, across all concurrent requests)
Transfer rate:          22212.74 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.7      0       7
Processing:    78  203  56.9    201     367
Waiting:       70  163  47.5    167     313
Total:         78  203  56.9    201     367

Percentage of the requests served within a certain time (ms)
  50%    201
  66%    222
  75%    243
  80%    247
  90%    283
  95%    301
  98%    351
  99%    367
 100%    367 (longest request)

API to export flattened encounter data

  • API will receive encounter type uuid, start date and end date as it params.

  • API will return a spreadsheet containing all the encounter data between these dates.

  • Format
    Header

    • Header will comprise of registration, enrolment, encounters in chronological order
    • E.g. Registration fields | Enrolment fields | Encounter 1 fields starting with encounter 1 date | Encounter 2 fields starting with encounter 2 date ... so on
    • For each field the header would be like
      Non coded : <Encounter_type_name>
      Coded: Multiselect :
      <Encounter_type_name><Concept_answer>
      Coded: SingleSelect :
      <Encounter_type_name>
      Values
    • For coded multiselect if it is selected it will have 1 as its value or else 0.
    • For coded SingleSelect value will be conceptAnswer.
    • For concept of any other type except coded, get it's it's actual field value.
  • Data will contain program exit observations if any.

  • Data will contain visit cancel observations if any.

  • For multiple enrolments (e.g if an individual exists and then rejoins) each enrolment details will a separate row.

Test Cases -
  • Based on Job completion status, file export option should come.
  • If Job is completed, show download button.
  • If job is failed, do not show the download button.

Check for multiple usages of same concept before creating a Form

Right now, in openchs forms one cannot have multiple form-elements tied to same concept. If someone uses same concept twice by mistake it will lead to data loss. Observation captured by one of the form element will be overwritten by other form element.

To prevent this forms api can have validation check before creation.

Form fetch api

Fetch a form by uuid

This will be used for the individual dashboard and filling of forms.

Fetch will contain details of concepts as well.

url: /api/form/uuid

Bulkupload API implementation for users and catchments

As an API client I should be able to create users through an users import API.
As an API client I should be able to create catchments through same API per user.
As an API client I should be able to assign users to catchments through the same API.

Locations should already be there in the system.

Create catchments, users, catchment address mapping, and user catchment mapping.

Input file format: *.csv

Location with full hierarchy Catchment Name Username Full Name of User Email Phone Language Track Location
PHC B, Sub B, Vil B A user28@ak user28 [email protected] +919876543210 English yes
PHC B, Sub B, Vil C A user28@ak
PHC B, Sub C, Vil C A user28@ak
PHC B, Sub B, Vil C B user48@ak user48 [email protected] +919876543210 English yes
PHC B, Sub C, Vil C B user48@ak
PHC C, Sub C, Vil C B user48@ak
PHC B, Sub C, Vil C C user68@ak user68 [email protected] +919876543210 English no
PHC C, Sub C, Vil C C user68@ak
Language
English
Hindi
Marathi
Gujarati
Bengali
Telugu
Tamil
Kannada
Odia
Malayalam
Punjabi
Sanskrit
Urdu

If same user assigned to multiple locations then need not to repeat the userinfo.

Example file format https://docs.google.com/spreadsheets/d/1klWTBj_cVLuc80sIRPYcpZllxVuea0o4GEO3v5C9o0s/edit#gid=1887642239

Test Cases -

`TransactionalResourceInterceptor.getCatchmentId` fails with `java.lang.NullPointerException`

Speculation: Auth failure
When a JWToken expires or any other auth failure happens, there is an empty UserContext. TransactionalResourceInterceptor.getCatchmentId is not null proof. Fix it.

Also, check if AuthService/CognitoAuthServiceImpl errors are reported to bugsnag properly

Stacktrace:

java.lang.NullPointerException        at org.openchs.framework.sync.TransactionalResourceInterceptor.getCatchmentId(TransactionalResourceInterceptor.java:58)
        at org.openchs.framework.sync.TransactionalResourceInterceptor.preHandle(TransactionalResourceInterceptor.java:38)
        at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:136)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:986)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.openchs.framework.sync.MutableRequestFilter.doFilter(MutableRequestFilter.java:20)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.openchs.framework.security.AuthenticationFilter.doFilterInternal(AuthenticationFilter.java:47)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:677)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

[Bug] Sync failing on Sewa Rural users

Pinal from Sewa Rural reported today that Sync is failing on her and jyotsnam tablet. By looking at the server logs I found that it is failing in posting videotelemetrics. Below is the exception thrown:
2019-07-10 03:57:21.609 ERROR 4013 --- [http-nio-8021-exec-6] org.openchs.web.ErrorInterceptors : result returns more than one elements; nested exception is javax.persistence.NonUniqueResultException: result returns more than one elements

org.springframework.dao.IncorrectResultSizeDataAccessException: result returns more than one elements; nested exception is javax.persistence.NonUniqueResultException: result returns more than one elements.

Found out that this was happening because of wrong deployment of video table. It had two duplicate records with same uuid. I have deleted one so the sync will work now. Will add a constraint on the table to prevent this in future.

Server side support for form element skip logic

Notes:

Right now we will create one generic rules table but we will create only one mapping table form_element_rule. We will add tables and apis for other kind of rules in other stories.

Database changes:

Add a table named rule_object with columns:
id::serial, uuid::varchar, code::text, rule_name::varchar, rule_type::varchar, organisation_id::integer, audit_id::integer

Add a table named form_element_rule with columns:
id::serial, form_element_id::integer, rule_object_id::integer, execution_order::integer, organisation_id::integer, audit_id::integer.

Add foreign key relationships from form_element_rule.form_element_id to form_elment.id and form_element_rule.rule_ojbect_id to rule_object.id

To create these tables create a migration sql file in openchs-server/db/migration directory. Look at db/migration/V1_99__CreateIdentifierTables.sql for an example of how to write migration and what are the standard data types that we use. Migration file should bump up the version number in file name from last migration.

Code Changes:

Add ORM model classes for RuleObject and FormElementRule. Look at classes in /openchs-server/openchs-server-api/src/main/java/org/openchs/domain for examples.
Add repositories for these classes. Look at FormElementRepository for an example.

API Changes:

Modify POST /forms api contract to include rule code string with each form element. The API should create an entry in rules table and form_element_rule table if entries are not present already.

In rules table set the values as following:

  • rule_name = form element name.
  • rule_type = FormElementSkipLogic

In form_element_rule table set the values as following:

  • execution_order: set to 1 for now.

If there already is an entry in rules table then it should update the value of code column.

Use models and repositories defined in Code Changes part.

Architecture notes:

Execution order is required mostly for decisions right now, i.e. you want to add a decision depending on previous decision.

POST and PUT /forms api for creating new form

Add/Modify apis

Tasks:

  • PUT

    • Update an existing form
      • Update form data e.g. groups and elements
      • return error if form of same name already exists.
      • Update form mapping
        • If mappings other than passed parameter exists then void those.
  • POST

    • Create new form
      • return error if form of same name already exists.
      • Create form mapping
    • Url: /web/forms
    • Parameters
      • formType(string)
      • name(string)
      • subjectType(string
      • programName(string)
      • encounterTypes(list of strings)
    • Response

{
"id": 75,
"uuid": "d79e9e80-abfe-4761-8da6-0f57a55f2183",
"version": 0,
"organisationId": 3,
"formType": "ProgramEncounter",
"name": "PNC Visit 10",
"formElementGroups": [],
"auditId": 4276,
"lastModifiedDateTime": 1565610991489,
"voided": false
}

Search API

As a user, I should be able to search beneficiaries using a search term and preferred sorts.

Search - Must search across individual properties (name, observations) and enrolment observations
Sort - On name, gender, date of birth, location
Filter - Enrolled programs, date of birth range (we may introduce this in future depending on requirement)

Search results must be paginated.
Search must take place only for an individual's catchment and not outside.

Testing notes:

$ cd <workspace>/openchs-client
$ make get-token-staging username=xxxx password=xxxx
## copy the token to /tmp/token
$ curl -o- https://staging.openchs.org/individual/search?size=5\&page=0\&name\=test -H "AUTH-TOKEN: $(cat /tmp/token)"

Some POST requests do not update last_updated_date_time

We know that form_element name change and form_element_group name change does not change the last_updated_date_time. We do not know of others yet.

  1. Identify which POST requests have this problem.
  2. Find out root cause and fix.
  3. Verify GET performance is not affected by fix
  4. Analyse and fix if there are data fixes required on server to fix the problem.

API to get the status of export job

  • Get all the request params used to submit the job.
  • Job status, fileName and job completion dateTime.

Test Cases -

  • When clicking on the Generate report, the status table gets updated automatically.
  • When the job fails, the table gets updated with the status "Failed".
  • When user clicks on "generate report" for program encounter, it should take all the enrolments in the program during that time period and show the data of encounter if available.

[Bugsnag] Send API url along with the error

In Bugsnag sometimes we get error messages with no clear cause. We can add Web request details to the error log, so we can guess where could be the problem.

It should have the 'API url called', 'useruuid' and 'username' if known.

Relevant code: org.openchs.web.ErrorInterceptors

Model and API for privileges

The purpose of this story is to create the models and necessary API for access control so that necessary features can be added to avni-client and avni-webapp.

Untitled (3).png

Acceptance Criteria

  • ** Models **

    • Add necessary models as provided in the diagram
    • Add necessary audit fields to all tables
    • Add organisation level RLS validations for user_group and group_privilege tables (view and edit allowed only at specific organisation level, not higher or lower levels)
  • ** Reference Data **

    • Add the following privileges

View subject
Register subject
Edit subject
Void subject
Enrol subject
View enrolment details
Edit enrolment details
Exit enrolment
View visit
Schedule visit
Perform visit
Edit visit
Cancel visit
View checklist
Edit checklist

  • Create a group called Everyone in each organisation, with all the above privileges added to every user.

  • Keep this migration running everytime (this will be removed later, but until then it will be useful if the privilege is added every time

  • ** Changes to existing sync API **

    • individualRelationship - based on subject_type_uuid
    • checklistItem - based on checklist_detail
    • checklist - based on checklist_detail
    • encounter - based on encounter_type_uuid
    • programEncounter - based on encounter_type_uuid
    • programEnrolment - based on program_uuid
    • individual - based on subject_type_uuid
  • ** New sync API **

    • /group - provides list of all groups (sync style, based on audit)
    • /group_privilege - provides list of all privileges for a group (sync style, based on audit)
    • /my_groups - provides a list of all groups this user has access to (sync style, based on audit)

Add support for rules written via UI Designer

Add decision_rule, validation_rule, visit_schedule_rule columns on form table.
Add enrolment_summary_rule, checklists_rule, enrolment_eligibility_check_rule columns on program table.
Add encounter_eligibility_check_rule column on encounter table.

[Access Control - 2] Sync API changes for access control

The client will now start retrieving data at a more granular level based on the permissions available to users. In order to achieve this, we need the sync API for transactional data to sync based on specific fields. The API will provide details of what needs to be synced. Here are the specific changes required.

  • Individual - based on subject_type_uuid (Add Subject type to sync GET url)

  • Program Encounter - based on encounter_type_uuid

  • Encounter - based on encounter_type_uuid

  • Program Enrolment - based on program_uuid

  • Checklist - based on program_uuid

  • IndividualRelationship - based on subject_type_uuid of both relationships

  • Add indices to the db if required for queries that retrieve data

  • Ensure that the previous API is preserved. This will be required for backward compatibility

  • Other sync API will remain as-is.

Support for meta db users

We are seeing instances where there are organisations that work with other partner organisations in order to implement a program. These meta organisations will need access to all data of their partner organisations. It is also possible that there are other combinations/hierarchies involved.

Solution
Keep it loose. Have the ability to create db users that can query across organisations. This will allow us to create any combination of organisation levels.

Tasks

  • Create a new table (db_user_organisation_access) with columns db_user, organisation_id, description, read, write. Unique key db_user+organisation_id
  • Change all RLS policies to use this information.
  • Change create_db_user function to insert data into db_user_organisation_access
  • Add migrations for existing organisations
  • Test reports to ensure it works fine
  • Test sync
  • Ensure all existing implementations use create_db_user function. If not, replace.

Why are we validating whether concept answer exists in concept when saving an individual

Right now in individuals sync if the concept answer in observations coming from client is not found inside a concept then we fail the sync and log error java.lang.IllegalArgumentException: Concept answer '3bdb940c-77f5-4a2d-bb15-da4d609970b8' not found in Concept '23d3c16d-da21-4a84-8158-938ad7e104c3'.
Fix this as this breaks sync for users for no fault of theirs.

Enrolment fetch api

This is a fetch of enrolment information and all encounters of that enrolment.

Only enrolment will have observations. Encounter's observations to be fetched separately per encounter.

Url
/web/programEnrolment/{uuid}

Testing:

  • run
make get-token-staging username=xxx password=xxx
  • copy the token
curl 'https://staging.openchs.org/web/programEnrolment/abcdef-some-uuid-here-xesf' \
  -H 'AUTH-TOKEN:   paste-token-here'
  • it should give a json simillar to the following
{
  "uuid": "e5c336b6-c355-4c56-93c2-f493ddd88841",
  "observations": [      // similar to subjectprofile api response's observations field
     {
        "concept": { "uuid": "d883d5fe-e17d-4136-b989-089fa0295e34", "name": "Height" },
        "value": 145
     },
     .....
  },
  "program": {
    "operationalProgramName": "Pregnancy",
    "uuid": "076ddb2d-a499-4314-af95-4178553d279b",
    "colour": "darkmagenta",
    "name": "Mother",
    "id": 1
  },
  "programEncounters": [
    {
      "uuid": "09865cda-3a87-4f18-afa4-1b86cb04a2b2",
      "encounterDateTime": 1562840922000,
      "encounterType": {
        "operationalEncounterTypeName": "Delivery",
        "uuid": "7b6a93c7-e1e1-4e73-842d-df8a1935bde2",
        "name": "Delivery",
        "id": 4
      },
      "earliestVisitDateTime": null,
      "maxVisitDateTime": null,
      "cancelDateTime": null,
      "name": null,
      "id": 2
    }
  ],
  "exitLocation": null,
  "enrolmentDateTime": 1562840818000,
  "programExitDateTime": null,
  "enrolmentLocation": null,
  "programExitObservations": {},
  "id": 1
}

POST /locations api for webapp is not creating location mapping

This seems to be happening because when you create a new location from the admin app, an entry is not being made in "location_location_mapping" table. The android app uses this table to show the hierarchy in registration and other places like search.

How to test this:
When you create a hierarchy and locations in that hierarchy from the UI, it should show up on android app when registering an individual or subject.

Ability to store organisation configuration

Create a new entity organisation_config that will store all organization configuration in Json format.
Table schema:
id, uuid, organization_id, config

Also admin should be able to add/edit/delete entry of this table from webapp.
For now store language in the config column.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.