예제 #1
0
    def get(self, filename):
        image = Image.get_by_filename(filename)
        if not image:
            return self.abort(404)

        # Gather the information we take from the user.
        identifier = self.request.get('identifier', '')
        ip_address = self.request.remote_addr
        referrer = self.request.referrer
        user_agent = self.request.headers.get('User-Agent', '')
        visitor_uuid = self.request.cookies.get('VISITOR_UUID', '')

        # If they're not in our database, create a new entity to track them.
        visitor = Visitor.get_by_uuid(visitor_uuid)
        if visitor is None:
            visitor = Visitor()
            visitor.put()

        visit = Visit(identifier=identifier, ip_address=ip_address,
                      user_agent=user_agent, referrer=referrer,
                      image=image.key, visitor=visitor.key)
        visit.put()

        # Dispatch a task to send the visit to keen.io for analysis.
        visit_key = visit.key.urlsafe()
        logging.info('Dispatching task to process {visit_key}'
        .format(visit_key=visit_key))
        taskqueue.add(url=self.uri_for('analytics'),
                      params={'visit_key': visit_key})

        self.response.content_type = str(image.content_type)
        self.response.set_cookie(key='VISITOR_UUID', value=visitor.uuid)
        self.response.out.write(image.data)
예제 #2
0
def create_user_visit_helper(sess, request_id, user_obj_id, merchant_data):
    """
    A helper function that takes in the following params and creates a new visit
    object by communicating with the DB
    :param sess: Session object for access to the DB
    :param request_id: Request ID to track every request helps debugging
    :param user_obj_id: user_id to get the User object
    :param merchant_data: Merchant data from the given input
    :return: Visit object
    """
    merchant = Merchant.get_and_check_else_new(
        sess, merchant_data["merchantId"], merchant_data["merchantName"]
    )
    user = User.get_and_check_else_new(sess, user_obj_id)
    visit_id = uuid.uuid4()
    timestamp = int(time.time())
    Visit.new(sess, visit_id, timestamp, user.pk, merchant.pk)
    log.info("[{}] New visit created for user: {}".format(request_id, user.pk))
    return {
        "visitId": visit_id,
        "timestamp": timestamp,
        "merchant": {
            "merchantId": merchant.merchant_id,
            "merchantName": merchant.merchant_name,
        },
        "user": {"userId": user.user_obj_id},
    }
예제 #3
0
 def test_defaults(self):
     visit = Visit()
     visit.put()
     self.assertIsNone(visit.ip_address)
     self.assertIsNone(visit.identifier)
     self.assertIsNone(visit.image)
     self.assertIsNone(visit.referrer)
     self.assertIsNone(visit.visitor)
     self.assertIsNone(visit.user_agent)
     self.assertAlmostEqual(datetime.datetime.now(), visit.timestamp,
                            delta=datetime.timedelta(seconds=5))
예제 #4
0
    def test_get_tracking_image(self):
        image = Image(
            filename=self.DEFAULT_FILENAME, content_type=self.DEFAULT_CONTENT_TYPE)
        image.put()
        response = self.app.get(
            self.uri_for('tracking_image', filename=image.filename))
        self.assertOk(response)
        self.assertEqual(image.content_type, response.content_type)
        self.assertLength(1, Visit.query())
        self.assertLength(1, Visitor.query())

        visit = Visit.query().get()
        visitor = Visitor.query().get()
        self.assertEqual(image.key, visit.image)
        self.assertEqual(visitor.key, visit.visitor)
def check_in(id):
    check_in = request.form.get('check_in')
    check_out = request.form.get('check_out')
    description = request.form.get('description')
    visit = Visit(id, check_in, check_out, description)
    VisitRep().save(visit)
    return redirect('/pets/' + id + '/visits')
예제 #6
0
 def get(self):
   pub_id = int(self.request.get('pub'))
   pub = Pub.get_by_id(pub_id)
   visits = Visit.all().filter('pub =', pub).run()
   for v in visits:
     v.delete()
   pub.delete()
예제 #7
0
class TestVisit(unittest.TestCase):
    def setUp(self):
        self.visit = Visit("Helsinki", "Finland", "lakes")

    def test_visit_has_country(self):
        self.assertEqual("Finland", self.visit.country)

    def test_visit_has_city(self):
        self.assertEqual("Helsinki", self.visit.city)

    def test_visit_has_sight(self):
        self.assertEqual("lakes", self.visit.sight)

    def test_check_to_visit(self):
        self.visit.visited()
        self.assertEqual(True, self.visit.to_visit)
예제 #8
0
  def get(self):
    visits = Visit.all().run()
    for v in visits:
      try:
        p = v.pub
      except:
        v.delete()

    self.response.out.write('success')
예제 #9
0
def create_task():
    user_id = request.form['user_id']
    location_id = request.form['location_id']
    review = request.form['review']
    user = user_repository.select(user_id)
    location = location_repository.select(location_id)
    visit = Visit(user, location, review)
    visit_repository.save(visit)
    return redirect('/visits')
예제 #10
0
 def get(self):
     current_time = datetime.datetime.utcnow()
     one_hour_ago = current_time - datetime.timedelta(hours=1)
     visits = [serialize_ndb_model(visit)
               for visit in Visit.query(Visit.timestamp >= one_hour_ago)]
     if visits:
         keen.add_events({
             'visits': visits,
         })
예제 #11
0
    def test_duplicate_visitors_not_made(self):
        image = Image(
            filename=self.DEFAULT_FILENAME, content_type=self.DEFAULT_CONTENT_TYPE)
        image.put()
        response = self.app.get(
            self.uri_for('tracking_image', filename=image.filename))
        self.assertOk(response)
        self.assertLength(1, Visit.query())
        self.assertLength(1, Visitor.query())
        response = self.app.get(
            self.uri_for('tracking_image', filename=image.filename))
        self.assertOk(response)
        self.assertLength(2, Visit.query())
        self.assertLength(1, Visitor.query())

        visit1, visit2 = Visit.query()
        visitor = Visitor.query().get()
        self.assertEqual(visitor.key, visit1.visitor, visit2.visitor)
        self.assertEqual(image.key, visit1.image, visit2.image)
예제 #12
0
def create_trip():
    city_id = request.form["city_id"]
    country_id = request.form["country_id"]
    sight_id = request.form["sight_id"]
    to_visit = request.form["to_visit"]
    new_city = City("name", city_id)
    new_country = Country("country", country_id)
    new_sight = Sight("sight", sight_id)
    trip = Visit(new_city, new_country, new_sight, to_visit)
    visit_repository.save(trip)
    return redirect("/trips")
예제 #13
0
    def get_visits(self, pet_id):
        visits = []
        sql = "SELECT * FROM visits WHERE pet_id = %s"
        values = [pet_id]
        results = run_sql(sql, values)

        for row in results:
            visit = Visit(row['pet_id'], row['check_in'], row['check_out'],
                          row['description'], row['id'])
            visits.append(visit)
        return visits
예제 #14
0
def get_user_counts():
  users = memcache.get('user-counts')
  if users:
    return users
  users = User.all().run()
  user_counts = []
  for u in users:
    count = Visit.all().ancestor(u).filter('visited =', True).count()
    user_counts.append({'name':u.name,'id':u.key().id(),'count':count})
  user_counts = sorted(user_counts, key=lambda c: -c['count'])
  memcache.set('user-counts', user_counts)
  return user_counts
예제 #15
0
def select_all():
    visits = []

    sql = "SELECT * FROM visits"
    results = run_sql(sql)

    for row in results:
        user = user_repository.select(row['user_id'])
        location = location_repository.select(row['location_id'])
        visit = Visit(user, location, row['review'], row['id'])
        visits.append(visit)
    return visits
예제 #16
0
  def post(self):
    name = self.request.get('name')
    p = Pub.all().filter('name =', name).get(keys_only=True)
    if p:
      self.response.out.write('already exists')
      return
    nlat = None
    nlong = None
    lat = self.request.get('lat')
    long = self.request.get('long')
    if lat:
      nlat = float(lat)
    if long:
      nlong = float(long)
    p = Pub(name=name, latitude=nlat, longitude=nlong)
    p.put()

    users = User.all().run()
    for u in users:
      v = Visit(parent=u, pub=p)
      v.put()
    self.response.out.write('added ' + name)
예제 #17
0
  def post(self):
    if get_current_user():
      return self.redirect('/')
    token = self.request.get('session')
    if token:
      session = SignupSession.getSignupSession(token)
      if not session:
        return self.redirect('/auth/login')
      fb_id = session.fb_id
      g_user = None
    else:
      if not GOOGLE_USERS:
        return self.redirect('/auth/login')
      fb_id = None
      g_user = users.get_current_user()
      if not g_user:
        return self.redirect('/auth/login')
    name = cgi.escape(self.request.get('name'))
    email = cgi.escape(self.request.get('email'))
    if not name or not email:
      template = jinja_environment.get_template('templates/signup.html')
      values = {'name':name,'email':email,'session':token,'errormsg':'Please supply a name and email address'}
      self.response.out.write(template.render(values))
      return
    user = User(name=name,email=email,google_user=g_user,fb_id=fb_id)
    user.put()

    pubs = Pub.all().run()
    for pub in pubs:
      v = Visit(parent=user,pub=pub)
      v.put()

    rand_string=base64.urlsafe_b64encode(os.urandom(32))
    session = Session()
    session.user_id = user.key().id()
    session.token = rand_string
    session.save()
    self.response.set_cookie("session",rand_string,expires=datetime.datetime.now()+datetime.timedelta(days=30));
    self.redirect('/')
예제 #18
0
def select_all():
    visits = []

    sql = "SELECT * FROM visits"
    results = run_sql(sql)

    for row in results:
        city = city_repository.select(row['city_id'])
        country = country_repository.select(row['country_id'])
        sight = sight_repository.select(row["sight_id"])
        visit = Visit(city, country, sight, row['to_visit'], row['id'])
        visits.append(visit)
    return visits
예제 #19
0
def get_visit_by_id_helper(sess, request_id, visit_id):
    visit = Visit.get_by_id(sess, request_id, visit_id)
    merchant = Merchant.get_by_pk(sess, request_id, visit.merchant_pk)
    user = User.get_by_pk(sess, request_id, visit.user_obj_pk)
    log.info("[{}] Found visit by user: {}".format(request_id, user.pk))
    return {
        "visitId": visit_id,
        "timestamp": visit.timestamp,
        "merchant": {
            "merchantId": merchant.merchant_id,
            "merchantName": merchant.merchant_name,
        },
        "user": {"userId": user.user_obj_id},
    }
예제 #20
0
    def select(self, id):
        visit = None
        sql = f"SELECT * FROM {self.table} " + "WHERE id = %s"
        values = [id]
        result = run_sql(sql, values)[0]

        if result is not None:
            visit = Visit(
                result['pet_id'],
                result["check_in"],
                result["check_out"],
                result['description'],
                result["id"],
            )
        return visit
예제 #21
0
  def post(self):
    user = get_current_user()
    if not user and False:
      return self.redirect('/')
    pub_id = self.request.get('pub_id')
    pub = Pub.get_by_id(int(pub_id))

    visit = Visit.all().ancestor(user).filter('pub =', pub).get()

    visited = bool(self.request.get('visited'))
    visit.visited = visited
    visit.put()
    memcache.delete('visited-' + str(user.key().id()))
    memcache.delete('not-visited-' + str(user.key().id()))
    memcache.delete('user-counts')
예제 #22
0
    def select_all(self):
        visits = []
        sql = f"SELECT * FROM {self.table}"
        results = run_sql(sql)

        for row in results:
            visit = Visit(
                row['pet_id'],
                row["check_in"],
                row["check_out"],
                row['description'],
                row["id"],
            )
            visits.append(visit)
        return visits
예제 #23
0
  def get(self):
    user = get_current_user()
    lat=float(self.request.get('lat'))
    long=float(self.request.get('long'))
    if self.request.get('show-colleges'):
      if not user.show_colleges:
        memcache.delete('not-visited-' + str(user.key().id()))
        user.show_colleges = True
        user.put()
    elif user and user.show_colleges:
      memcache.delete('not-visited-' + str(user.key().id()))
      user.show_colleges = False
      user.put()
    if self.request.get('hide-visited'):
      if not user.hide_visited:
        user.hide_visited = True
        user.put()
    elif user and user.hide_visited:
      user.hide_visited = False
      user.put()

    if user and user.hide_visited:
      visits = memcache.get('not-visited-' + str(user.key().id()))
      if not visits:
        visits = Visit.all().ancestor(user).filter('visited =', False).fetch(500)
        visits = sorted(visits, key = lambda v: v.pub.name.lower())
        memcache.set('not-visited-' + str(user.key().id()), visits)
      if user.show_colleges:
        pubs = [v.pub for v in visits]
      else:
        pubs = [v.pub for v in visits if not v.pub.is_college]
      pubs = [p for p in pubs if not p.closed]
      pubs = sorted(pubs, key=lambda p: p.distance(lat, long))[0:20]
      pubs = [pub.toDictionary() for pub in pubs]
    else:
      pubs = memcache.get('all-pubs-list')
      if not pubs:
        pubs = Pub.all().filter('closed =', False).fetch(500)
        pubs = sorted(pubs, key = lambda p: p.name.lower())
        memcache.set('all-pubs-list', pubs)
      if user and not user.show_colleges:
        pubs = [p for p in pubs if not p.is_college]
      pubs = sorted(pubs, key=lambda p: p.distance(lat, long))[0:20]
      pubs = [p.toDictionary() for p in pubs]

    self.response.out.write(json.dumps(pubs))
예제 #24
0
 def refresh(self, customer_id):
     """
     Refresh customers product list
     Args:
         customer_id
     Returns:
         bool
     """
     visit = Visit()
     selection = ("customer_id", )
     filters = [("customer_id", "=")]
     values = (customer_id, )
     sql = self.q.build("select",
                        visit.model,
                        selection=selection,
                        filters=filters)
     success, data = self.q.execute(sql, values=values)
     if success:
         try:
             v_ids = data[0]
             sql = "SELECT lines.sku, sum(pcs) AS pcs, product.item " \
                   "FROM lines " \
                   "INNER JOIN product ON product.sku = lines.sku " \
                   "WHERE cust_id IN ? GROUP BY lines.sku"
             success, data = self.q.execute(sql, v_ids)
             if success:
                 try:
                     self._products = [
                         dict(zip(self.model["fields"], row))
                         for row in data
                     ]
                 except IndexError:
                     pass
             return True
         except IndexError:
             self._products = []
     return False
예제 #25
0
 def setUp(self):
     self.visit = Visit("Helsinki", "Finland", "lakes")
예제 #26
0
ophth_drugs = Treatment(
    'Ophthalmological drugs',
    'Oral medications or eye drops can be used to treat infection and other ocular issues, such as cataracts and glaucoma.'
)
treatment7 = TreatmentRep().save(ophth_drugs)

bmt = Treatment(
    'Behavioral modification treatments',
    'f your animal appears neurotic, obsessive, or overly aggressive and other treatments have not been successful, your veterinarian may prescribe behavioral modifiers like antidepressants or antipsychotics.'
)
treatment8 = TreatmentRep().save(bmt)
##############

# VISITS
visit1 = Visit(pet_1.id, dt.date(2020, 7, 28), dt.date(2020, 7, 30),
               'In this visit the pet was so cute the disease cured itself')
VisitRep().save(visit1)

visit2 = Visit(pet_2.id, dt.date(2020, 8, 28), dt.date(2020, 8, 30),
               'In this visit the pet was so cute the disease cured itself')
VisitRep().save(visit2)

visit3 = Visit(pet_3.id, dt.date(2020, 9, 28), dt.date(2020, 9, 30),
               'In this visit the pet was so cute the disease cured itself')
VisitRep().save(visit3)

visit4 = Visit(pet_4.id, dt.date(2020, 11, 28), dt.date(2020, 12, 30),
               'In this visit the pet was so cute the disease cured itself')
VisitRep().save(visit4)

visit5 = Visit(pet_5.id, dt.date(2020, 11, 28), dt.date(2020, 12, 30),
예제 #27
0
    def test_get_visit_by_id_helper(
        self,
        mock_visit_get_by_id,
        mock_user_get_by_pk,
        mock_merchant_get_by_pk,
        mock_time,
    ):
        test_merchant = Merchant()
        test_user = User()
        test_visit = Visit()
        sess_mock = MagicMock()

        test_merchant.pk = 40
        test_merchant.merchant_id = 4
        test_merchant.merchant_name = "test2"

        test_visit.visit_id = uuid.uuid4()
        test_visit.timestamp = self.timestamp
        test_visit.merchant_pk = 40
        test_visit.user_obj_pk = 4

        test_request_id = "test2"

        test_user.user_obj_id = "20"
        test_user.pk = 4

        mock_merchant_get_by_pk.return_value = test_merchant
        mock_user_get_by_pk.return_value = test_user
        mock_visit_get_by_id.return_value = test_visit

        test_output = {
            "visitId": test_visit.visit_id,
            "timestamp": test_visit.timestamp,
            "merchant": {
                "merchantId": test_merchant.merchant_id,
                "merchantName": test_merchant.merchant_name,
            },
            "user": {
                "userId": test_user.user_obj_id
            },
        }
        output = get_visit_by_id_helper(sess_mock, test_request_id,
                                        test_visit.visit_id)

        mock_visit_get_by_id.assert_called_once_with(sess_mock,
                                                     test_request_id,
                                                     test_visit.visit_id)
        mock_merchant_get_by_pk.assert_called_once_with(
            sess_mock, test_request_id, test_visit.merchant_pk)
        mock_user_get_by_pk.assert_called_once_with(sess_mock, test_request_id,
                                                    test_visit.user_obj_pk)
        mock_time.assert_called_once_with()

        self.assertEqual(test_output["merchant"]["merchantId"],
                         output["merchant"]["merchantId"])
        self.assertEqual(test_output["merchant"]["merchantName"],
                         output["merchant"]["merchantName"])
        self.assertEqual(test_output["user"]["userId"],
                         output["user"]["userId"])
        self.assertEqual(type(uuid.uuid4()), type(output["visitId"]))
        self.assertEqual(500, output["timestamp"])
예제 #28
0
 def test_get_by_ip_address(self):
     visit = Visit(ip_address=self.DEFAULT_IP)
     visit.put()
     self.assertLength(1, Visit.get_by_ip_address(self.DEFAULT_IP))
     self.assertLength(0, Visit.get_by_ip_address('1.1.1.1'))
예제 #29
0
 def test_get_by_identifier(self):
     visit = Visit(identifier=self.DEFAULT_IDENTIFIER)
     visit.put()
     self.assertLength(1, Visit.get_by_identifier(self.DEFAULT_IDENTIFIER))
     self.assertLength(0, Visit.get_by_identifier('*****@*****.**'))
예제 #30
0
user1 = User('Samwise Gamgee')
user_repository.save(user1)

user2 = User('Frodo Baggins')
user_repository.save(user2)

user3 = User('Gollum')
user_repository.save(user3)

location1 = Location('Mordor', 'Attractions')
location_repository.save(location1)

location2 = Location('The Prancing Pony', 'Tavern')
location_repository.save(location2)

visit1 = Visit(user1, location1, '0 stars, far too hot')
visit_repository.save(visit1)

visit2 = Visit(user3, location1, '5 stars, would visit again if I could')
visit_repository.save(visit2)

visit3 = Visit(user1, location2, '4 stars, plenty of beer available')
visit_repository.save(visit3)

visit4 = Visit(user2, location2,
               '3 stars, too crowded, could not find my wizard friend')
visit_repository.save(visit4)

pdb.set_trace()
예제 #31
0
 def Visit(self, start_time, owner, vet, reason, end_time=None):
     return Visit(start_time, owner, vet, reason, end_time)
예제 #32
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)
예제 #33
0
파일: visittab.py 프로젝트: mape90/VetApp
 def makeItem(self):
     data = self.getData()
     from models.visit import Visit
     return Visit(data["start_time"], data["owner"], data["vet"],
                  data["visit_reason"], data["end_time"],
                  data["visitanimals"])
예제 #34
0
sight_3 = Sight("Art Gallery")
sight_repository.save(sight_3)

city_1 = Sight("Havana")
city_repository.save(city_1)

city_2 = City("Barcelona")
city_repository.save(city_2)

city_3 = City("Florence")
city_repository.save(city_3)

country_1 = Country("Cuba")
country_repository.save(country_1)

country_2 = Country("Spain")
country_repository.save(country_2)

country_3 = Country("Italy")
country_repository.save(country_3)

visit_1 = Visit(city_2, country_2, sight_2, True)
visit_repository.save(visit_1)

visit_2 = Visit(city_1, country_1, sight_1, True)
visit_repository.save(visit_2)

visit_3 = Visit(city_3, country_3, sight_3, False)
visit_repository.save(visit_3)

pdb.set_trace()
예제 #35
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()