Bläddra i källkod

Improve jobs and progress message

JoostSijm 5 år sedan
förälder
incheckning
df33fb3c30
11 ändrade filer med 231 tillägg och 162 borttagningar
  1. 2 0
      .gitignore
  2. 1 1
      Pipfile
  3. 59 55
      Pipfile.lock
  4. 27 9
      app/__init__.py
  5. 28 92
      app/__main__.py
  6. 2 1
      app/api.py
  7. 71 0
      app/app.py
  8. 4 4
      app/database.py
  9. 18 0
      app/job_storage.py
  10. 12 0
      app/jobs.py
  11. 7 0
      example.jobs.json

+ 2 - 0
.gitignore

@@ -1,3 +1,5 @@
 .venv/
 .env
 __pycache__
+*.log
+jobs.json

+ 1 - 1
Pipfile

@@ -14,4 +14,4 @@ psycopg2-binary = "*"
 apscheduler = "*"
 
 [requires]
-python_version = "3.7"
+python_version = "3"

+ 59 - 55
Pipfile.lock

@@ -1,11 +1,11 @@
 {
     "_meta": {
         "hash": {
-            "sha256": "40681423ee7bb7705184a16526334130adc76c1b726852ea6797a4552c90cdac"
+            "sha256": "dfc866db4a7e79933532497f154755e037f8ef5947733a821745397d78893acf"
         },
         "pipfile-spec": 6,
         "requires": {
-            "python_version": "3.7"
+            "python_version": "3"
         },
         "sources": [
             {
@@ -18,27 +18,27 @@
     "default": {
         "apscheduler": {
             "hashes": [
-                "sha256:529afb7909e08416132891188cbfea5351eb35e4a684b67e983d819e8d01a6b0",
-                "sha256:cde18f6dbffa1b75aff67fd7fe423a3020cb0363f6c67bd45f24306d90898231"
+                "sha256:3bb5229eed6fbbdafc13ce962712ae66e175aa214c69bed35a06bffcf0c5e244",
+                "sha256:e8b1ecdb4c7cb2818913f766d5898183c7cb8936680710a4d3a966e02262e526"
             ],
             "index": "pypi",
-            "version": "==3.6.1"
+            "version": "==3.6.3"
         },
         "beautifulsoup4": {
             "hashes": [
-                "sha256:05668158c7b85b791c5abde53e50265e16f98ad601c402ba44d70f96c4159612",
-                "sha256:25288c9e176f354bf277c0a10aa96c782a6a18a17122dba2e8cec4a97e03343b",
-                "sha256:f040590be10520f2ea4c2ae8c3dae441c7cfff5308ec9d58a0ec0c1b8f81d469"
+                "sha256:5279c36b4b2ec2cb4298d723791467e3000e5384a43ea0cdf5d45207c7e97169",
+                "sha256:6135db2ba678168c07950f9a16c4031822c6f4aec75a65e0a97bc5ca09789931",
+                "sha256:dcdef580e18a76d54002088602eba453eec38ebbcafafeaabd8cab12b6155d57"
             ],
             "index": "pypi",
-            "version": "==4.8.0"
+            "version": "==4.8.1"
         },
         "certifi": {
             "hashes": [
-                "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939",
-                "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"
+                "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
+                "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
             ],
-            "version": "==2019.6.16"
+            "version": "==2019.11.28"
         },
         "chardet": {
             "hashes": [
@@ -56,37 +56,41 @@
         },
         "psycopg2-binary": {
             "hashes": [
-                "sha256:080c72714784989474f97be9ab0ddf7b2ad2984527e77f2909fcd04d4df53809",
-                "sha256:110457be80b63ff4915febb06faa7be002b93a76e5ba19bf3f27636a2ef58598",
-                "sha256:171352a03b22fc099f15103959b52ee77d9a27e028895d7e5fde127aa8e3bac5",
-                "sha256:19d013e7b0817087517a4b3cab39c084d78898369e5c46258aab7be4f233d6a1",
-                "sha256:249b6b21ae4eb0f7b8423b330aa80fab5f821b9ffc3f7561a5e2fd6bb142cf5d",
-                "sha256:2ac0731d2d84b05c7bb39e85b7e123c3a0acd4cda631d8d542802c88deb9e87e",
-                "sha256:2b6d561193f0dc3f50acfb22dd52ea8c8dfbc64bcafe3938b5f209cc17cb6f00",
-                "sha256:2bd23e242e954214944481124755cbefe7c2cf563b1a54cd8d196d502f2578bf",
-                "sha256:3e1239242ca60b3725e65ab2f13765fc199b03af9eaf1b5572f0e97bdcee5b43",
-                "sha256:3eb70bb697abbe86b1d2b1316370c02ba320bfd1e9e35cf3b9566a855ea8e4e5",
-                "sha256:51a2fc7e94b98bd1bb5d4570936f24fc2b0541b63eccadf8fdea266db8ad2f70",
-                "sha256:52f1bdafdc764b7447e393ed39bb263eccb12bfda25a4ac06d82e3a9056251f6",
-                "sha256:5b3581319a3951f1e866f4f6c5e42023db0fae0284273b82e97dfd32c51985cd",
-                "sha256:63c1b66e3b2a3a336288e4bcec499e0dc310cd1dceaed1c46fa7419764c68877",
-                "sha256:8123a99f24ecee469e5c1339427bcdb2a33920a18bb5c0d58b7c13f3b0298ba3",
-                "sha256:85e699fcabe7f817c0f0a412d4e7c6627e00c412b418da7666ff353f38e30f67",
-                "sha256:8dbff4557bbef963697583366400822387cccf794ccb001f1f2307ed21854c68",
-                "sha256:908d21d08d6b81f1b7e056bbf40b2f77f8c499ab29e64ec5113052819ef1c89b",
-                "sha256:af39d0237b17d0a5a5f638e9dffb34013ce2b1d41441fd30283e42b22d16858a",
-                "sha256:af51bb9f055a3f4af0187149a8f60c9d516cf7d5565b3dac53358796a8fb2a5b",
-                "sha256:b2ecac57eb49e461e86c092761e6b8e1fd9654dbaaddf71a076dcc869f7014e2",
-                "sha256:cd37cc170678a4609becb26b53a2bc1edea65177be70c48dd7b39a1149cabd6e",
-                "sha256:d17e3054b17e1a6cb8c1140f76310f6ede811e75b7a9d461922d2c72973f583e",
-                "sha256:d305313c5a9695f40c46294d4315ed3a07c7d2b55e48a9010dad7db7a66c8b7f",
-                "sha256:dd0ef0eb1f7dd18a3f4187226e226a7284bda6af5671937a221766e6ef1ee88f",
-                "sha256:e1adff53b56db9905db48a972fb89370ad5736e0450b96f91bcf99cadd96cfd7",
-                "sha256:f0d43828003c82dbc9269de87aa449e9896077a71954fbbb10a614c017e65737",
-                "sha256:f78e8b487de4d92640105c1389e5b90be3496b1d75c90a666edd8737cc2dbab7"
+                "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29",
+                "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03",
+                "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039",
+                "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881",
+                "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309",
+                "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed",
+                "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b",
+                "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3",
+                "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7",
+                "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b",
+                "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03",
+                "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103",
+                "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d",
+                "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35",
+                "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b",
+                "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49",
+                "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70",
+                "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e",
+                "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e",
+                "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e",
+                "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103",
+                "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6",
+                "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1",
+                "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9",
+                "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e",
+                "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f",
+                "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd",
+                "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8",
+                "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f",
+                "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4",
+                "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964",
+                "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"
             ],
             "index": "pypi",
-            "version": "==2.8.3"
+            "version": "==2.8.4"
         },
         "python-dotenv": {
             "hashes": [
@@ -98,10 +102,10 @@
         },
         "pytz": {
             "hashes": [
-                "sha256:26c0b32e437e54a18161324a2fca3c4b9846b74a8dccddd843113109e1116b32",
-                "sha256:c894d57500a4cd2d5c71114aaab77dbab5eabd9022308ce5ac9bb93a60a6f0c7"
+                "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
+                "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
             ],
-            "version": "==2019.2"
+            "version": "==2019.3"
         },
         "requests": {
             "hashes": [
@@ -113,24 +117,24 @@
         },
         "six": {
             "hashes": [
-                "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
-                "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+                "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
+                "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
             ],
-            "version": "==1.12.0"
+            "version": "==1.13.0"
         },
         "soupsieve": {
             "hashes": [
-                "sha256:8662843366b8d8779dec4e2f921bebec9afd856a5ff2e82cd419acc5054a1a92",
-                "sha256:a5a6166b4767725fd52ae55fee8c8b6137d9a51e9f1edea461a062a759160118"
+                "sha256:bdb0d917b03a1369ce964056fc195cfdff8819c40de04695a80bc813c3cfa1f5",
+                "sha256:e2c1c5dee4a1c36bcb790e0fabd5492d874b8ebd4617622c4f6a731701060dda"
             ],
-            "version": "==1.9.3"
+            "version": "==1.9.5"
         },
         "sqlalchemy": {
             "hashes": [
-                "sha256:0459bf0ea6478f3e904de074d65769a11d74cdc34438ab3159250c96d089aef0"
+                "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec"
             ],
             "index": "pypi",
-            "version": "==1.3.7"
+            "version": "==1.3.12"
         },
         "tzlocal": {
             "hashes": [
@@ -141,10 +145,10 @@
         },
         "urllib3": {
             "hashes": [
-                "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
-                "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
+                "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293",
+                "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
             ],
-            "version": "==1.25.3"
+            "version": "==1.25.7"
         }
     },
     "develop": {}

+ 27 - 9
app/__init__.py

@@ -14,22 +14,40 @@ from app.models import Base, Player, State, Department, DepartmentStat
 load_dotenv()
 
 # database
-engine = create_engine(os.environ["DATABASE_URI"], client_encoding='utf8')
-Session = sessionmaker(bind=engine)
+ENGINE = create_engine(os.environ["DATABASE_URI"], client_encoding='utf8')
+SESSION = sessionmaker(bind=ENGINE)
 
 # scheduler
-scheduler = BackgroundScheduler(
+SCHEDULER = BackgroundScheduler(
     daemon=True,
     job_defaults={'misfire_grace_time': 10*60},
 )
-scheduler.start()
+SCHEDULER.start()
 
-# logging
-logging.basicConfig(
-    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
-    level=logging.INFO
-)
+# get logger
 LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.INFO)
+SCHEDULER_LOGGER = logging.getLogger('apscheduler')
+SCHEDULER_LOGGER.setLevel(logging.DEBUG)
+
+# create file handler
+FILE_HANDLER = logging.FileHandler('output.log')
+FILE_HANDLER.setLevel(logging.DEBUG)
+
+# create console handler
+STREAM_HANDLER = logging.StreamHandler()
+STREAM_HANDLER.setLevel(logging.INFO)
+
+# create formatter and add it to the handlers
+FORMATTER = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+STREAM_HANDLER.setFormatter(FORMATTER)
+FILE_HANDLER.setFormatter(FORMATTER)
+
+# add the handlers to logger
+LOGGER.addHandler(STREAM_HANDLER)
+LOGGER.addHandler(FILE_HANDLER)
+SCHEDULER_LOGGER.addHandler(STREAM_HANDLER)
+SCHEDULER_LOGGER.addHandler(FILE_HANDLER)
 
 # api
 BASE_URL = os.environ["API_URL"]

+ 28 - 92
app/__main__.py

@@ -1,29 +1,11 @@
 """Main app"""
 
-import math
+import sys
 import time
 
-from app import scheduler, LOGGER
-from app.api import get_professors, get_institutes, send_message
-from app.database import get_latest_professor, save_professors, get_yesterday_professors
+from app import SCHEDULER, LOGGER, jobs, job_storage
 
 
-def job_update_department(state_id, department_type):
-    """Update department professors"""
-    LOGGER.info('"%s": Run update for "%s" department for state', state_id, department_type)
-    latest_professor = get_latest_professor(state_id, department_type)
-    date = None
-    if latest_professor:
-        date = latest_professor.date_time
-    professors = get_professors(state_id, department_type, date)
-    LOGGER.info(
-        '"%s": Found "%s" new professors in "%s" department',
-        state_id, len(professors), department_type
-    )
-    # print_professors(professors)
-    save_professors(state_id, department_type, professors)
-    LOGGER.info('"%s": saved professors', state_id)
-
 def print_professors(professors):
     """Print professors"""
     for professor in professors:
@@ -35,8 +17,8 @@ def print_professors(professors):
 
 def add_update_department(state_id, department_type):
     """Add jobs"""
-    scheduler.add_job(
-        job_update_department,
+    SCHEDULER.add_job(
+        jobs.update_department,
         'cron',
         args=[state_id, department_type],
         id='{}_{}'.format(state_id, department_type),
@@ -44,56 +26,10 @@ def add_update_department(state_id, department_type):
         hour='20'
     )
 
-def job_send_progress_message(state_id, department_type, language):
-    """Update department professors"""
-    LOGGER.info('"%s": Send progress message for "%s" department', state_id, department_type)
-    yesterday_professors = get_yesterday_professors(state_id, department_type)
-    if not yesterday_professors:
-        LOGGER.warning('"%s": 0 professor yesterday in "%s" department', state_id, department_type)
-        return
-    yesterday_total = 0
-    for professor in yesterday_professors:
-        yesterday_total += professor.points
-
-    institutes = get_institutes()
-    uranium_institutes = []
-    for institute in institutes:
-        if institute['department_type'] == department_type:
-            uranium_institutes.append(institute)
-            if institute['state_id'] == state_id:
-                state_institute = institute
-    top_department = uranium_institutes[0]
-    top_value = math.ceil(top_department['value'] / 10) * 10
-    points_per_day = round(top_value / 14)
-    msg_current = "Huidige uranium bonus is {} % met {} punten.".format(
-        state_institute['current_bonus'],
-        state_institute['value']
-    )
-    if state_institute['current_bonus'] == 10:
-        msg_required = "Dagelijks zijn er {} punten nodig.".format(
-            points_per_day
-        )
-    else:
-        msg_required = "Benodigde punten voor 10 % bonus: {} wat dagelijks {} punten zijn.".format(
-            top_value,
-            points_per_day
-        )
-    msg_yesterday = "Aantal punten gisteren: {}, wat {} % van de benodigde aantal punten is.".format(
-        yesterday_total,
-        round(100 / points_per_day * yesterday_total)
-    )
-    message = ' '.join([
-        msg_current,
-        msg_required,
-        msg_yesterday
-    ])
-    print(message)
-    send_message(language, message)
-
 def add_send_progress_message(state_id, department_type, language):
     """Add send_message"""
-    scheduler.add_job(
-        job_send_progress_message,
+    SCHEDULER.add_job(
+        jobs.send_progress_message,
         'cron',
         args=[state_id, department_type, language],
         id='send_message_{}_{}'.format(state_id, department_type),
@@ -104,27 +40,27 @@ def add_send_progress_message(state_id, department_type, language):
 
 if __name__ == '__main__':
     # jobs
-    # job_update_department(2788, 6)
-    # job_send_progress_message(2788, 6, 'nl')
-    # VN
-    # uranium
-    add_update_department(2788, 6)
-    # gold
-    add_update_department(2788, 2)
-    # construction
-    add_update_department(2788, 1)
-    # oil
-    add_update_department(2788, 3)
-    # Belgium
-    # gold
-    add_update_department(2604, 2)
-    # uranium
-    add_update_department(2604, 6)
-    # De Provincien
-    # gold
-    add_update_department(2620, 2)
+    # jobs.update_department(2788, 6)
+    # jobs.send_progress_message(2788, 6, 'nl')
+
+    # Jobs
+    JOBS = job_storage.get_jobs()
+    for job in JOBS:
+        LOGGER.info(
+            'For "%s" add department "%s" update',
+            job['state_id'],
+            job['department_type']
+        )
+        SCHEDULER.add_job(
+            jobs.update_department,
+            'cron',
+            args=[job['state_id'], job['department_type']],
+            id='{}_{}'.format(job['state_id'], job['department_type']),
+            replace_existing=True,
+            hour='20'
+        )
 
-    # send message
+    # progress message VN uranium
     add_send_progress_message(2788, 6, 'nl')
 
     try:
@@ -132,5 +68,5 @@ if __name__ == '__main__':
             time.sleep(100)
     except KeyboardInterrupt:
         print('Exiting application')
-        scheduler.shutdown()
-        exit()
+        SCHEDULER.shutdown()
+        sys.exit()

+ 2 - 1
app/api.py

@@ -87,7 +87,8 @@ def parse_institutes(html):
     institutes_tree = soup.find_all(class_='list_link')
     institutes = []
     for institute_tree in institutes_tree:
-        department_type = int(re.sub(r'^.*\/', '', institute_tree.select('.results_date')[1]['action']))
+        department_type = \
+            int(re.sub(r'^.*\/', '', institute_tree.select('.results_date')[1]['action']))
         value = int(institute_tree.select('.list_level')[0].string)
         current_bonus = float(re.sub(r'\s%$', '', institute_tree.select('.list_level')[2].string))
         if current_bonus >= 2:

+ 71 - 0
app/app.py

@@ -0,0 +1,71 @@
+"""General functions module"""
+
+import math
+
+from app import LOGGER, database, api
+
+
+def update_department(state_id, department_type):
+    """Update department professors"""
+    LOGGER.info('"%s": Run update for "%s" department for state', state_id, department_type)
+    latest_professor = database.get_latest_professor(state_id, department_type)
+    date = None
+    if latest_professor:
+        date = latest_professor.date_time
+    professors = api.get_professors(state_id, department_type, date)
+    LOGGER.info(
+        '"%s": Found "%s" new professors in "%s" department',
+        state_id, len(professors), department_type
+    )
+    # print_professors(professors)
+    database.save_professors(state_id, department_type, professors)
+    LOGGER.info('"%s": saved professors', state_id)
+
+
+def send_progress_message(state_id, department_type, language):
+    """Update department professors"""
+    LOGGER.info('"%s": Send progress message for "%s" department', state_id, department_type)
+    yesterday_professors = database.get_yesterday_professors(state_id, department_type)
+    if not yesterday_professors:
+        LOGGER.warning('"%s": 0 professor yesterday in "%s" department', state_id, department_type)
+        return
+    yesterday_total = 0
+    for professor in yesterday_professors:
+        yesterday_total += professor.points
+
+    institutes = api.get_institutes()
+    uranium_institutes = []
+    for institute in institutes:
+        if institute['department_type'] == department_type:
+            uranium_institutes.append(institute)
+            if institute['state_id'] == state_id:
+                state_institute = institute
+    top_department = uranium_institutes[0]
+    top_value = math.ceil(top_department['value'] / 10) * 10
+    points_per_day = round(top_value / 14)
+    msg_current = "Huidige uranium bonus is {} % met {} punten.".format(
+        state_institute['current_bonus'],
+        state_institute['value']
+    )
+    if state_institute['current_bonus'] == 10:
+        msg_required = "Dagelijks zijn er {} punten nodig.".format(
+            points_per_day
+        )
+    else:
+        msg_required = \
+            "Benodigde punten voor 10 % bonus: {} wat dagelijks {} punten zijn.".format(
+                top_value,
+                points_per_day
+            )
+    msg_yesterday = \
+        "Aantal punten gisteren: {}, wat {} % van de benodigde aantal punten is.".format(
+            yesterday_total,
+            round(100 / points_per_day * yesterday_total)
+        )
+    message = ' '.join([
+        msg_current,
+        msg_required,
+        msg_yesterday
+    ])
+    print(message)
+    api.send_message(language, message)

+ 4 - 4
app/database.py

@@ -2,13 +2,13 @@
 
 from datetime import datetime, timedelta
 
-from app import Session
+from app import SESSION
 from app.models import Player, Department, DepartmentStat
 
 
 def get_latest_professor(state_id, department_type):
     """Get latest professor from database"""
-    session = Session()
+    session = SESSION()
     department = get_department(session, state_id, department_type)
     professor = department.department_stats.order_by(DepartmentStat.date_time.desc()).first()
     session.close()
@@ -42,7 +42,7 @@ def get_department(session, state_id, department_type):
 
 def save_professors(state_id, department_type, professors):
     """Save professors to database"""
-    session = Session()
+    session = SESSION()
     department = get_department(session, state_id, department_type)
 
     for professor in professors:
@@ -58,7 +58,7 @@ def save_professors(state_id, department_type, professors):
 
 def get_yesterday_professors(state_id, department_type):
     """Get professors from yesterday"""
-    session = Session()
+    session = SESSION()
     department = get_department(session, state_id, department_type)
     until_date = datetime.today().replace(hour=20, minute=0, second=0)
     from_date = until_date - timedelta(1)

+ 18 - 0
app/job_storage.py

@@ -0,0 +1,18 @@
+"""store and read jobs"""
+
+import json
+
+from app import LOGGER
+
+
+def get_jobs():
+    """Read jobs"""
+    LOGGER.info('Read stored jobs')
+    try:
+        with open('jobs.json', 'r') as jobs_file:
+            jobs = json.load(jobs_file)
+            LOGGER.info('found "%s" job(s) in job storage', len(jobs))
+            return jobs
+    except FileNotFoundError:
+        LOGGER.error('job storage file "jobs.json" not found')
+    return []

+ 12 - 0
app/jobs.py

@@ -0,0 +1,12 @@
+"""Jobs for scheduler module"""
+
+from app import app
+
+
+def update_department(state_id, department_type):
+    """Update department"""
+    app.update_department(state_id, department_type)
+
+def send_progress_message(state_id, department_type, language):
+    """Send department progress message"""
+    app.send_progress_message(state_id, department_type, language)

+ 7 - 0
example.jobs.json

@@ -0,0 +1,7 @@
+[
+    {
+    	"_department": "uranium",
+        "state_id": 2788,
+        "department_type": 6,
+    },
+]