コード例 #1
0
ファイル: ping.py プロジェクト: JavierLuna/cunhaobot
def _send_report(bot: Bot, now: datetime.date) -> None:
    yesterday = now - timedelta(days=1)
    bef_yesterday = yesterday - timedelta(days=1)
    today_report, yesterday_report = Report.get_at(yesterday), Report.get_at(
        bef_yesterday)

    longs, longs_delta = today_report.longs, today_report.longs - yesterday_report.longs
    shorts, shorts_delta = today_report.shorts, today_report.shorts - yesterday_report.shorts
    users, user_delta = today_report.users, today_report.users - yesterday_report.users
    groups, groups_delta = today_report.groups, today_report.groups - yesterday_report.groups
    in_users, in_users_delta = today_report.inline_users, today_report.inline_users - yesterday_report.inline_users
    in_uses, in_uses_delta = today_report.inline_usages, today_report.inline_usages - yesterday_report.inline_usages
    gdprs, gdprs_delta = today_report.gdprs, today_report.gdprs - yesterday_report.gdprs
    chapas, chapas_delta = today_report.chapas, today_report.chapas - yesterday_report.chapas
    top_long, top_short = today_report.top_long, today_report.top_short

    def fmt_delta(delta: int) -> str:
        return f'+{delta}' if delta >= 0 else str(delta)

    bot.send_message(
        curators_chat_id,
        f"<b>Resumen del {yesterday.strftime('%Y/%m/%d')}</b>:\n"
        f"Frases largas: {longs} ({fmt_delta(longs_delta)})\n"
        f"Palabras poderosas: {shorts} ({fmt_delta(shorts_delta)})\n"
        f"Usuarios: {users} ({fmt_delta(user_delta)})\n"
        f"Grupos: {groups} ({fmt_delta(groups_delta)})\n"
        f"Usuarios inline: {in_users} ({fmt_delta(in_users_delta)})\n"
        f"Usos inline: {in_uses} ({fmt_delta(in_uses_delta)})\n"
        f"Chapas: {chapas} ({fmt_delta(chapas_delta)})\n"
        f"GDPRs: {gdprs} ({fmt_delta(gdprs_delta)})\n\n"
        f"La frase más usada de ayer fue:\n<b>{top_long}</b>\n"
        f"El apelativo más usado ayer fue:\n<b>{top_short}</b>\n",
        parse_mode=ParseMode.HTML,
    )
コード例 #2
0
ファイル: ks_crash.py プロジェクト: jarodl/KSCrashServer
def crashes():
    if request.method == 'POST':
        json_file = request.files['reports']
        reports = json.loads(json_file.read())
        for report_dict in reports:
            crash_id = report_dict['crash_id']
            if Report.get(crash_id) is None:
                report = Report(crash_id, report_dict)
                report.save()
                jug.publish('report-channel', report.__dict__)
        return jsonify(success=True)
    return redirect(url_for('index'))
コード例 #3
0
ファイル: ping.py プロジェクト: JavierLuna/cunhaobot
def _generate_report(now: datetime.date) -> None:
    # Shuffle so in case of draw for usage of the day it's not always the same
    long_phrases: List[LongPhrase] = random.sample(
        LongPhrase.refresh_cache(), len(LongPhrase.get_phrases()))
    short_phrases: List[Phrase] = random.sample(Phrase.refresh_cache(),
                                                len(Phrase.get_phrases()))
    users = User.load_all(ignore_gdpr=True)
    chapas = ScheduledTask.get_tasks(type='chapa')
    inline_users = InlineUser.get_all()
    Report.generate(long_phrases, short_phrases, users, inline_users, chapas,
                    now)
    Phrase.remove_daily_usages()
    LongPhrase.remove_daily_usages()
コード例 #4
0
ファイル: report.py プロジェクト: bigbag/archive_term-flask
def report_get_terminal_report():
    arg = get_post_arg(request, True)
    arg['firm_id'] = g.firm_info['id']

    if not 'report_type' in arg:
        abort(405)

    if arg['report_type'] == 'term':
        arg['payment_type'] = Report.TYPE_WHITE
        answer = Report().get_term_report(**arg)
    else:
        answer = Report().get_person_report(**arg)

    return jsonify(answer)
コード例 #5
0
    def test_func_add_history(self):
        history = PaymentHistory()

        data_wallet = dict(
            id=1,
            payment_id=self.PAYMENT_ID,
            hard_id=self.HARD_ID,
            name=self.TEST_STRING,
            user_id=self.USER_ID,
            discodes_id=self.DISCODES_ID,
            card_pan=self.CARD_PAN
        )
        wallet = PaymentWallet()
        wallet.__dict__.update(data_wallet)

        data_report = dict(
            term_id=self.TERM_ID,
            event_id=self.EVENT_ID,
            person_id=self.PERSON_ID,
            payment_id=self.FIRM_ID,
            firm_id=self.FIRM_ID,
            creation_date=date_helper.get_current_date(),
        )
        report = Report()
        report.__dict__.update(data_report)

        assert history.add_history(wallet, report)

        history.delete()
コード例 #6
0
ファイル: test_report.py プロジェクト: jordantjh/re-root
    def test_constructor(self):
        """ Test whether constructor sets correctly """
        d1 = Driver('a', 0, 0)
        d2 = Driver('b', 0, 0)
        r = Report([d1, d2])

        self.assertListEqual(r.output, [d1, d2])
コード例 #7
0
ファイル: report.py プロジェクト: timur-glushan/tt
 def listActiveReports(cls, start_date=None, end_date=None, accounts=None, components=None):
   from models.account import Account
   from models.project import Project, Component
   from models.report import Report
   
   query = Report.query\
     .filter(~Report.status.in_(Report._r(Report.STATUS_DELETED)))\
     .join(Report.account)\
     .filter(~Account.status.in_(Account._r(Account.STATUS_DELETED)))\
     .join(Report.component, aliased=True)\
     .filter(~Component.status.in_(Component._r(Component.STATUS_DELETED)))\
     .join(Report.project, aliased=True)\
     .filter(~Project.status.in_(Project._r(Project.STATUS_DELETED)))
   
   if start_date:
     query = query.filter(Report.due_date>=start_date)
   if end_date:
     query = query.filter(Report.due_date<=end_date)
   if accounts:
     query = query.filter(Report.account_id.in_(accounts))
   if components:
     query = query.filter(Report.component_id.in_(components))
   
   query = query.order_by(Account.first_name, Account.last_name, Account.alias, Report.due_date, Report.created)
   
   return query.all()
コード例 #8
0
def delete_report(submitter_id, id):
    if not check.logged_in():
        flash({'text': "Please sign in.", 'type': "error"})
        return redirect("/")
    else:
        if submitter_id == session.get("user_id", ""):
            report = Report(id)
            report.delete()
            flash({'text': "You have deleted a report.", 'type': "success"})
            return redirect("/user/profile/" + str(submitter_id))
        else:
            flash({
                'text': "You can not delete another user's report.",
                'type': "error"
            })
            return redirect("/")
コード例 #9
0
ファイル: report.py プロジェクト: simpleai-dev/anfora
    async def post(self, user):

        # Id of the user being reported
        try:
            target = int(self.get_argument('target', False))
        except:
            raise CustomError(reason="Target user not provided",
                              status_code=404)
            logger.error(
                "Id of target couldn't be converted to int or is not present")

        user_target = await self.application.objects.get(UserProfile,
                                                         id=target)

        if not user_target:
            raise CustomError(reason="Target provided is not valid",
                              status_code=404)

        # Id of the user reporting
        reporter = user.id

        # Message of the report
        message = self.get_param('message', default="")

        # Reason of the report
        reason = self.get_param('reason', default="Not expecified")

        report = Report.create(target=user_target,
                               reporter=reporter,
                               message=message,
                               reason=reason)

        resp.body = json.dumps(report.json())
        resp.status = falcon.HTTP_200
コード例 #10
0
def send_report():
    state_id = request.form.get('state_id')
    check_state = storage.get('State', state_id)
    if check_state is None:
        return jsonify({'error': 'Department selected does not exist'})
    number_infections = request.form.get('number_infections')
    try:
        number_infections = w2n.word_to_num(number_infections)
        if number_infections < 0 or type(number_infections) is not int:
            raise ValueError('Invalid number')
    except:
        return jsonify({'error': 'The number you typed is invalid'})
    new_report = Report(state_id=state_id, infections=number_infections)
    new_report.save()
    storage.close()
    return jsonify({'success': 'Your data was registered correctly'})
コード例 #11
0
ファイル: report.py プロジェクト: bigbag/archive_term-flask
def report_get_money_report():
    arg = get_post_arg(request, True)

    arg['payment_type'] = Report.TYPE_PAYMENT
    arg['firm_id'] = g.firm_info['id']

    answer = Report().get_term_report(**arg)

    return jsonify(answer)
コード例 #12
0
    def get_report(self):
        if not self.task or not self.firm:
            return False
        if not self.type or not self.type['meta']:
            return False
        if not self.interval or not self.interval['meta'] or not self.interval['search']:
            return False

        report = Report()
        report.firm_id = self.firm.id
        report.period = self.interval['meta']
        report.person_id = self.get_person_id()

        report_query_name = "%s_query" % self.type['meta']
        if report_query_name not in Report.__dict__:
            return False

        return getattr(report, report_query_name)(self.interval['search']).all()
コード例 #13
0
ファイル: report.py プロジェクト: simpleai-dev/anfora
    async def get(self, id):

        report = Report.get_or_none(Report.id == id)
        if report and req.context['user'].is_admin:
            resp.body = json.dumps(report.json())
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_404
            resp.body = json.dumps({'Error': 'Report not found'})
コード例 #14
0
def review_reports(id):
#Admins can review reports and decide the result of it. 

    if check.admin_logged_in():
        form = ReviewForm(request.form)
        
        if form.validate_on_submit():
            report = Report(id)
            action = form.data["action_taken"]
            is_dismissed = form.data["is_dismissed"]
            report.update_for_review(action,is_dismissed)
            return redirect("../")
        else:
            if request.method == "POST":
                return render_template('admin_review.html', form=form, error = "Invalid, field, please check again.")
            else:
                return render_template('admin_review.html', form=form)
    else:
        flash({'text': "You have to sign in to your admin account first.", 'type': "error"}) 
        return redirect("/user/login")
コード例 #15
0
    def get_interval_dict(self):
        result = {}
        if not self.task:
            return None

        result['meta'] = ReportStack().get_interval_meta(self.task.interval)
        result['templ_name'] = ReportStack().get_sender_interval_name(
            self.task.interval)
        result['date'] = datetime.now() - timedelta(1)
        result['search'] = date_helper.get_date_interval(
            result['date'], result['meta'])

        full_format = '%Y-%m-%d %H:%M:%S'
        simple_format = '%Y-%m-%d'
        if self.task.interval == ReportStack.INTERVAL_ONCE:
            details = self.task.details
            if details and 'period' in details:
                details = self.task.decode_field(details)
                interval = details['period']
                try:
                    result['search'] = (
                        date_helper.to_utc(
                            datetime.strptime(interval['start'], full_format), app.config['TZ']),
                        date_helper.to_utc(
                            datetime.strptime(interval['end'], full_format), app.config['TZ']))
                except:
                    result['search'] = (
                        date_helper.to_utc(
                            datetime.strptime(interval['start'], simple_format), app.config['TZ']),
                        date_helper.to_utc(
                            datetime.strptime(interval['end'], simple_format), app.config['TZ']))

                result['date'] = result['search']

        report = Report()
        report.period = result['meta']
        result['templ_interval'] = report.format_search_date(result['date'])

        return result
コード例 #16
0
def get_reports():
    cursor.execute(
        "SELECT *, (SELECT COUNT(*) FROM report_confirm WHERE report_confirm.report_id = report.id) AS confirm FROM report"
    )

    t_reports = list()

    for t_report in cursor.fetchall():
        t_reports.append(
            Report(t_report[0], t_report[1], t_report[2], t_report[3],
                   t_report[4], t_report[5]))  #Parsing of tuple to object

    return json.dumps([ob.__dict__ for ob in t_reports])
コード例 #17
0
ファイル: test_report.py プロジェクト: jordantjh/re-root
    def test_print(self):
        """ Test both cases when output is empty and when it is not """

        # output = []
        r1 = Report([])
        r1.print()
        out, err = self.capfd.readouterr()
        assert "No result." in out

        # output = [d1]
        d1 = Driver('a', 0, 0)
        r2 = Report([d1])
        r2.print()
        out, err = self.capfd.readouterr()
        assert "No result." not in out
コード例 #18
0
    def run(self):
        s = ExpectSolver.storage
        _condition = self._enabled_condition or ""
        if _condition.strip() != "" and not eval(self._enabled_condition):
            return
        if not self._enabled:
            return

        # TODO : this only supports json add more

        # send request
        root_report: Report
        try:
            _response = request(
                self._request_model.method,
                self._url_override or self._request_model.url,
                headers=self._headers,
                json=self._body,
            )
            root_report = Report(True, '', name=self._name, tag='main')

        except Exception as e:
            self._reports.append(
                Report(False,
                       str(e),
                       name='sending request ' + self._name,
                       tag='main'))
            # create N/A reports for expressions
            for expr in self._expressions:
                self._reports.append(
                    Report(None,
                           'expression ignored',
                           name=expr.name,
                           tag='sub'))
            return

        # check expects
        for expr in self._expressions:
            expr.request_response = _response
            expr.solve()
            self._reports.append(
                Report(expr.ok,
                       'pass' if expr.ok else expr.error,
                       name=expr.name,
                       tag='sub'))

        for save in self._save:
            save.request_response = _response
            save.solve()

        for report in self._reports:
            if not report.status:
                root_report.status = False

        self._reports = [root_report] + self._reports
コード例 #19
0
def show_reports(id):
    if check.logged_in():
        if id == session.get("user_id", ""):
            return render_template('user_reports.html',
                                   report_list=Report.get_user_all_reports(id))
        else:
            flash({
                'text': "You can not view another user's reports",
                'type': "error"
            })
            return redirect("../")
    else:
        flash({
            'text': "You have to sign in to view your reports.",
            'type': "error"
        })
        return redirect("/")
コード例 #20
0
ファイル: report.py プロジェクト: indigos33k3r/anfora
    def on_post(self, req, resp):
        target = req.get_param_as_int('target', required=True, min=0)
        reporter = req.context['user']
        message = req.get_param('message', default="")
        reason = req.get_param('reason', required=True)

        user_target = UserProfile.get_or_none(id=target)

        if user_target and reason in topics:
            report = Report.create(target=user_target,
                                   reporter=reporter,
                                   message=message,
                                   reason=reason)

            resp.body = json.dumps(report.json())
            resp.status = falcon.HTTP_200
        else:
            resp.status = falcon.HTTP_400
            resp.body = json.dumps({"Error": "Bad topic or no target"})
コード例 #21
0
def profile_page(id):
    try:
        admin = False
        ban = False
        self_profile = False
        if check.logged_in():
            if id == session.get("user_id", ""):
                self_profile = True
        if admin_check.admin_logged_in():
            admin = True
        user = User(id)
        if user.is_banned == True:
            ban = True

        parent_list = []
        for vote in Vote.get_user_total_votes(user.id):
            if vote.is_comment == 1:
                parent_list.append(Comment(vote.comment_id))
            elif vote.is_comment == 0:
                parent_list.append(Post(vote.post_id))

        return render_template('profile.html',
                               id=user.id,
                               username=user.username,
                               first_name=user.first_name,
                               last_name=user.last_name,
                               birth_date=user.birth_date,
                               creation_date=user.date,
                               posts=Post.get_user_post(user.id),
                               email=user.email,
                               self_profile=self_profile,
                               total_votes=Vote.get_user_total_votes(user.id),
                               comments=Comment.get_user_total_comments(
                                   user.id),
                               reports=Report.get_user_all_reports(user.id),
                               parent_list=parent_list,
                               admin=admin,
                               ban=ban)

    except NotImplementedError as error:
        flash("Error: " + str(error))
        return redirect("/")
コード例 #22
0
ファイル: payment.py プロジェクト: bigbag/archive_term-flask
    def new_payment_manager():
        history = PaymentHistory.get_new_payment()
        for key in history:
            PaymentTask.check_status.delay(key.id)

        reports = Report.get_new_payment()
        if not reports:
            return False

        for report in reports:
            history = PaymentHistory.query.filter_by(
                report_id=report.id).first()
            if history:
                continue

            # Start: Костыль на время перехода от кошельков с балансом
            wallet = PaymentWallet.get_valid_by_payment_id(report.payment_id)
            if wallet and int(wallet.balance) > 0:
                PaymentTask.background_old_payment.delay(report.id)
                continue
            # End
            PaymentTask.background_payment.delay(report.id)

        return True
コード例 #23
0
ファイル: test_report.py プロジェクト: endymecy/NDIToolbox
 def setUp(self):
     self.output_folder = os.path.join(os.path.dirname(__file__),
                                       "support_files")
     self.output_file = os.path.join(self.output_folder, "test_report.pdf")
     self.report = Report(self.output_file)
コード例 #24
0
def show_reports():
    if check.admin_logged_in():
        return render_template('admin_reports.html', report_list = Report.get_reports())
    else:
        flash({'text': "You have to sign in to your admin account first.", 'type': "error"}) 
        return redirect("/user/login")
コード例 #25
0
ファイル: insert_data.py プロジェクト: carlosz22/psl-outbreak
#!/usr/bin/python3
"""
Populates the database with necessary data
"""

from flask import Flask, render_template, jsonify
from models.report import Report
from models.news import News
from models.state import State
import models
from models import storage

first_state = storage.session.query(State).filter_by(name="Antioquia").first()
new_report = Report(infections=12, state_id=first_state.id)
print(new_report.to_dict())
print(first_state.to_dict())
storage.new(new_report)
storage.save()
print(first_state.reports)
コード例 #26
0
ファイル: report.py プロジェクト: timur-glushan/tt
def report_edit(account_id, report_id=None):
  from models.account import Account
  from models.project import Project, Component
  from models.report import Report
  
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    if request.is_ajax:
      return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['user not found']}), mimetype='application/json')
    else:
      abort(404)
  
  report = None
  if not report_id:
    report = Report()
    report.status = Report.STATUS_ACTIVE
    report.due_date = datetime.datetime.now().strftime('%Y-%m-%d')
    if not app.access('report', action='create'):
      if request.is_ajax:
        return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
      else:
        abort(403)
  else:
    report_id = urllib.unquote_plus(report_id)
    report = Report.query.filter_by(id=report_id).first()
    if not report:
      if request.is_ajax:
        return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['report not found']}), mimetype='application/json')
      else:
        abort(404)
    elif not app.access('report', action='update', report=report):
      if request.is_ajax:
        return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
      else:
        abort(403)
  
  title = g._t('report submit')
  
  report_due_date_list = []
  validationErrors = []
  if (request.method == 'POST' and request.values.get('csrf_token', None)) or request.values.get('no_validate', None):
    report.reporter_id = g.account.id
    
    component_id = request.values.get('report_component_id', None)
    if component_id:
      component = Component.query.filter_by(id=component_id).first()
      if component:
        report.component_id = component.id
        report.project_id = component.project_id
    
    
    report_due_date_list = request.values.get('report_due_date', report.due_date).strip().split(',')
    report.due_date = report_due_date_list.pop(0)
    
    hours = request.values.get('report_hours', str(report.hours)).strip() or 0
    if not hours or not str(hours).isdigit():
      hours = 0.0
    minutes = request.values.get('report_minutes', str(report.minutes)).strip() or 0
    if not minutes or not str(minutes).isdigit():
      minutes = 0.0
    report.duration = float(hours) + (float(minutes) / 60)
    
    report.summary = request.values.get('report_summary', report.summary).strip()
    report.status = int(request.form.get('report_status', report.status).strip())
    report.account_id = account.id
    validationErrors = report.validate()
    if request.values.get('no_validate', None):
      status = 200
      description = 'OK'
    elif not validationErrors:
      report.save()
      
      for report_clone_due_date in report_due_date_list:
        if report_clone_due_date == report.due_date:
          continue
        reportClone = Report()
        reportClone.reporter_id = report.reporter_id
        reportClone.project_id = report.project_id
        reportClone.component_id = report.component_id
        reportClone.summary = report.summary
        reportClone.status = report.status
        reportClone.duration = report.duration
        reportClone.account_id = report.account_id
        reportClone.due_date = report_clone_due_date
        reportCloneValidationErrors = reportClone.validate()
        if not reportCloneValidationErrors:
          reportClone.save()
          print 'reportClone: saved'
      
      status = 200
      description = 'OK'
      if request.is_ajax:
        return Response(json.dumps({
          'html':render_template('_popup.html', title=g._t( 'report submit success' ), message=g._t( 'report submit success message' ), javascript="""setTimeout(function(){$('form[name=statistics-form]').submit(); $('form[name=filter-form]').submit();}, 300);"""),
          'status':status,
          'description':description,
          'errors':validationErrors
        }), mimetype='application/json')
      else:
        flash( g._t( 'report submit success' ) )
        return redirect( url_for( 'report_index', account_id=account_id ) )
    else:
      status = 400
      description = 'Bad request'
  else:
    status = 200
    description = 'OK'
    validationErrors = []
  
  if report.due_date:
    report_due_date_list.insert(0, report.due_date)
    
  report.due_date = ','.join(report_due_date_list)
  
  """
  If the report exists, but the account is no longer a member of the project, 
  we avoid an ability to change the project by keeping the only project option available
  """
  header = _activityHeader(employees=[account])
  projectList = header['projects']
  if report.id and report.component and not report.component in projectList:
    projectList = [report.component]
  
  if request.is_ajax:
    htmlContent = render_template('report/report.edit-popup.html', account=account, title=title, report=report, errors=validationErrors, projectList=projectList)
    return  Response(json.dumps({'html':htmlContent, 'status':status, 'description':description, 'errors':validationErrors}), mimetype='application/json')
  else:
    htmlContent = render_template('report/report.edit.html', account=account, title=title, report=report, errors=validationErrors, projectList=projectList)
    return htmlContent
コード例 #27
0
 def Report(self):
     return Report(self)
コード例 #28
0
ファイル: file_handler.py プロジェクト: jordantjh/re-root
    def print(self):
        """ Output result. """

        r = Report(self.output)
        r.print()
コード例 #29
0
ファイル: ks_crash.py プロジェクト: jarodl/KSCrashServer
def report(crash_id):
    report = Report.get(crash_id)
    return jsonify(report=report.__dict__)
コード例 #30
0
ファイル: test_report.py プロジェクト: ccoughlin/NDIToolbox
 def setUp(self):
     self.output_folder = os.path.join(os.path.dirname(__file__), "support_files")
     self.output_file = os.path.join(self.output_folder, "test_report.pdf")
     self.report = Report(self.output_file)
コード例 #31
0
class MainWindow(QMainWindow, Ui_mainWindow):
    """
    Main Application Window
    """
    def __init__(self, parent=None):
        """
        Initialize MainWindow class
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        thread = QThread()
        thread.currentThread().setObjectName(__appname__)
        configfn.check_config_folder()  # Check appdata folder in users home

        self.textWorkdate.setText(datetime.date.today().isoformat()
                                  )  # initialize workdate to current date

        self._archivedOrderlines = OrderLine()  # Initialize Detail object
        self._archivedVisits = Visit()  # Initialize Visit object
        self._contacts = Contact()  # Initialize Contact object
        self._customers = Customer()  # Initialize Customer object
        self._employees = Employee()  # Initialize Employee object
        self._orderLines = OrderLine()
        self._products = Product()  # Initialize Product object
        self._reports = Report()  # Initialize Report object
        self._settings = Settings()  # Initialize Settings object
        self._visits = Visit()

        self.buttonArchiveContacts.clicked.connect(self.archive_contacts)
        self.buttonArchiveCustomer.clicked.connect(self.archive_customer)
        self.buttonArchiveVisit.clicked.connect(self.archive_visit)

        self.buttonCreateContact.clicked.connect(self.create_contact)
        self.buttonCreateCustomer.clicked.connect(self.create_customer)
        self.buttonCreateReport.clicked.connect(self.create_report)
        self.buttonCreateVisit.clicked.connect(self.load_visit)

        self.buttonGetCustomers.clicked.connect(self.get_customers)
        self.buttonGetPricelist.clicked.connect(self.get_pricelist)

        self.toolButtonArchiveSettings.clicked.connect(self.archive_settings)
        self.toolButtonCustomer.clicked.connect(self.show_page_customer)
        self.toolButtonCustomers.clicked.connect(self.show_page_customers)
        self.toolButtonCustomerVisits.clicked.connect(
            self.show_page_customer_visits)
        self.toolButtonExit.clicked.connect(self.app_exit)
        self.toolButtonInfo.clicked.connect(self.show_page_info)
        self.toolButtonPricelist.clicked.connect(self.show_page_pricelist)
        self.toolButtonReport.clicked.connect(self.show_page_report)
        self.toolButtonReports.clicked.connect(self.show_page_reports)
        self.toolButtonSettings.clicked.connect(self.show_page_settings)
        self.toolButtonCustomerVisit.clicked.connect(self.show_page_visit)

        self.toolButtonDeleteSalesData.clicked.connect(self.zero_database)
        self.toolButtonExportDatabase.clicked.connect(self.data_export)
        self.toolButtonImportCsvData.clicked.connect(
            self.show_csv_import_dialog)
        self.toolButtonImportDatabase.clicked.connect(self.data_import)

        self.widgetCustomers.currentItemChanged.connect(
            self.on_customer_changed)
        self.widgetCustomers.itemDoubleClicked.connect(
            self.on_customer_double_clicked)

        self.widgetArchivedVisits.currentItemChanged.connect(
            self.on_visit_changed)
        self.widgetArchivedVisits.setColumnHidden(0, True)

        self.widgetArchivedOrderLines.setColumnWidth(0, 30)
        self.widgetArchivedOrderLines.setColumnWidth(1, 30)
        self.widgetArchivedOrderLines.setColumnWidth(2, 100)
        self.widgetArchivedOrderLines.setColumnWidth(3, 150)
        self.widgetArchivedOrderLines.setColumnWidth(4, 60)
        self.widgetArchivedOrderLines.setColumnWidth(5, 40)

        self.widgetCustomers.setColumnHidden(0, True)  # ID
        self.widgetCustomers.setColumnWidth(1, 100)
        self.widgetCustomers.setColumnWidth(2, 100)
        self.widgetCustomers.setColumnWidth(3, 100)
        self.widgetCustomers.setColumnWidth(4, 250)
        self.widgetCustomers.setColumnWidth(5, 60)

        self.widgetPricelist.setColumnWidth(0, 70)
        self.widgetPricelist.setColumnWidth(1, 100)
        self.widgetPricelist.setColumnWidth(2, 150)
        self.widgetPricelist.setColumnWidth(3, 50)
        self.widgetPricelist.setColumnWidth(4, 50)
        self.widgetPricelist.setColumnWidth(5, 50)
        self.widgetPricelist.setColumnWidth(6, 50)
        self.widgetPricelist.setColumnWidth(7, 50)
        self.widgetPricelist.setColumnWidth(8, 50)
        self.widgetPricelist.setColumnWidth(9, 50)
        self.widgetPricelist.setColumnWidth(10, 50)
        self.widgetPricelist.setColumnWidth(11, 50)
        self.widgetPricelist.setColumnWidth(12, 50)

        self.widgetReports.setColumnHidden(0, True)  # ID
        self.widgetReports.setColumnWidth(1, 80)  # rep_date
        self.widgetReports.setColumnWidth(2, 60)  # visits
        self.widgetReports.setColumnWidth(3, 60)  # sale day
        self.widgetReports.setColumnWidth(4, 60)  # demo day
        self.widgetReports.setColumnWidth(5, 100)  # turnover day
        self.widgetReports.setColumnWidth(6, 50)  # km
        # self.widgetReports column 7                # supervisor

        self.widgetReportVisits.setColumnWidth(0, 150)
        self.widgetReportVisits.setColumnWidth(1, 100)
        self.widgetReportVisits.setColumnWidth(2, 100)
        self.widgetReportVisits.setColumnWidth(3, 60)

        self.populate_customer_list()
        self.populate_price_list()

        try:
            cid = self._settings.settings["cust_idx"]
            if self._customers.lookup_by_id(cid):
                try:
                    self.widgetCustomers.setCurrentIndex(
                        self.widgetCustomers.indexFromItem(
                            self.widgetCustomers.findItems(str(
                                self._customers.customer["customer_id"]),
                                                           Qt.MatchExactly,
                                                           column=0)[0]))
                    self.toolButtonCustomer.click()
                except KeyError:
                    pass
        except KeyError:
            return

        self._reports.load(workdate=self.textWorkdate.text())
        self.populate_report_list()
        self.populate_report_visit_list()
        self.toolButtonReport.click()

    def closeEvent(self, event):
        """
        Slot for close event signal
        Args:
            event:

        intended use is warning about unsaved data
        """
        # TODO handle close event
        self.app_exit()

    def display_sync_status(self):
        """
        Update status fields
        """
        try:
            self.textCustomerLocalDate.setText(self._settings.settings["lsc"])
            self.textPricelistLocalDate.setText(self._settings.settings["lsp"])
            self.textCustomerServerDate.setText(self._settings.settings["sac"])
            self.textPricelistServerDate.setText(
                self._settings.settings["sap"])
        except KeyError:
            pass

    def populate_archived_visit_details(self):
        """
        Populate the details list based on the line visit
        """
        self.widgetArchivedOrderLines.clear()

        self.labelArchivedApprovedText.setText("")
        self.labelArchivedSendText.setText("")
        self.textArchivedOrderPoNumber.setText("")
        self.textArchivedOrderSale.setText("")
        self.textArchivedOrderSas.setText("")
        self.textArchivedOrderTotal.setText("")
        self.textArchivedVisitNote.setText("")

        items = []
        try:
            self.labelArchivedSendText.setText(
                utils.bool2dk(
                    utils.int2bool(self._archivedVisits.visit["po_sent"])))
            self.labelArchivedApprovedText.setText(
                utils.bool2dk(
                    utils.int2bool(self._archivedVisits.visit["po_approved"])))
            self.textArchivedOrderPoNumber.setText(
                self._archivedVisits.visit["po_number"])
            self.textArchivedOrderSale.setText(
                str(self._archivedVisits.visit["po_sale"]))
            self.textArchivedOrderSas.setText(
                str(self._archivedVisits.visit["po_sas"]))
            self.textArchivedOrderTotal.setText(
                str(self._archivedVisits.visit["po_total"]))
            self.textArchivedVisitNote.setText(
                self._archivedVisits.visit["visit_note"])

            self._archivedOrderlines.list_ = self._archivedVisits.visit[
                "visit_id"]
            for line in self._archivedOrderlines.list_:
                item = QTreeWidgetItem([
                    line["linetype"],
                    str(line["pcs"]), line["sku"], line["text"],
                    str(line["price"]),
                    str(line["discount"]), line["linenote"]
                ])
                items.append(item)
        except KeyError:
            pass
        except IndexError:
            pass
        self.widgetArchivedOrderLines.addTopLevelItems(items)

    def populate_archived_visits(self):
        """
        Populate the visitlist based on the active customer
        """
        self.widgetArchivedVisits.clear()

        items = []
        try:
            self._archivedVisits.list_by_customer(
                self._customers.customer["customer_id"])

            for visit in self._archivedVisits.visits:
                item = QTreeWidgetItem([
                    str(visit["visit_id"]), visit["visit_date"],
                    visit["po_buyer"], visit["prod_demo"], visit["prod_sale"],
                    visit["po_note"]
                ])
                items.append(item)
                if visit["visit_date"] == self.textWorkdate.text():
                    self.toolButtonCustomerVisit.setEnabled(True)

        except IndexError:
            pass
        except KeyError:
            pass
        self.widgetArchivedVisits.addTopLevelItems(items)

    def populate_contact_list(self):
        """
        Populate the contactlist based on currently selected customer
        """
        # load contacts
        self.widgetCustomerContacts.clear()
        items = []
        try:
            self._contacts.list_ = self._customers.customer["customer_id"]
            for c in self._contacts.list_:
                item = QTreeWidgetItem(
                    [c["name"], c["department"], c["phone"], c["email"]])
                items.append(item)
        except IndexError:
            pass
        except KeyError:
            pass

        self.widgetCustomerContacts.addTopLevelItems(items)

    def populate_customer_list(self):
        """
        Populate customer list
        """

        self.widgetCustomers.clear()  # shake the tree for leaves
        items = []  # temporary list
        try:
            for c in self._customers.customers:
                item = QTreeWidgetItem([
                    str(c["customer_id"]), c["account"], c["phone1"],
                    c["phone2"], c["company"], c["zipcode"], c["city"]
                ])
                items.append(item)
        except (IndexError, KeyError):
            pass
        # assign Widgets to Tree
        self.widgetCustomers.addTopLevelItems(items)
        self.widgetCustomers.setSortingEnabled(True)  # enable sorting

    def populate_price_list(self):
        """
        Populate widgetPricelist
        """
        self.widgetPricelist.clear()
        pricelist = []
        try:
            for product in self._products.products:
                item = QTreeWidgetItem([
                    product["item"], product["sku"], product["name1"],
                    str(product["price"]).format("#.##"),
                    str(product["d2"]).format("#.##"),
                    str(product["d4"]).format("#.##"),
                    str(product["d6"]).format("#.##"),
                    str(product["d8"]).format("#.##"),
                    str(product["d12"]).format("#.##"),
                    str(product["d24"]).format("#.##"),
                    str(product["d48"]).format("#.##"),
                    str(product["d96"]).format("#.##"),
                    str(product["net"]).format("#.##")
                ])
                pricelist.append(item)
        except IndexError as i:
            print("IndexError: {}".format(i))
        except KeyError as k:
            print("KeyError: {}".format(k))
        self.widgetPricelist.addTopLevelItems(pricelist)
        self.widgetPricelist.setSortingEnabled(True)

    def populate_report_list(self):
        """
        Populate widgetReports
        """
        self.widgetReports.clear()
        reports = []
        try:
            for report in self._reports.reports:
                item = QTreeWidgetItem([
                    str(report["report_id"]), report["rep_date"],
                    str(report["newvisitday"] + report["recallvisitday"]),
                    str(report["newdemoday"] + report["recalldemoday"]),
                    str(report["newsaleday"] + report["recallsaleday"]),
                    str(report["newturnoverday"] +
                        report["recallturnoverday"] +
                        report["sasturnoverday"]),
                    str(report["kmevening"] - report["kmmorning"]),
                    report["supervisor"]
                ])
                reports.append(item)
        except (IndexError, KeyError):
            pass
        self.widgetReports.addTopLevelItems(reports)

    def populate_report_visit_list(self):
        """
        Populate widgetReportVisits
        """
        self.widgetReportVisits.clear()
        items = []
        try:
            self._visits.list_by_date(self.textWorkdate.text())
            for v in self._visits.visits:
                c = self._customers.lookup_by_id(v["customer_id"])
                if c:
                    item = QTreeWidgetItem([
                        self._customers.customer["company"], v["prod_demo"],
                        v["prod_sale"], v["po_total"]
                    ])
                    items.append(item)
        except (IndexError, KeyError):
            pass
        self.widgetReportVisits.addTopLevelItems(items)

    def populate_settings_page(self):
        """
        Populate settings page
        :return:
        """
        try:
            self.textAppUserMail.setText(self._settings.settings["usermail"])
            self.textAppUserPass.setText(self._settings.settings["userpass"])
            self.textAppUserCountry.setText(
                self._settings.settings["usercountry"])
            self.textAppDataServer.setText(self._settings.settings["http"])
            self.textAppMailServer.setText(self._settings.settings["smtp"])
            self.textAppMailServerPort.setText(
                str(self._settings.settings["port"]))
            self.textAppMailOrderTo.setText(self._settings.settings["mailto"])
            self.checkServerData.setChecked(
                utils.int2bool(self._settings.settings["sc"]))
            self.textExtMailServer.setText(
                self._settings.settings["mailserver"])
            self.textExtMailServerPort.setText(
                str(self._settings.settings["mailport"]))
            self.textExtMailServerUser.setText(
                self._settings.settings["mailuser"])
            self.textExtMailServerPass.setText(
                self._settings.settings["mailpass"])
        except KeyError:
            pass

    def resizeEvent(self, event):
        """
        Slot for the resize event signal
        Args:
            event:
        intended use is resize content to window
        :param event:
        """
        # TODO handle resize event
        # w = event.size().width()
        # h = event.size().height()
        # dpival = self.labelAvailable.devicePixelRatio()
        # dpivalf = self.labelAvailable.devicePixelRatioF()
        # dpivalfs = self.labelAvailable.devicePixelRatioFScale()
        # dpilogx = self.labelAvailable.logicalDpiX()
        # dpilogy = self.labelAvailable.logicalDpiY()
        #
        # winch = w/dpival
        # hinch = h/dpival
        # print("width = {}\n"
        #       "height = {}\n"
        #       "dpi = {}\n"
        #       "dpi f = {}\n"
        #       "w inch = {}\n"
        #       "h inch = {}\n"
        #       "dpi fs = {}\n"
        #       "dpi log x = {}\n"
        #       "dpi log y = {}".format(w, h, dpival, dpivalf, winch, hinch, dpivalfs, dpilogx, dpilogy))
        pass

    def run(self):
        """
        Setup database and basic configuration
        """
        # basic settings must be done
        is_set = check_settings(self._settings.settings)
        if is_set:
            try:
                _ = self._employees.employee["fullname"]
            except KeyError:
                msgbox = QMessageBox()
                msgbox.about(
                    self, __appname__,
                    "Der er en fejl i dine indstillinger.\nKontroller dem venligst.\nTak."
                )
        else:
            msgbox = QMessageBox()
            msgbox.about(
                self, __appname__,
                "App'en skal bruge nogle oplysninger.\nRing kontoret hvis du er i tvivl.\nTak."
            )

            self.show_page_settings()

        # if requested check server data
        try:
            if utils.int2bool(self._settings.settings["sc"]):
                # update sync status
                status = utils.refresh_sync_status(self._settings)
                self._settings.settings["sac"] = status[0][1].split()[0]
                self._settings.settings["sap"] = status[1][1].split()[0]
                self._settings.update()
        except KeyError:
            pass

        # display known sync data
        self.display_sync_status()

    def set_indexes(self):
        """
        Save page index to settings
        :return:
        """
        try:
            self._settings.settings["cust_idx"] = self._customers.customer[
                "customer_id"]
        except KeyError:
            self._settings.settings["cust_idx"] = 0

        try:
            _ = self._settings.settings["page_idx"]
        except KeyError:
            self._settings.settings[
                "page_idx"] = self.widgetAppPages.currentIndex()
        self._settings.update()

    def set_input_enabled(self, arg: bool) -> None:
        """Enable inputs"""
        self.checkVisitSas.setEnabled(arg)
        self.comboOrderItem.setEnabled(arg)
        self.comboOrderSku.setEnabled(arg)
        self.textVisitPcs.setEnabled(arg)
        self.textVisitLinePrice.setEnabled(arg)
        self.textVisitLineDiscount.setEnabled(arg)

    @pyqtSlot(name="app_exit")
    def app_exit(self):
        """
        Exit - save current customer
        """
        # customer id
        try:
            self._settings.settings["cust_idx"] = self._customers.customer[
                "customer_id"]
        except KeyError:
            self._settings.settings["cust_idx"] = 0
        self._settings.update()
        app.quit()

    @pyqtSlot(name="archive_contacts")
    def archive_contacts(self):
        """
        Save changes made to contacts
        """
        # TODO save changes made to contacts
        msgbox = QMessageBox()
        msgbox.information(self, __appname__,
                           "# TODO save changes made to contacts",
                           QMessageBox.Ok)

    @pyqtSlot(name="archive_customer")
    def archive_customer(self):
        """
        Slot for updateCustomer triggered signal
        """
        if not self._customers.customer:
            # msgbox triggered if no current is selected
            msgbox = QMessageBox()
            msgbox.information(self, __appname__,
                               "Det kan jeg ikke på nuværende tidspunkt!",
                               QMessageBox.Ok)
            return False
        # assign input field values to current object
        self._customers.customer["company"] = self.textCompany.text()
        self._customers.customer["address1"] = self.textAddress1.text()
        self._customers.customer["address2"] = self.textAddress2.text()
        self._customers.customer["zipcode"] = self.textZipCode.text()
        self._customers.customer["city"] = self.textCityName.text()
        self._customers.customer["phone1"] = self.textPhone1.text()
        self._customers.customer["phone2"] = self.textPhone2.text()
        self._customers.customer["email"] = self.textEmail.text()
        self._customers.customer["factor"] = self.textFactor.text()
        self._customers.customer[
            "infotext"] = self.textArchivedVisitNote.toPlainText()
        self._customers.customer["modified"] = 1
        self._customers.update()

    @pyqtSlot(name="archive_settings")
    def archive_settings(self):
        """
        Archive settings
        :return:
        """
        checkok = True
        items = []
        if self.textAppUserMail.text() == "":
            items.append("Gruppe 'Sælger' -> 'Email'")
            checkok = False
        if self.textAppUserPass.text() == "":
            items.append("Gruppe 'Sælger' -> 'Adgangsfrase'")
            checkok = False
        if self.textAppUserCountry.text() == "":
            items.append("Gruppe: Sælger -> landekode")
            checkok = False
        if self.textAppMailServer.text() == "":
            items.append("Gruppe: Intern -> Mailserver")
            checkok = False
        if self.textAppMailServerPort.text() == "":
            items.append("Gruppe: Intern -> Port")
            checkok = False
        if self.textAppMailOrderTo == "":
            items.append("Gruppe: Intern -> Mail til")
            checkok = False
        if self.textAppDataServer == "":
            items.append("Gruppe: Intern -> Dataserver")
            checkok = False
        # inform user about settings validity
        msgbox = QMessageBox()
        if not checkok:
            msgbox.warning(
                self, __appname__,
                "Der er mangler i dine indstillinger!\n{}".format(
                    "\n".join(items)), QMessageBox.Ok)
            return False
        # update password in settings
        if len(self.textAppUserPass.text()) < 97:
            self._settings.settings["userpass"] = passwdFn.hash_password(
                self.textAppUserPass.text())
        if len(self.textExtMailServerPass.text()) < 97:
            self._settings.settings["mailpass"] = passwdFn.hash_password(
                self.textExtMailServerPass.text())
        self._settings.settings["usermail"] = self.textAppUserMail.text(
        ).lower()
        self._settings.settings["usercountry"] = self.textAppUserCountry.text()
        self._settings.settings["http"] = self.textAppDataServer.text()
        self._settings.settings["smtp"] = self.textAppMailServer.text()
        self._settings.settings["port"] = self.textAppMailServerPort.text()
        self._settings.settings["mailto"] = self.textAppMailOrderTo.text()
        self._settings.settings["sc"] = utils.bool2int(
            self.checkServerData.isChecked())
        self._settings.settings["mailserver"] = self.textExtMailServer.text(
        ).lower()
        self._settings.settings["mailport"] = self.textExtMailServerPort.text()
        self._settings.settings["mailuser"] = self.textExtMailServerUser.text()
        self._settings.update()
        self._employees.load(self._settings.settings["usermail"])
        msgbox.information(self, __appname__, "Indstillinger opdateret.",
                           QMessageBox.Ok)

    @pyqtSlot(name="archive_visit")
    def archive_visit(self):
        """
        Slot for saving the visit
        """
        self.toolButtonCustomerVisit.setEnabled(False)
        # save visit head contents
        self._visits.visit["po_buyer"] = self.textVisitBuyer.text()
        self._visits.visit["po_number"] = self.textVisitPoNumber.text()
        self._visits.visit["po_company"] = self.textVisitDelCompany.text()
        self._visits.visit["po_address1"] = self.textVisitDelAddress1.text()
        self._visits.visit["po_address2"] = self.textVisitDelAddress2.text()
        self._visits.visit["po_postcode"] = self.textVisitDelZip.text()
        self._visits.visit["po_postofffice"] = self.textVisitDelCity.text()
        self._visits.visit["po_country"] = self._employees.employee["country"]
        self._visits.visit["po_note"] = self.textVisitOrderNote.text()
        self._visits.visit["prod_demo"] = self.textVisitProductDemo.text()
        self._visits.visit["prod_sale"] = self.textVisitProductSale.text()
        self._visits.visit["po_sas"] = self.textVisitSas.text()
        self._visits.visit["po_sale"] = self.textVisitSale.text()
        self._visits.visit["po_total"] = self.textVisitTotal.text()
        self._visits.visit["visit_note"] = self.textVisitInfo.toPlainText()

        # TODO: save visitdetails

    @pyqtSlot(name="create_contact")
    def create_contact(self):
        """
        Save changes made to contacts
        """
        # TODO add new contact
        msgbox = QMessageBox()
        msgbox.information(self, __appname__, "# TODO add new contact",
                           QMessageBox.Ok)

    @pyqtSlot(name="create_customer")
    def create_customer(self):
        """
        Slot for createCustomer triggered signal
        """
        if not self.textNewCompany.text() or not self.textNewPhone1.text():
            msgbox = QMessageBox()
            msgbox.information(
                self, __appname__,
                "Snap - Jeg mangler:\n Firma navn \n Telefon nummer",
                QMessageBox.Ok)
        else:
            msgbox = QMessageBox()
            msgbox.information(
                self, __appname__, "Gem kunde til database\n\n" +
                self.textNewCompany.text() + "\n" + self.textNewPhone1.text(),
                QMessageBox.Ok)

    @pyqtSlot(name="create_report")
    def create_report(self):
        """
        Slot for Report triggered signal
        """
        try:
            # check the report date
            # no report triggers KeyError which in turn launches the CreateReportDialog
            repdate = self._reports.report["rep_date"]
            if not repdate == self.textWorkdate.text():
                # if active report is not the same replace it with workdate
                self._reports.load(self.textWorkdate.text())
                # trigger a KeyError if no report is current which launches the CreateReportDialog
                repdate = self._reports.report["rep_date"]
                # check if the report is sent
                if self._reports.report["sent"] == 1:
                    # we do not allow visits to be created on a report which is closed
                    self.buttonCreateVisit.setEnabled(False)
                else:
                    self.buttonCreateVisit.setEnabled(True)
            infotext = "Rapport aktiv for: {}".format(repdate)
            msgbox = QMessageBox()
            msgbox.information(self, __appname__, infotext, QMessageBox.Ok)
            return True

        except KeyError:
            # Show report dialog
            create_report_dialog = ReportDialogCreate(self.textWorkdate.text())
            if create_report_dialog.exec_():
                # user chosed to create a report
                self.textWorkdate.setText(create_report_dialog.workdate)
                # try load a report for that date
                self._reports.load(self.textWorkdate.text())
                try:
                    # did the user choose an existing report
                    _ = self._reports.report["rep_date"]
                    infotext = "Eksisterende rapport hentet: {}".format(
                        self.textWorkdate.text())
                except KeyError:
                    # create the report
                    self._reports.create(self._employees.employee,
                                         self.textWorkdate.text())
                    infotext = "Rapport Createtet for: {}".format(
                        self.textWorkdate.text())
                msgbox = QMessageBox()
                msgbox.information(self, __appname__, infotext, QMessageBox.Ok)
                return True
            else:
                msgbox = QMessageBox()
                msgbox.information(
                    self, __appname__,
                    "Den aktive rapport er <strong>IKKE</strong> ændret!",
                    QMessageBox.Ok)
                return False

    @pyqtSlot(name="load_visit")
    def load_visit(self):
        """
        Slot for loading the visit dialog
        """

        try:
            # do we have a report
            _ = self._reports.report["rep_date"]
            active_report = True
        except KeyError:
            active_report = self.create_report()

        if active_report:
            self._reports.load(workdate=self.textWorkdate.text())
            try:
                # do we have a customer
                _ = self._customers.customer["company"]
            except KeyError:
                msgbox = QMessageBox()
                msgbox.information(
                    self, __appname__,
                    "Ingen valgt kunde! Besøg kan ikke oprettes.",
                    QMessageBox.Ok)
                return

        if self.textCustId.text() is not "" and \
                self.textCustId.text() is not self._customers.customer["customer_id"]:
            confirm = QMessageBox()
            val = confirm.question(
                self, __appname__,
                f"Du har et uafsluttet besøg på {self.textVisitCompany.text()}."
                f"<br/>Vil du slette det?", confirm.Yes | confirm.No)
            if val == confirm.No:
                self._customers.lookup_by_id(self.textCustId.text())
            else:
                self._archivedVisits.delete(self.textVisitId.text())

        self.toolButtonCustomerVisit.setEnabled(True)
        # self.widgetAppPages.setCurrentIndex(PAGE_VISIT)

        customer_pricelist = self._products
        workdate = self.textWorkdate.text()
        customerid = self._customers.customer["customer_id"]
        reportid = self._reports.report["report_id"]
        employeeid = self._employees.employee["employee_id"]

        self.textCustId.setText(str(customerid))
        self.textVisitDate.setText(self.textWorkdate.text())
        self.textVisitCompany.setText(self._customers.customer["company"])

        try:
            """
            load visits for workdate
            """
            self._visits.list_by_date(workdate)
            self.textVisitId.setText(str(self._visits.visit["visit_id"]))
        except (KeyError, ):
            self.textVisitId.setText(
                str(
                    self._visits.add(reportid, employeeid, customerid,
                                     workdate)))
            self._visits.visit["visit_type"] = "R"
            if self._customers.customer["account"] == "NY":
                self._visits.visit["visit_type"] = "N"

        visit_id = self.textVisitId.text()
        self._orderLines = OrderLine()
        self._orderLines.load_visit(visit_id)

        self.widgetTableSale.setColumnWidth(0, 43)  # line_type D/N/S
        self.widgetTableSale.setColumnWidth(1, 44)  # pcs
        self.widgetTableSale.setColumnWidth(2, 44)  # item
        self.widgetTableSale.setColumnWidth(3, 123)  # sku
        self.widgetTableSale.setColumnWidth(4, 153)  # text
        self.widgetTableSale.setColumnWidth(5, 60)  # price
        self.widgetTableSale.setColumnWidth(6, 50)  # discount
        self.widgetTableSale.setColumnWidth(6, 60)  # amount
        self.widgetTableSale.setColumnWidth(7, 30)  # SAS

        lines = self._orderLines.list_
        visit_sale = 0.0
        visit_sas = 0.0
        visit_total = 0.0
        line_demo = 0
        line_sale = 0
        row_number = 0
        self.widgetTableSale.setRowCount(len(lines) - 1)
        for line in lines:
            # "line_id", "visit_id",
            # "pcs", "sku", "text", "price", "sas", "discount",
            # "linetype", "linenote", "item"
            amount = float(
                line["pcs"]) * line["price"] * line["discount"] / 100
            if line["sas"] == 1:
                visit_sas += amount
            else:
                visit_sale += amount
            visit_total += amount

            # self.widgetTableSale.setRowHeight(row_number, 12)
            if line["linetype"].lower() == "d":
                line_demo += 1
                row_number = line_demo
                self.widgetTableDemo.setRowCount(row_number)

                c1 = QTableWidgetItem()
                c1.setText(line["linetype"])
                self.widgetTableDemo.setItem(row_number, 0, c1)
                c2 = QTableWidgetItem()
                c2.setText(str(line["pcs"]))
                self.widgetTableDemo.setItem(row_number, 1, c2)
                c3 = QTableWidgetItem()
                c3.setText(str(line["item"]))
                self.widgetTableDemo.setItem(row_number, 2, c3)
            else:
                line_sale += 1
                row_number = line_sale
                self.widgetTableSale.setRowCount(row_number)

                c1 = QTableWidgetItem()
                c1.setText(line["linetype"])
                self.widgetTableSale.setItem(row_number, 0, c1)
                c2 = QTableWidgetItem()
                c2.setText(str(line["pcs"]))
                self.widgetTableSale.setItem(row_number, 1, c2)
                c3 = QTableWidgetItem()
                c3.setText(str(line["item"]))
                self.widgetTableSale.setItem(row_number, 2, c3)
                c4 = QTableWidgetItem()
                c4.setText(line["sku"])
                self.widgetTableSale.setItem(row_number, 3, c4)
                c5 = QTableWidgetItem()
                c5.setText(line["text"])
                self.widgetTableSale.setItem(row_number, 4, c5)
                c6 = QTableWidgetItem()
                c6.setText(str(line["price"]))
                self.widgetTableSale.setItem(row_number, 5, c6)
                c7 = QTableWidgetItem()
                c6.setText(str(line["discount"]))
                self.widgetTableSale.setItem(row_number, 6, c7)
                c9 = QTableWidgetItem()
                c9.setText(utils.int2strdk(line["sas"]))
                self.widgetTableSale.setItem(row_number, 7, c9)
                c10 = QTableWidgetItem()
                c10.setText(line["linenote"])
                self.widgetTableSale.setItem(row_number, 8, c10)

        # Setup pricelist and selection combos
        factor = self._customers.customer["factor"]
        if not factor:
            factor = 0.0

        for item in customer_pricelist.products:
            if factor is not 0.0:
                item["price"] = item["price"] * factor
                item["d2"] = item["d2"] * factor
                item["d3"] = item["d3"] * factor
                item["d4"] = item["d4"] * factor
                item["d6"] = item["d6"] * factor
                item["d8"] = item["d8"] * factor
                item["d12"] = item["d12"] * factor
                item["d24"] = item["d24"] * factor
                item["d48"] = item["d48"] * factor
                item["d96"] = item["d96"] * factor
                item["min"] = item["min"] * factor
                item["net"] = item["net"] * factor
            self.comboLineItem.addItem(item["item"],
                                       [item["sku"], item["name1"], item])
            self.comboLineSku.addItem(item["sku"],
                                      [item["item"], item["name1"], item])

        # connect to signals
        self.buttonArchiveVisit.clicked.connect(self.archive_visit)
        self.comboOrderItem.currentIndexChanged.connect(
            self.on_order_item_changed)
        self.comboOrderSku.currentIndexChanged.connect(
            self.on_order_sku_changed)
        self.comboOrderSku.editTextChanged.connect(self.on_order_sku_changed)

    @pyqtSlot(name="data_export")
    def data_export(self):
        """
        Export Database backup file
        """
        # TODO: Create CSV data backup
        msgbox = QMessageBox()
        msgbox.information(self, __appname__,
                           "TODO: Create Database Backup File", QMessageBox.Ok)

    @pyqtSlot(name="data_import")
    def data_import(self):
        """
        Import Database backup file
        """
        # TODO: Restore from CSV data backup
        msgbox = QMessageBox()
        msgbox.information(self, __appname__,
                           "TODO: Import Database Backup File", QMessageBox.Ok)

    @pyqtSlot(name="get_customers")
    def get_customers(self):
        """
        Slot for getCustomers triggered signal
        """
        import_customers = GetCustomersDialog(app,
                                              customers=self._customers,
                                              employees=self._employees,
                                              settings=self._settings)
        import_customers.sig_done.connect(self.on_get_customers_done)
        import_customers.exec_()

    @pyqtSlot(name="get_pricelist")
    def get_pricelist(self):
        """
        Slot for getProducts triggered signal
        """
        import_product = GetPricelistDialog(app,
                                            products=self._products,
                                            settings=self._settings)
        import_product.sig_done.connect(self.on_get_products_done)
        import_product.exec_()

    @pyqtSlot(name="on_add_demo")
    def on_add_demo(self):
        """
        Add line to product demo table
        :return:
        """
        row_count = self.widgetTableDemo.rowCount()
        self.widgetTableDemo.setRowCount(row_count + 1)

    @pyqtSlot(name="on_add_sale")
    def on_add_sale(self):
        """
        Add line to product sale table
        :return:
        """
        row_count = self.widgetTableSale.rowCount()
        self.widgetTableSale.setRowCount(row_count + 1)

    @pyqtSlot(name="on_remove_demo")
    def on_remove_demo(self):
        """
        Remove line from product demo table
        :return:
        """
        if self.widgetTableDemo.currentIndex():
            self.widgetTableDemo.removeRow(self.widgetTableDemo.currentIndex())

    @pyqtSlot(name="on_remove_sale")
    def on_remove_sale(self):
        """
        Remove line from product sale table
        :return:
        """
        if self.widgetTableSale.currentIndex():
            self.widgetTableSale.removeRow(self.widgetTableSale.currentIndex())

    @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem, name="on_customer_changed")
    def on_customer_changed(self, current, previous):
        """
        Slot for treewidget current item changed signal
        Used to respond to changes in the customer list
        and update the related customer info

        Args:
            current: currently selected item
            previous: previous selected item
        """
        try:
            # account = current.text(0)
            phone = current.text(2)
            company = current.text(4)
            # load customer
            self._customers.lookup(phone, company)
            # fill out fields
            self.textAccount.setText(self._customers.customer["account"])
            self.textCompany.setText(self._customers.customer["company"])
            self.textAddress1.setText(self._customers.customer["address1"])
            self.textAddress2.setText(self._customers.customer["address2"])
            self.textZipCode.setText(self._customers.customer["zipcode"])
            self.textCityName.setText(self._customers.customer["city"])
            self.textPhone1.setText(self._customers.customer["phone1"])
            self.textPhone2.setText(self._customers.customer["phone2"])
            self.textEmail.setText(self._customers.customer["email"])
            self.textFactor.setText(str(self._customers.customer["factor"]))
            self.textCustomerNotes.setText(
                self._customers.customer["infotext"])
            self.textCustomerNameCreateVisit.setText(
                self._customers.customer["company"])
        except AttributeError:
            pass
        except KeyError:
            pass
        # load customer infos
        self.populate_contact_list()
        self.populate_archived_visits()
        self.populate_archived_visit_details()
        self.load_visit()

    @pyqtSlot(name="on_csv_import_done")
    def on_csv_import_done(self):
        """
        Slog for csv import done signal
        """
        self.populate_customer_list()

    @pyqtSlot(QTreeWidgetItem, name="on_customer_clicked")
    def on_customer_double_clicked(self, current):
        """
        Customer selected in
        :param current:
        :return:
        """
        print("current: {}".format(current))
        self.toolButtonCustomer.click()

    @pyqtSlot(name="on_get_customers_done")
    def on_get_customers_done(self):
        """
        Slot for getCustomers finished signal
        """
        self.populate_customer_list()
        lsc = datetime.date.today().isoformat()
        self.textCustomerLocalDate.setText(lsc)
        self._settings.settings["lsc"] = lsc
        self._settings.update()

    @pyqtSlot(name="on_get_products_done")
    def on_get_products_done(self):
        """
        Slot for getProducts finished signal
        """
        _ = self._products.products
        lsp = datetime.date.today().isoformat()
        self.textPricelistLocalDate.setText(lsp)
        self._settings.settings["lsp"] = lsp
        self._settings.update()

    @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem, name="on_visit_changed")
    def on_visit_changed(self, current, previous):
        """
        Response to current visit changed
        Args:
            current:
            previous:
        """
        try:
            self._archivedVisits.load_visit(current.text(0))
        except AttributeError:
            pass
        except KeyError:
            pass
        self.populate_archived_visit_details()

    @pyqtSlot(name="on_order_item_changed")
    def on_order_item_changed(self):
        """Update SKU combo when item changes"""
        self.comboOrderSku.setCurrentText(
            self.comboOrderItem.itemData(
                self.comboOrderItem.currentIndex())[0])
        self.update_orderline_text(
            self.comboOrderItem.itemData(
                self.comboOrderItem.currentIndex())[1])
        utils.item_price(
            self.comboOrderItem.itemData(
                self.comboOrderItem.currentIndex())[3],
            self.textVisitPcs.text())

    @pyqtSlot(name="on_order_sku_changed")
    def on_order_sku_changed(self):
        """Update ITEM combo when sku changes"""
        self.comboOrderItem.setCurrentText(
            self.comboOrderSku.itemData(self.comboOrderSku.currentIndex())[0])
        self.update_orderline_text(
            self.comboOrderSku.itemData(self.comboOrderSku.currentIndex())[1])
        utils.item_price(
            self.comboOrderSku.itemData(self.comboOrderSku.currentIndex()[3]),
            self.textVisitPcs.text())

    def update_orderline_text(self, text):
        self.textVisitLineText.setText(text)

    @pyqtSlot(name="show_csv_import_dialog")
    def show_csv_import_dialog(self):
        """
        Slot for fileImport triggered signal
        """
        if self._customers.customers:
            msgbox = QMessageBox()
            msgbox.warning(
                self, __appname__,
                "<strong>Ved import slettes alle eksisterende data</strong>!<br/><br/>"
                "Det er alt eller intet af hensyn til datas sammenhæng.<br/>"
                "Du <strong>SKAL</strong> importere <strong>ALLE<strong> tabeller fra listen!<br/><br/>"
                "<strong>Gør du ikke det giver det uløselige problemer</strong>!",
                QMessageBox.Ok)
        # app, contact, customer, detail, employee, report, visit, tables
        import_dialog = CsvFileImportDialog(
            app,
            contacts=self._contacts,
            customers=self._customers,
            employees=self._employees,
            orderlines=self._archivedOrderlines,
            reports=self._reports,
            tables=config.CSV_TABLES,
            visits=self._archivedVisits)
        import_dialog.sig_done.connect(self.on_csv_import_done)
        import_dialog.exec_()

    @pyqtSlot(name="show_page_customer")
    def show_page_customer(self):
        """
        Show page with customer
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_CUSTOMER)

    @pyqtSlot(name="show_page_customer_visits")
    def show_page_customer_visits(self):
        """
        Show page with customer visits and orders
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_CUSTOMER_VISITS)

    @pyqtSlot(name="show_page_customers")
    def show_page_customers(self):
        """
        Show page with customer list
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_CUSTOMERS)

    @pyqtSlot(name="show_page_info")
    def show_page_info(self):
        """
        Show page with about Qt and Eordre
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_INFO)

    @pyqtSlot(name="show_page_pricelist")
    def show_page_pricelist(self):
        """
        Show page with pricelist
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_PRICELIST)

    @pyqtSlot(name="show_page_report")
    def show_page_report(self):
        """
        Slot for masterData triggered signal
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_REPORT)

    @pyqtSlot(name="show_page_reports")
    def show_page_reports(self):
        """
        Show page with a report list
        """
        self.set_indexes()
        self.widgetAppPages.setCurrentIndex(PAGE_REPORTS)

    @pyqtSlot(name="show_page_settings")
    def show_page_settings(self):
        """
        Show page with settings
        """
        self.set_indexes()
        self.populate_settings_page()
        self.widgetAppPages.setCurrentIndex(PAGE_SETTINGS)

    @pyqtSlot(name="show_page_visit")
    def show_page_visit(self):
        """
        Show page with visit
        """
        self.set_indexes()
        self.load_visit()
        self.widgetAppPages.setCurrentIndex(PAGE_VISIT)

    @pyqtSlot(name="zero_database")
    def zero_database(self):
        """
        Slot for zeroDatabase triggered signal
        """
        confirm = QMessageBox()
        val = confirm.question(self, __appname__,
                               "Alle salgsdata slettes<br/>Vil du fortsætte?",
                               confirm.Yes | confirm.No)

        if val == confirm.Yes:
            self._contacts.recreate_table()
            self._customers.recreate_table()
            self._archivedOrderlines.recreate_table()
            self._archivedVisits.recreate_table()
            self._reports.recreate_table()

            self.populate_contact_list()
            self.populate_archived_visit_details()
            self.populate_archived_visits()
            self.populate_customer_list()

            self._settings.settings["lsc"] = ""
            self._settings.settings["sac"] = ""
            self._settings.settings["lsp"] = ""
            self._settings.settings["sap"] = ""
            self._settings.update()
            self.display_sync_status()

            msgbox = QMessageBox()
            msgbox.information(self, __appname__, "Salgsdata er nulstillet!",
                               QMessageBox.Ok)
コード例 #32
0
ファイル: ks_crash.py プロジェクト: jarodl/KSCrashServer
def reports():
    reports = Report.all()
    reports = [report.__dict__ for report in reports]
    return jsonify(reports=reports)
コード例 #33
0
ファイル: test_report.py プロジェクト: endymecy/NDIToolbox
class TestReport(unittest.TestCase):
    """Functional testing for the Report class"""
    def setUp(self):
        self.output_folder = os.path.join(os.path.dirname(__file__),
                                          "support_files")
        self.output_file = os.path.join(self.output_folder, "test_report.pdf")
        self.report = Report(self.output_file)

    def generate_sample_plot(self,
                             output_filename,
                             width=5,
                             height=5,
                             title="Sample Data"):
        """Generates a sample plot of random data"""
        # Initialize matplotlib plot formatting to sane defaults
        mainmodel.init_matplotlib_defaults()
        figure = Figure(figsize=(width, height))
        canvas = FigureCanvas(figure)
        axes = figure.gca()
        x = np.arange(-10, 10)
        data = np.sinc(x + random.uniform(-.25, .25))
        linestyles = ['_', '-', '--', ':']
        colors = ('b', 'g', 'r', 'c', 'm', 'y', 'k')
        axes.plot(x,
                  data,
                  linestyle=random.choice(linestyles),
                  marker=".",
                  color=random.choice(colors))
        axes.set_title(title)
        axes.grid(True)
        figure.savefig(output_filename, format='png')

    def generate_sample_table(self, rows=3, cols=4, header=None):
        """Generates and returns a 2D list suitable for inclusion in a Report as a table.
        If the list header is included, it is prepended to the table as its header."""
        def random_content():
            """Returns some random content for a cell"""
            coin_flip = random.choice([0, 1])
            if coin_flip == 0:
                return random.choice([
                    "Sample Text", "", "Alternate Text", "Lorem Ipsum",
                    os.path.basename(self.output_file)
                ])
            else:
                return random.uniform(-25, 25)

        table = []
        if header is not None:
            table.append(header)
        for r in range(rows):
            row = []
            for c in range(cols):
                row.append(random_content())
            table.append(row)
        return table

    def test_generate_report(self):
        """Functional test to verify generating a PDF report"""
        self.report.front_matter = os.path.join(self.output_folder,
                                                "Sample Front Matter.pdf")
        self.report.end_matter = os.path.join(self.output_folder,
                                              "Sample End Matter.pdf")
        lorem_file = os.path.join(self.output_folder, "loremipsum.txt")
        with open(lorem_file, "r") as fidin:
            sample_text = fidin.readlines()
        for i in range(5):
            output_filename = os.path.join(self.output_folder,
                                           "plot{0}.png".format(i + 1))
            self.generate_sample_plot(output_filename,
                                      title="Plot {0}".format(i + 1))
            heading = "Section {0}".format(i + 1)
            a_section = ReportSection(heading)
            caption = "Sample caption for plot {0}".format(i + 1)
            start_idx = random.randint(0, len(sample_text))
            end_idx = start_idx + random.randint(0,
                                                 len(sample_text) - start_idx)
            text = sample_text[start_idx:end_idx]
            if i % 2 == 0:
                _t = self.generate_sample_table(
                    header=["Col 1", "Col 2", "Col 3"])
                _t_caption = "A sample table"
                a_section.add_table(_t, caption=_t_caption)
            a_section.add_figure(output_filename, caption=caption)
            a_section.add_text(text)
            self.report.sections.append(a_section)
        self.report.write()
        print("Please examine the PDF output file {0}.".format(
            self.output_file))

    def tearDown(self):
        pngs = os.listdir(self.output_folder)
        for png in pngs:
            root, ext = os.path.splitext(png)
            if 'plot' in root and 'png' in ext:
                try:
                    os.remove(os.path.join(self.output_folder, png))
                except WindowsError:  # Windows reports file in use
                    pass
                except OSError:  # Other operating system error
                    print("Unable to delete test output file {0}.".format(png))
コード例 #34
0
    def __init__(self, parent=None):
        """
        Initialize MainWindow class
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        thread = QThread()
        thread.currentThread().setObjectName(__appname__)
        configfn.check_config_folder()  # Check appdata folder in users home

        self.textWorkdate.setText(datetime.date.today().isoformat()
                                  )  # initialize workdate to current date

        self._archivedOrderlines = OrderLine()  # Initialize Detail object
        self._archivedVisits = Visit()  # Initialize Visit object
        self._contacts = Contact()  # Initialize Contact object
        self._customers = Customer()  # Initialize Customer object
        self._employees = Employee()  # Initialize Employee object
        self._orderLines = OrderLine()
        self._products = Product()  # Initialize Product object
        self._reports = Report()  # Initialize Report object
        self._settings = Settings()  # Initialize Settings object
        self._visits = Visit()

        self.buttonArchiveContacts.clicked.connect(self.archive_contacts)
        self.buttonArchiveCustomer.clicked.connect(self.archive_customer)
        self.buttonArchiveVisit.clicked.connect(self.archive_visit)

        self.buttonCreateContact.clicked.connect(self.create_contact)
        self.buttonCreateCustomer.clicked.connect(self.create_customer)
        self.buttonCreateReport.clicked.connect(self.create_report)
        self.buttonCreateVisit.clicked.connect(self.load_visit)

        self.buttonGetCustomers.clicked.connect(self.get_customers)
        self.buttonGetPricelist.clicked.connect(self.get_pricelist)

        self.toolButtonArchiveSettings.clicked.connect(self.archive_settings)
        self.toolButtonCustomer.clicked.connect(self.show_page_customer)
        self.toolButtonCustomers.clicked.connect(self.show_page_customers)
        self.toolButtonCustomerVisits.clicked.connect(
            self.show_page_customer_visits)
        self.toolButtonExit.clicked.connect(self.app_exit)
        self.toolButtonInfo.clicked.connect(self.show_page_info)
        self.toolButtonPricelist.clicked.connect(self.show_page_pricelist)
        self.toolButtonReport.clicked.connect(self.show_page_report)
        self.toolButtonReports.clicked.connect(self.show_page_reports)
        self.toolButtonSettings.clicked.connect(self.show_page_settings)
        self.toolButtonCustomerVisit.clicked.connect(self.show_page_visit)

        self.toolButtonDeleteSalesData.clicked.connect(self.zero_database)
        self.toolButtonExportDatabase.clicked.connect(self.data_export)
        self.toolButtonImportCsvData.clicked.connect(
            self.show_csv_import_dialog)
        self.toolButtonImportDatabase.clicked.connect(self.data_import)

        self.widgetCustomers.currentItemChanged.connect(
            self.on_customer_changed)
        self.widgetCustomers.itemDoubleClicked.connect(
            self.on_customer_double_clicked)

        self.widgetArchivedVisits.currentItemChanged.connect(
            self.on_visit_changed)
        self.widgetArchivedVisits.setColumnHidden(0, True)

        self.widgetArchivedOrderLines.setColumnWidth(0, 30)
        self.widgetArchivedOrderLines.setColumnWidth(1, 30)
        self.widgetArchivedOrderLines.setColumnWidth(2, 100)
        self.widgetArchivedOrderLines.setColumnWidth(3, 150)
        self.widgetArchivedOrderLines.setColumnWidth(4, 60)
        self.widgetArchivedOrderLines.setColumnWidth(5, 40)

        self.widgetCustomers.setColumnHidden(0, True)  # ID
        self.widgetCustomers.setColumnWidth(1, 100)
        self.widgetCustomers.setColumnWidth(2, 100)
        self.widgetCustomers.setColumnWidth(3, 100)
        self.widgetCustomers.setColumnWidth(4, 250)
        self.widgetCustomers.setColumnWidth(5, 60)

        self.widgetPricelist.setColumnWidth(0, 70)
        self.widgetPricelist.setColumnWidth(1, 100)
        self.widgetPricelist.setColumnWidth(2, 150)
        self.widgetPricelist.setColumnWidth(3, 50)
        self.widgetPricelist.setColumnWidth(4, 50)
        self.widgetPricelist.setColumnWidth(5, 50)
        self.widgetPricelist.setColumnWidth(6, 50)
        self.widgetPricelist.setColumnWidth(7, 50)
        self.widgetPricelist.setColumnWidth(8, 50)
        self.widgetPricelist.setColumnWidth(9, 50)
        self.widgetPricelist.setColumnWidth(10, 50)
        self.widgetPricelist.setColumnWidth(11, 50)
        self.widgetPricelist.setColumnWidth(12, 50)

        self.widgetReports.setColumnHidden(0, True)  # ID
        self.widgetReports.setColumnWidth(1, 80)  # rep_date
        self.widgetReports.setColumnWidth(2, 60)  # visits
        self.widgetReports.setColumnWidth(3, 60)  # sale day
        self.widgetReports.setColumnWidth(4, 60)  # demo day
        self.widgetReports.setColumnWidth(5, 100)  # turnover day
        self.widgetReports.setColumnWidth(6, 50)  # km
        # self.widgetReports column 7                # supervisor

        self.widgetReportVisits.setColumnWidth(0, 150)
        self.widgetReportVisits.setColumnWidth(1, 100)
        self.widgetReportVisits.setColumnWidth(2, 100)
        self.widgetReportVisits.setColumnWidth(3, 60)

        self.populate_customer_list()
        self.populate_price_list()

        try:
            cid = self._settings.settings["cust_idx"]
            if self._customers.lookup_by_id(cid):
                try:
                    self.widgetCustomers.setCurrentIndex(
                        self.widgetCustomers.indexFromItem(
                            self.widgetCustomers.findItems(str(
                                self._customers.customer["customer_id"]),
                                                           Qt.MatchExactly,
                                                           column=0)[0]))
                    self.toolButtonCustomer.click()
                except KeyError:
                    pass
        except KeyError:
            return

        self._reports.load(workdate=self.textWorkdate.text())
        self.populate_report_list()
        self.populate_report_visit_list()
        self.toolButtonReport.click()
コード例 #35
0
ファイル: migration.py プロジェクト: timur-glushan/tt
def install_migration_reports():
  """Migrate the reports data from the old CouchDB storage"""
  from models.account import Account
  from models.project import Project, Component
  from models.report import Report
  import datetime
  
  fault = open('data/fault.log', 'w')
  
  for row in __couchdb().view('_design/reports/_view/list_by_date', startkey=['2013-01-01'], endkey=['2014-12-12']):
    try:
      value = row['value']
      value['project'] = value.get('project', '').replace(':', '/').replace('EXT/', '').replace('INT/', '')
      
      report = Report()
      report.due_date = value.get('due_date')
    
      if value.get('reporter', ''):
        report.reporter = Account.query.filter_by(alias=value.get('reporter', '')).first()
    
      if value.get('project', ''):
        report.project = Project.query.filter_by(alias=value.get('project', '')).first()
    
      if value.get('partition', []):
        component_alias = '/'.join(partition.keys()[0] for partition in value.get('partition', []))
      else:
        component_alias = Component.COMPONENT_DEFAULT
      report.component = Component.query.filter_by(project=report.project, alias=component_alias).first() or Component.query.filter_by(project=project, alias=Component.COMPONENT_DEFAULT).first()
    
      report.duration = float(value.get('hours', 0))
      report.summary = value.get('summary', '')
      if value.get('employee', ''):
        report.account = Account.query.filter_by(alias=value.get('employee', '')).first()
    
      if value.get('deleted', False):
          report.status = Report.STATUS_ACTIVE | Report.STATUS_DELETED
    
      report.save()
      print '[MIGRATION:REPORT]', report.__str__()
    except Exception as e:
      message = datetime.datetime.now().__str__().split('.')[0] + '\n\t' + str(e)
      print message
      fault.write(message)
  
  fault.close()
コード例 #36
0
    def generate_report(self):
        print("\n")
        Print.success("Generating Report")

        report = Report(self, self.exp_reports)
        report.generate()
コード例 #37
0
def report_post(is_comment, reported_id):
    create_report = False
    if not check.logged_in():
        return redirect("/")
    else:
        form = ReportForm(request.form)
        if form.validate_on_submit():
            try:
                #If reported object is a post
                if is_comment == 0:
                    reported_post = Post(reported_id)
                    if len(
                            Report.get_user_prev_report(
                                session.get("user_id", ""), reported_id)) > 0:
                        return redirect("/post/" + str(reported_id))
                else:
                    reported_comment = Comment(reported_id)
                    if len(
                            Report.get_user_prev_report(
                                session.get("user_id", ""), reported_id)) > 0:
                        return redirect("/post/" +
                                        str(reported_comment.post_id))

                report = Report()
                report.submitting_user_id = session.get("user_id", "")
                report.violated_rule = form.data["violated_rule"]
                report.date = datetime.utcnow()
                report.reason_description = form.data["reason_description"]
                report.is_comment = is_comment
                report.action_taken = None
                report.is_dismissed = False
                report.post_id = reported_id if is_comment == 0 else None
                report.comment_id = reported_id if is_comment == 1 else None
                report.save()
                flash({
                    'text': "You have created a report.",
                    'type': "success"
                })
                return redirect("/")
            except NotImplementedError as error:
                return render_template("error.html",
                                       error_type="Failed",
                                       error_info=str(error))
        else:
            if request.method == "POST":
                return render_template(
                    'report.html',
                    form=form,
                    error="Invalid field, please check again.")
            else:
                return render_template('report.html', form=form)
コード例 #38
0
ファイル: test_report.py プロジェクト: ccoughlin/NDIToolbox
class TestReport(unittest.TestCase):
    """Functional testing for the Report class"""

    def setUp(self):
        self.output_folder = os.path.join(os.path.dirname(__file__), "support_files")
        self.output_file = os.path.join(self.output_folder, "test_report.pdf")
        self.report = Report(self.output_file)

    def generate_sample_plot(self, output_filename, width=5, height=5, title="Sample Data"):
        """Generates a sample plot of random data"""
        # Initialize matplotlib plot formatting to sane defaults
        mainmodel.init_matplotlib_defaults()
        figure = Figure(figsize=(width, height))
        canvas = FigureCanvas(figure)
        axes = figure.gca()
        x = np.arange(-10, 10)
        data = np.sinc(x + random.uniform(-.25, .25))
        linestyles = ['_', '-', '--', ':']
        colors = ('b', 'g', 'r', 'c', 'm', 'y', 'k')
        axes.plot(x, data, linestyle=random.choice(linestyles), marker=".", color=random.choice(colors))
        axes.set_title(title)
        axes.grid(True)
        figure.savefig(output_filename, format='png')

    def generate_sample_table(self, rows=3, cols=4, header=None):
        """Generates and returns a 2D list suitable for inclusion in a Report as a table.
        If the list header is included, it is prepended to the table as its header."""
        def random_content():
            """Returns some random content for a cell"""
            coin_flip = random.choice([0, 1])
            if coin_flip == 0:
                return random.choice(["Sample Text", "", "Alternate Text", "Lorem Ipsum",
                                      os.path.basename(self.output_file)])
            else:
                return random.uniform(-25, 25)
        table = []
        if header is not None:
            table.append(header)
        for r in range(rows):
            row = []
            for c in range(cols):
                row.append(random_content())
            table.append(row)
        return table

    def test_generate_report(self):
        """Functional test to verify generating a PDF report"""
        self.report.front_matter = os.path.join(self.output_folder, "Sample Front Matter.pdf")
        self.report.end_matter = os.path.join(self.output_folder, "Sample End Matter.pdf")
        lorem_file = os.path.join(self.output_folder, "loremipsum.txt")
        with open(lorem_file, "r") as fidin:
            sample_text = fidin.readlines()
        for i in range(5):
            output_filename = os.path.join(self.output_folder, "plot{0}.png".format(i+1))
            self.generate_sample_plot(output_filename, title="Plot {0}".format(i+1))
            heading = "Section {0}".format(i+1)
            a_section = ReportSection(heading)
            caption = "Sample caption for plot {0}".format(i+1)
            start_idx = random.randint(0, len(sample_text))
            end_idx = start_idx + random.randint(0, len(sample_text)-start_idx)
            text = sample_text[start_idx:end_idx]
            if i%2 == 0:
                _t = self.generate_sample_table(header=["Col 1", "Col 2", "Col 3"])
                _t_caption = "A sample table"
                a_section.add_table(_t, caption=_t_caption)
            a_section.add_figure(output_filename, caption=caption)
            a_section.add_text(text)
            self.report.sections.append(a_section)
        self.report.write()
        print("Please examine the PDF output file {0}.".format(self.output_file))

    def tearDown(self):
            pngs = os.listdir(self.output_folder)
            for png in pngs:
                root, ext = os.path.splitext(png)
                if 'plot' in root and 'png' in ext:
                    try:
                        os.remove(os.path.join(self.output_folder, png))
                    except WindowsError: # Windows reports file in use
                        pass
                    except OSError: # Other operating system error
                        print("Unable to delete test output file {0}.".format(png))
コード例 #39
0
    def generate_report(params, data):
        log = logging.getLogger('task')

        error = False
        term = Term.query.filter_by(hard_id=params['term_id']).first()
        if not term:
            log.error('Not found term %s' % params['term_id'])
            return False

        event = Event.get_by_key(data['event_key'])
        if not event:
            log.error('Not found event %s' % data['event_key'])
            return False

        firm_terms = FirmTerm.query.filter_by(term_id=term.id).all()
        payments = data['payments']
        report_max_date = ''
        for payment in payments:
            report = Report()
            report.term_id = term.id
            report.event_id = event.id
            report.type = payment['type']
            report.payment_id = None
            report.amount = payment['amount'] * int(term.factor)

            real_person = None
            for row in firm_terms:
                report.term_firm_id = row.firm_id
                query = Person.query
                query = query.filter((Person.payment_id == payment['card']) |
                                     (Person.hard_id == int(payment['card'])))
                person = query.filter(Person.firm_id == row.child_firm_id).first()
                if not person:
                    continue
                real_person = person

            if real_person:
                report.name = real_person.name
                report.person_id = real_person.id
                report.person_firm_id = real_person.firm_id

                report.payment_id = real_person.payment_id
            else:
                report.payment_id = payment['card']

            date_pattern = '%Y-%m-%d %H:%M:%S'
            date_time_utc = date_helper.convert_date_to_utc(
                payment['date_time'],
                term.tz,
                date_pattern,
                date_pattern)
            report.creation_date = date_time_utc

            if report.creation_date > report_max_date:
                report_max_date = report.creation_date

            error = report.add_new()

        if not error:
            ReportSenderTask.lost_report_watcher.delay(term.id, report_max_date)

        return error
コード例 #40
0
def test_reports():
    with open("./test_data/report_single.json", "r") as j:
        data = json.load(j)

    report = Report(**data)
    return (report.output)
コード例 #41
0
    def generate_report(params, data):
        log = logging.getLogger('task')

        error = False
        term = Term.query.filter_by(hard_id=params['term_id']).first()
        if not term:
            log.error('Not found term %s' % params['term_id'])
            return False

        event = Event.get_by_key(data['event_key'])
        if not event:
            log.error('Not found event %s' % data['event_key'])
            return False

        firm_terms = FirmTerm.query.filter_by(term_id=term.id).all()
        payments = data['payments']
        report_max_date = ''
        for payment in payments:
            report = Report()
            report.term_id = term.id
            report.event_id = event.id
            report.type = payment['type']
            report.payment_id = None
            report.amount = payment['amount'] * int(term.factor)

            real_person = None
            for row in firm_terms:
                report.term_firm_id = row.firm_id
                query = Person.query
                query = query.filter((Person.payment_id == payment['card']) | (
                    Person.hard_id == int(payment['card'])))
                person = query.filter(
                    Person.firm_id == row.child_firm_id).first()
                if not person:
                    continue
                real_person = person

            if real_person:
                report.name = real_person.name
                report.person_id = real_person.id
                report.person_firm_id = real_person.firm_id

                report.payment_id = real_person.payment_id
            else:
                report.payment_id = payment['card']

            date_pattern = '%Y-%m-%d %H:%M:%S'
            date_time_utc = date_helper.convert_date_to_utc(
                payment['date_time'], term.tz, date_pattern, date_pattern)
            report.creation_date = date_time_utc

            if report.creation_date > report_max_date:
                report_max_date = report.creation_date

            error = report.add_new()

        if not error:
            ReportSenderTask.lost_report_watcher.delay(term.id,
                                                       report_max_date)

        return error