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, )
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'))
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()
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)
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()
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])
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()
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("/")
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
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'})
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)
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()
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'})
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")
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
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])
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
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
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("/")
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"})
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("/")
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
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 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")
#!/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)
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
def Report(self): return Report(self)
def print(self): """ Output result. """ r = Report(self.output) r.print()
def report(crash_id): report = Report.get(crash_id) return jsonify(report=report.__dict__)
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)
def reports(): reports = Report.all() reports = [report.__dict__ for report in reports] return jsonify(reports=reports)
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))
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 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()
def generate_report(self): print("\n") Print.success("Generating Report") report = Report(self, self.exp_reports) report.generate()
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)
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))
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
def test_reports(): with open("./test_data/report_single.json", "r") as j: data = json.load(j) report = Report(**data) return (report.output)
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