ubuntu-support-team team mailing list archive
-
ubuntu-support-team team
-
Mailing list archive
-
Message #04163
[Merge] ~rodrigo-barbieri2010/sftools:sftc into sftools:main
Rodrigo Barbieri has proposed merging ~rodrigo-barbieri2010/sftools:sftc into sftools:main.
Requested reviews:
Dan Streetman (ddstreet)
For more details, see:
https://code.launchpad.net/~rodrigo-barbieri2010/sftools/+git/sftools/+merge/426958
--
Your team Ubuntu Support Team is subscribed to branch sftools:main.
diff --git a/scripts/sftc_insert b/scripts/sftc_insert
new file mode 100755
index 0000000..5f9d982
--- /dev/null
+++ b/scripts/sftc_insert
@@ -0,0 +1,145 @@
+#!/usr/bin/python3
+
+import logging
+import pytz
+import sys
+
+from datetime import datetime
+from pathlib import Path
+
+# if called from git source, add parent dir to python path
+if Path(__file__).parent.name == 'scripts':
+ sys.path.insert(0, str(Path(__file__).parent.parent))
+
+from sftools.argparse import SFObjectArgumentParser
+from sftools.sf import SF
+
+
+LOG = logging.getLogger(__name__)
+
+
+def parse_params(data, sf=None):
+
+ if sf is None:
+ sf = SF()
+
+ # Param Minutes
+ LOG.debug(f"Minutes Input: {data['minutes']}")
+ if not isinstance(data['minutes'], int):
+ LOG.error("Minutes parameter is not an integer")
+ exit(1)
+
+ # Param Case Number
+ LOG.debug(f"Case Input: {data['case']}")
+ if not isinstance(data['case'], str):
+ LOG.error("Case number or ID must be a string")
+ exit(1)
+ if len(data['case']) not in (18, 8):
+ LOG.error("Double check your case number or ID param, it should be "
+ "either 8 number digits or 18 chars ID")
+ exit(1)
+ case = sf.Case(data['case'])
+ if not case:
+ LOG.error(f"Case {data['case']} not found")
+ exit(1)
+ LOG.debug(f"Case ID: {case.Id}")
+
+ # Param Start Time
+ LOG.debug(f"Start time Input: {data.get('starttime')}")
+ if data.get('starttime'):
+ try:
+ starttime = datetime.strptime(data['starttime'],'%Y-%m-%d-%H-%M')
+ except ValueError:
+ LOG.error("Wrong timestamp format for Timecard start time, "
+ "check your format is 'yyyy-mm-dd-hh-mm'")
+ exit(1)
+ starttime = starttime.replace(tzinfo=pytz.UTC)
+ else:
+ starttime = datetime.now(pytz.UTC)
+ starttime_str = starttime.isoformat()
+ LOG.debug(f"Start time Parsed: {starttime_str}")
+
+ # Param Work Performed
+ LOG.debug(f"Work performed Input: {data['workperformed']}")
+ if not isinstance(data['case'], str):
+ LOG.error("Data for 'Work performed' field must be a string")
+ exit(1)
+ if len(data['workperformed']) > 254:
+ LOG.error("Length of 'Work performed' string should not exceed 254 chars")
+ exit(1)
+
+ # Dict
+ params = {
+ 'TotalMinutesStatic__c': data['minutes'],
+ 'CaseId__c': case.Id,
+ 'StartTime__c': starttime_str,
+ 'WorkPerformed__c': data['workperformed'],
+ }
+ LOG.debug(f"Insert Dict: {params}")
+ LOG.info(f"Parsed Timecard ( Case Number/ID: {case.CaseNumber} / {case.Id}"
+ f", Minutes: {data['minutes']}, Start Time: {starttime_str}"
+ f", Work Performed: {data['workperformed']} )")
+ return params
+
+
+def insert(params, sf=None):
+
+ if sf is None:
+ sf = SF()
+
+ result = sf.TimeCard__c.create(params)
+ LOG.debug(f"Result: {result}")
+ if result and result.get('success') == True and result.get('errors') == []:
+ LOG.info(f"Inserted Timecard Successfully ( "
+ f"Case ID: {params['CaseId__c']}, "
+ f"Minutes: {params['TotalMinutesStatic__c']}, "
+ f"Start Time: {params['StartTime__c']}, "
+ f"Work Performed: {params['WorkPerformed__c']} )")
+ else:
+ LOG.error(f"Failed to insert Timecard ( "
+ f"Case ID: {params['CaseId__c']}, "
+ f"Minutes: {params['TotalMinutesStatic__c']}, "
+ f"Start Time: {params['StartTime__c']}, "
+ f"Work Performed: {params['WorkPerformed__c']} )"
+ f" : Response: {result}")
+
+
+def main():
+
+ parser = SFObjectArgumentParser()
+
+ parser.add_argument('-m', '--minutes', required=True, type=int,
+ help='Timecard minutes')
+ parser.add_argument('-c', '--case', required=True,
+ help='Case number (or Case ID)')
+ parser.add_argument('-w', '--workperformed', required=True,
+ help='Work performed (Timecard description)')
+ parser.add_argument('-t', '--starttime', required=False, type=str,
+ help='Start time of timecard '
+ '(Format: yyyy-mm-dd-hh-mm) in UTC. If not '
+ 'specified, defaults to current timestamp')
+
+ opts = parser.parse_args()
+
+ logging.basicConfig(level='DEBUG' if opts.verbose else 'INFO',
+ format='%(message)s')
+
+ sf = opts.functions.SF()
+ data = {
+ 'minutes': opts.minutes,
+ 'case': opts.case,
+ 'workperformed': opts.workperformed,
+ 'starttime': opts.starttime,
+ }
+
+ params = parse_params(data, sf=sf)
+
+ if opts.dry_run:
+ LOG.info("Dry run completed")
+ exit(0)
+
+ insert(params, sf=sf)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/sftc_reader b/scripts/sftc_reader
new file mode 100755
index 0000000..c503176
--- /dev/null
+++ b/scripts/sftc_reader
@@ -0,0 +1,93 @@
+#!/usr/bin/python3
+
+from sftc_insert import parse_params, insert
+import argparse
+import logging
+import sys
+
+from pathlib import Path
+
+# if called from git source, add parent dir to python path
+if Path(__file__).parent.name == 'scripts':
+ sys.path.insert(0, str(Path(__file__).parent.parent))
+
+from sftools.sf import SF
+
+LOG = logging.getLogger(__name__)
+
+
+def read(filename, translation_dict=None):
+
+ if translation_dict is None:
+ translation_dict = {}
+
+ with open(filename, 'r') as file:
+ lines = file.readlines()
+
+ timecards = []
+
+ for line in lines:
+ if not line.strip():
+ continue
+ contents = line.split('===')
+ if len(contents) < 3:
+ LOG.error("Incorrect format, please use: "
+ "'case === minutes === workperformed'")
+ case = contents[0].strip()
+ case = translation_dict.get(case) or case
+ minutes = int(contents[1].strip())
+ workperformed = contents[2].strip()
+ starttime = None
+ if len(contents) > 3:
+ starttime = contents[3].strip()
+ data = {
+ 'case': case,
+ 'minutes': minutes,
+ 'workperformed': workperformed,
+ 'starttime': starttime,
+ }
+ timecards.append(data)
+
+ LOG.debug(f"Timecard data parsed from file {timecards}")
+ return timecards
+
+
+def main(translation_dict=None, sf=None):
+
+ if translation_dict is None:
+ translation_dict = {}
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--dry-run', action='store_true',
+ help="Dry-run only, do not make any changes")
+ parser.add_argument('-f', '--filename', type=str, default="timecards.txt",
+ help="File name to open and parse timecards to "
+ "insert. Default is timecards.txt")
+ parser.add_argument('-v', '--verbose', action='store_true', default=False,
+ help="Enable verbose logging")
+
+ opts = parser.parse_args()
+
+ logging.basicConfig(level='DEBUG' if opts.verbose else 'INFO',
+ format='%(message)s')
+
+ timecards = read(opts.filename, translation_dict=translation_dict)
+
+ if sf is None:
+ sf = SF()
+
+ req_params = []
+ for timecard in timecards:
+ params = parse_params(timecard, sf=sf)
+ req_params.append(params)
+
+ if opts.dry_run:
+ LOG.info("Dry run completed")
+ exit(0)
+
+ for params in req_params:
+ insert(params, sf=sf)
+
+
+if __name__ == "__main__":
+ main()
Follow ups