Skip to content

Commit dc532b3

Browse files
author
Sergey Chernyak
committed
issue-1 added support fo holiday calendar
1 parent 789314d commit dc532b3

File tree

10 files changed

+177
-24
lines changed

10 files changed

+177
-24
lines changed

Pipfile.lock

Lines changed: 21 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/explicitdev/analyse/abstract.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def _update_gspread(self, query):
4646
rows = list(self._get_rows_from_query(query))
4747
new_rows_count = len(rows)
4848
logging.info('Going to upload %s rows into %s report', new_rows_count, class_name)
49-
work_sheet.append_rows(
49+
work_sheet.insert_rows(
5050
rows,
5151
)
5252
logging.info('Upload data to %s completed', class_name)

src/explicitdev/cli.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from explicitdev.fetch.jira import FetchJiraData
77
from explicitdev.storage.model.base import Base
88
from explicitdev.storage.update import UpdateJira
9+
from explicitdev.storage.update.holiday import UpdateHolidayCSV
910

1011

1112
def drop_and_create_all():
@@ -47,6 +48,15 @@ def sync(drop_db):
4748
drop_and_create_all()
4849
UpdateJira(Config).sync()
4950

51+
@main.command()
52+
@click.option('--drop_db', is_flag=True)
53+
def sync_holiday(drop_db):
54+
updater = UpdateHolidayCSV(Config)
55+
# todo delete copypaste and merge it with load
56+
if drop_db:
57+
updater.drop_create_tables()
58+
updater.sync()
59+
5060

5161
def _analyze():
5262
analyzer = Config.JiraAnalyzer(Config)

src/explicitdev/config.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,25 @@
55

66
import gspread
77
import pytz
8+
from sqlalchemy import create_engine
9+
from sqlalchemy.orm import sessionmaker
10+
811
from explicitdev.analyse.jira import JiraAnalyzer
912
from explicitdev.storage.factory import (
1013
FactoryIssue,
1114
FactoryStatus,
1215
FactoryHistory,
1316
FactoryUser,
17+
FactoryHoliday,
1418
)
1519
from explicitdev.storage.model import (
1620
Issue as AlchemyIssue,
1721
User as AlchemyUser,
1822
Status as AlchemyStatus,
23+
Holiday as AlchemyHoliday,
1924
)
2025
from explicitdev.storage.session import session_scope
2126
from explicitdev.utils.const import ReportSaveModes
22-
from sqlalchemy import create_engine
23-
from sqlalchemy.orm import sessionmaker
2427

2528
if TYPE_CHECKING:
2629
from explicitdev.storage.model.base import ModelContainerTypeTuple
@@ -37,6 +40,7 @@ class DataFiles:
3740
PATH: Path = None
3841
"""Folder to store different data files as source and target for dump"""
3942
ISSUE_DUMPS: str = "issue_dumps.json"
43+
HOLIDAYS: str = "holidays.csv"
4044

4145
class Models:
4246
class Issue:
@@ -51,6 +55,10 @@ class User:
5155
Class = AlchemyUser
5256
Factory = FactoryUser
5357

58+
class Holiday:
59+
Class = AlchemyHoliday
60+
Factory = FactoryHoliday
61+
5462
FactoryHistory = FactoryHistory
5563
models_with_containers: 'ModelContainerTypeTuple' = (Issue.Class, Status.Class)
5664

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from explicitdev.config import Config
2+
from explicitdev.fetch.abstract_csv import FetchCSV
3+
4+
5+
class FetchHolidayCSV(FetchCSV):
6+
7+
def __init__(self, c: Config):
8+
super().__init__(c)
9+
self.file_name = c.DataFiles.HOLIDAYS

src/explicitdev/storage/factory/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from .status import FactoryStatus
33
from .history import FactoryHistory
44
from .user import FactoryUser
5+
from .holiday import FactoryHoliday
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from datetime import date
2+
3+
from sqlalchemy.orm import Session
4+
5+
from explicitdev.storage.factory.abstract import FactoryAbstract
6+
from explicitdev.storage.model import HolidayAttrs
7+
from explicitdev.storage.model.holiday import HolidayType
8+
9+
HA = HolidayAttrs
10+
11+
12+
class FactoryHoliday(FactoryAbstract):
13+
YEAR_FIELD_NAME = 'Год/Месяц'
14+
15+
SKIP_SYMBOL = '*'
16+
"""A symbol from calenders on witch we skip days."""
17+
18+
def __init__(self, c):
19+
super().__init__(c)
20+
self.Holiday = c.Models.Holiday.Class
21+
22+
def fill_dict_from_raw_dict(self, raw_json_dict, data, result_dict: dict = None) -> dict:
23+
"""
24+
25+
:param raw_json_dict:
26+
:param data:
27+
:param result_dict: Actually passing this will not work, because result_dict generated internally.
28+
:return:
29+
"""
30+
if not result_dict:
31+
result_dict = dict()
32+
33+
rjd = raw_json_dict
34+
year = int(rjd.pop(self.YEAR_FIELD_NAME))
35+
for month, month_days in enumerate(rjd.values(), start=1):
36+
if month > 12:
37+
break
38+
for day in month_days.split(','):
39+
try:
40+
day = int(day)
41+
except ValueError:
42+
symbol = day[-1:]
43+
if symbol == self.SKIP_SYMBOL:
44+
continue
45+
day = int(day[:-1])
46+
47+
result_dict = {
48+
HA.date: date(year, month, day),
49+
HA.type: HolidayType.government,
50+
}
51+
52+
self.solve_update_or_insert(
53+
data[self.Holiday.__name__],
54+
result_dict,
55+
result_dict[HA.date],
56+
)
57+
58+
return result_dict
59+
60+
def get_existed_entities(self, session: Session, **kwargs) -> dict:
61+
# noinspection PyTypeChecker
62+
result = super().get_existed_entities(
63+
session=session,
64+
model=self.Holiday,
65+
columns=(
66+
HA.date,
67+
),
68+
)
69+
return result
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .issue import Issue, IssueAttrs
22
from .user import User, UserAttrs
33
from .status import Status, StatusAttrs
4+
from .holiday import Holiday, HolidayAttrs
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from sqlalchemy import (
2+
Column,
3+
String,
4+
Integer,
5+
Date,
6+
)
7+
8+
from .base import Base
9+
from ...utils.auto_name_attrs import AutoNamedModelAttrs
10+
11+
12+
class HolidayType:
13+
government = 'government'
14+
corporate = 'corporate'
15+
16+
17+
class Holiday(Base):
18+
id = Column(Integer, primary_key=True)
19+
type = Column(
20+
String,
21+
comment='User types. Look at enum.',
22+
index=True,
23+
)
24+
date = Column(
25+
Date,
26+
comment='Date of a day',
27+
unique=True,
28+
)
29+
30+
31+
class HolidayAttrs(Holiday, metaclass=AutoNamedModelAttrs):
32+
pass
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from explicitdev.config import Config
2+
from explicitdev.fetch.holiday_csv import FetchHolidayCSV
3+
from explicitdev.storage.factory import FactoryHoliday
4+
from explicitdev.storage.update.abstract import AbstractUpdate
5+
6+
7+
class UpdateHolidayCSV(AbstractUpdate):
8+
9+
def __init__(self, c: Config, *args, **kwargs):
10+
super().__init__(c, *args, **kwargs)
11+
self.models_with_containers = (c.Models.Holiday.Class,)
12+
13+
def sync(self):
14+
fetcher = FetchHolidayCSV(self.c)
15+
factory = FactoryHoliday(self.c)
16+
containers = self._create_data_containers_dict()
17+
with self.c.session_context() as session:
18+
factory.get_existed_entities(session)
19+
for row in fetcher.get_data():
20+
factory.fill_dict_from_raw_dict(row, containers)
21+
self._bulk_update_insert_mappings(session, containers)
22+
# Todo write verification for a working and non-working day for a row
23+
session.commit()

0 commit comments

Comments
 (0)