def manage_documents(request, company, page): c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'stock', 'view'): return no_permission_view(request, c, _("You have no permission to view stock.")) documents = Document.objects.filter(company=c).order_by('-number') paginator = Paginator(documents, g.MISC['documents_per_page']) if page: documents = paginator.page(page) else: documents = paginator.page(1) context = { 'managing': 'documents', 'company': c, 'documents': documents, # 'searched': searched, # 'filter_form': form, 'title': _("Stock"), 'next_url': reverse('pos:manage_documents', args=[c.url_name, int(page)+1]), 'prev_url': reverse('pos:manage_documents', args=[c.url_name, int(page)-1]), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), 'date_format_js': get_date_format(request.user, c, 'js'), } return render(request, 'pos/manage/manage_documents.html', context)
def list_users(request, company): """ show a list of users and their pins """ c = get_object_or_404(Company, url_name=company) # check permission if not has_permission(request.user, c, 'user', 'view'): return no_permission_view(request, c, _("You have no permission to view users' settings.")) # this company's permissions permissions = Permission.objects.filter(company=c) # show waiting and canceled invites actions = Action.objects.filter(company=c, type=g.ACTION_INVITATION) # do some nice formatting on the actions for a in actions: a.sender = str(BlocklogicUser.objects.get(email=a.sender)) context = { 'company': c, 'permissions': permissions, 'permission_groups': g.PERMISSION_GROUPS, 'actions': actions, 'pin_length': g.PIN_LENGTH, 'title': _("Users"), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), } return render(request, 'pos/manage/users.html', context)
def add_register(request, company): # add a new register c = get_object_or_404(Company, url_name=company) # check permissions: needs to be manager if not has_permission(request.user, c, 'register', 'edit'): return no_permission_view(request, c, _("You have no permission to add printers.")) context = { 'add': True, 'company': c, 'title': _("Add printer"), 'site_title': g.MISC['site_title'], 'date_format_js': get_date_format(request.user, c, 'js') } if request.method == 'POST': # submit data form = RegisterForm(request.POST) if form.is_valid(): register = form.save(False) register.company = c register.created_by = request.user register.save() return redirect('pos:list_registers', company=c.url_name) else: form = RegisterForm() form.user = request.user form.company = c context['form'] = form return render(request, 'pos/manage/register.html', context)
def add_contact(request, company): # add a new contact c = get_object_or_404(Company, url_name=company) # check permissions: needs to be manager if not has_permission(request.user, c, 'contact', 'edit'): return no_permission_view(request, c, _("You have no permission to add contacts.")) t = request.GET.get('type') if not t: t = 'Individual' # the default context = { 'add': True, 'type': t, 'company': c, 'title': _("Add contact"), 'site_title': g.MISC['site_title'], 'date_format_js': get_date_format(request.user, c, 'js') } if request.method == 'POST': # submit data form = ContactForm(request.POST) form.user = request.user form.company = c if form.is_valid(): # create a new Contact contact = Contact( type=form.cleaned_data.get('type'), company_name=form.cleaned_data.get('company_name'), first_name=form.cleaned_data.get('first_name'), last_name=form.cleaned_data.get('last_name'), sex=form.cleaned_data.get('sex'), street_address=form.cleaned_data.get('street_address'), postcode=form.cleaned_data.get('postcode'), city=form.cleaned_data.get('city'), state=form.cleaned_data.get('state'), country=form.cleaned_data.get('country'), email=form.cleaned_data.get('email'), phone=form.cleaned_data.get('phone'), vat=form.cleaned_data.get('vat'), date_of_birth=form.cleaned_data.get('date_of_birth'), created_by=request.user, company=c ) contact.save() return redirect('pos:list_contacts', company=c.url_name) else: form = ContactForm(initial={'type': t, 'country': c.country}) form.user = request.user form.company = c context['form'] = form return render(request, 'pos/manage/contact.html', context)
def list_contacts(request, company): c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'contact', 'view'): return no_permission_view(request, c, _("You have no permission to view contacts.")) l = request.GET.get('letter') results_display = False # true if there was something in the search form # show the filter form if request.method == 'POST': contacts = Contact.objects.all() form = ContactFilterForm(request.POST) results_display = True if form.is_valid(): # filter by whatever is in the form if form.cleaned_data['type'] == 'Individual': contacts = contacts.filter(type='Individual') if 'name' in form.cleaned_data: # search by first and last name first_names = contacts.filter(first_name__icontains=form.cleaned_data['name']) last_names = contacts.filter(last_name__icontains=form.cleaned_data['name']) contacts = (first_names | last_names).distinct() else: contacts = contacts.filter(type='Company') if 'name' in form.cleaned_data: # search by company name contacts = contacts.filter(company_name__icontains=form.cleaned_data['name']) else: form = ContactFilterForm() if l: if l == '*': # get all contacts that don't begin with any letter of the alphabet contacts = Contact.objects.filter(company=c, company_name__iregex=r'^[^' + g.ALPHABETS[get_language()] + '].*') | \ Contact.objects.filter(company=c, first_name__iregex=r'^[^' + g.ALPHABETS[get_language()] + '].*') else: # get contacts beginning with the selected letter contacts = Contact.objects.filter(company=c, company_name__istartswith=l) | \ Contact.objects.filter(company=c, first_name__istartswith=l) else: contacts = Contact.objects.none() context = { 'company': c, 'letter': l, 'contacts': contacts, 'filter_form': form, 'results_display': results_display, 'title': _("Contacts"), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), 'alphabet': g.ALPHABETS[get_language()], } return render(request, 'pos/manage/contacts.html', context)
def format_date(user, company, date, send_to='python'): """ formats date for display according to user's settings """ from config.functions import get_date_format if not date: return '' else: return date.strftime(get_date_format(user, company, send_to))
def edit_contact(request, company, contact_id): # edit an existing contact c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'contact', 'edit'): return no_permission_view(request, c, _("You have no permission to edit contacts.")) context = { 'company': c, 'contact_id': contact_id, 'title': _("Edit contact"), 'site_title': g.MISC['site_title'], 'date_format_js': get_date_format(request.user, c, 'js'), } # get contact contact = get_object_or_404(Contact, id=contact_id) # check if contact actually belongs to the given company if contact.company != c: raise Http404 if request.method == 'POST': # submit data form = ContactForm(request.POST) form.user = request.user form.company = c if form.is_valid(): contact.type = form.cleaned_data.get('type') contact.company_name = form.cleaned_data.get('company_name') contact.first_name = form.cleaned_data.get('first_name') contact.last_name = form.cleaned_data.get('last_name') contact.sex = form.cleaned_data.get('sex') contact.date_of_birth = form.cleaned_data.get('date_of_birth') contact.street_address = form.cleaned_data.get('street_address') contact.postcode = form.cleaned_data.get('postcode') contact.city = form.cleaned_data.get('city') contact.state = form.cleaned_data.get('state') contact.country = form.cleaned_data.get('country') contact.email = form.cleaned_data.get('email') contact.phone = form.cleaned_data.get('phone') contact.vat = form.cleaned_data.get('vat') contact.save() return redirect('pos:list_contacts', company=c.url_name) else: initial = contact_to_dict(request.user, c, contact) form = ContactForm(initial=initial) form.user = request.user form.company = c context['form'] = form context['type'] = contact.type return render(request, 'pos/manage/contact.html', context)
def list_registers(request, company): c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'register', 'view'): return no_permission_view(request, c, _("You have no permission to view registers.")) context = { 'company': c, 'title': _("Cash Registers"), 'registers': Register.objects.filter(company__id=c.id).order_by('name'), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), 'date_format_js': get_date_format(request.user, c, 'js'), 'currency': get_company_value(request.user, c, 'pos_currency'), } return render(request, 'pos/manage/registers.html', context)
def parse_date(user, company, string): """ parses date in string according to user selected preferences return dictionary with result status and parsed datetime: {'success':True/False, date:<num>/None} """ from config.functions import get_date_format try: d = dtm.datetime.strptime(string, get_date_format(user, company, 'python')) except: return {'success': False, 'date': None} return {'success': True, 'date': d}
def edit_discount(request, company, discount_id): # edit an existing contact c = get_object_or_404(Company, url_name=company) # check permissions: needs to be at least manager if not has_permission(request.user, c, 'discount', 'edit'): return no_permission_view(request, c, _("You have no permission to edit discounts.")) context = { 'title': _("Edit discount"), 'site_title': g.MISC['site_title'], 'company': c, 'discount_id': discount_id, 'date_format_js': get_date_format(request.user, c, 'js'), } discount = get_object_or_404(Discount, id=discount_id) # check if contact actually belongs to the given company if discount.company != c: raise Http404 if request.method == 'POST': # submit data form = DiscountForm(data=request.POST, initial=discount_to_dict(request.user, c, discount), company=c, user=request.user) if form.is_valid(): discount.description = form.cleaned_data.get('description') discount.code = form.cleaned_data.get('code') discount.type = form.cleaned_data.get('type') discount.amount = form.cleaned_data.get('amount') discount.start_date = form.cleaned_data.get('start_date') discount.end_date = form.cleaned_data.get('end_date') discount.enabled = form.cleaned_data.get('enabled') discount.save() return redirect('pos:list_discounts', company=c.url_name) else: form = DiscountForm(initial=discount_to_dict(request.user, c, discount), user=request.user, company=c) context['form'] = form return render(request, 'pos/manage/discount.html', context)
def add_discount(request, company): c = get_object_or_404(Company, url_name=company) # check for permission for adding discounts if not has_permission(request.user, c, 'discount', 'edit'): return no_permission_view(request, c, _("You have no permission to add discounts.")) context = { 'title': _("Add discount"), 'site_title': g.MISC['site_title'], 'company': c, 'date_format_js': get_date_format(request.user, c, 'js'), } if request.method == 'POST': # submit data form = DiscountForm(data=request.POST, user=request.user, company=c) if form.is_valid(): # save the new discount and redirect back to discounts d = Discount( description=form.cleaned_data.get('description'), code=form.cleaned_data.get('code'), type=form.cleaned_data.get('type'), amount=form.cleaned_data.get('amount'), start_date=form.cleaned_data.get('start_date'), end_date=form.cleaned_data.get('end_date'), enabled=form.cleaned_data.get('enabled'), created_by=request.user, company=c ) d.save() return redirect('pos:list_discounts', company=c.url_name) else: form = DiscountForm(user=request.user, company=c) context['form'] = form context['company'] = c context['add'] = True return render(request, 'pos/manage/discount.html', context)
def edit_register(request, company, register_id): # edit an existing register c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'register', 'edit'): return no_permission_view(request, c, _("You have no permission to edit registers.")) context = { 'company': c, 'register_id': register_id, 'title': _("Edit register"), 'site_title': g.MISC['site_title'], 'date_format_js': get_date_format(request.user, c, 'js'), } # get register register = get_object_or_404(Register, id=register_id, company=c) if request.method == 'POST': # submit data form = RegisterForm(request.POST, instance=register) if form.is_valid(): form.save() return redirect('pos:list_registers', company=c.url_name) else: initial = register_to_dict(request.user, c, register) form = RegisterForm(initial=initial) form.user = request.user form.company = c context['form'] = form return render(request, 'pos/manage/register.html', context)
def stats(request, company): c = Company.objects.get(url_name=company) # permission? if not has_permission(request.user, c, 'stats', 'view'): return no_permission_view(request, c, _("You have no permission to view stats")) # recent earnings: all bills from today/yesterday/this week/this month, # their income and profit def bill_earnings(start_date=None, end_date=None): billset = Bill.objects.filter(company=c, payment__status=PAID) if start_date: billset = billset.filter(timestamp__gte=start_date) if end_date: billset = billset.filter(timestamp__lt=end_date) if billset.count() == 0: return { 'income': format_number(request.user, c, Decimal(0)), 'profit': format_number(request.user, c, Decimal(0)), } income = billset.aggregate(Sum('payment__total'))['payment__total__sum'] return { 'income': format_number(request.user, c, income), 'profit': format_number(request.user, c, income - billset.aggregate(Sum('base'))['base__sum'] - billset.aggregate(Sum('discount'))['discount__sum']) } today = dtm.datetime.utcnow().replace(tzinfo=timezone(get_company_value(request.user, c, 'pos_timezone'))) today = today.replace(hour=0, minute=0, second=0, microsecond=0) yesterday = today - dtm.timedelta(days=1) week_start = today - dtm.timedelta(days=today.weekday()) month_start = today.replace(day=1) # get custom dates from form, if they are present earnings_from = None earnings_to = None if request.method == "GET": r = parse_date(request.user, c, request.GET.get('earnings_from')) if not r['success']: earnings_from = None else: earnings_from = r['date'] r = parse_date(request.user, c, request.GET.get('earnings_to')) if not r['success']: earnings_to = None else: earnings_to = r['date'] if earnings_from and earnings_to and earnings_from > earnings_to: earnings_from = None earnings_to = None if earnings_from and earnings_to: custom_earnings = bill_earnings(start_date=earnings_from, end_date=earnings_to) else: custom_earnings = None earnings = { 'today': bill_earnings(start_date=today), 'yesterday': bill_earnings(start_date=yesterday, end_date=today), 'week': bill_earnings(start_date=week_start), 'month': bill_earnings(start_date=month_start), 'custom': custom_earnings, } # top-selling products: # today/yesterday/this week/this/month/overall TOP_PRODUCTS_LEN = 10 def top_products(start_date=None, end_date=None): itemset = BillItem.objects.filter(bill__company=c, bill__payment__status=PAID) if start_date: itemset = itemset.filter(bill__timestamp__gte=start_date) if end_date: itemset = itemset.filter(bill__timestamp__lt=end_date) itemset = itemset.values('name', 'code')\ .annotate(sold_quantity=Sum('quantity'))\ .order_by('-sold_quantity')[:TOP_PRODUCTS_LEN] # make sure the list is always exactly TOP_PRODUCTS_LEN long itemset = list(itemset) itemset += [None for t in range(TOP_PRODUCTS_LEN - len(itemset))] return itemset # custom date limits from form products_from = None products_to = None if request.method == "GET": r = parse_date(request.user, c, request.GET.get('products_from')) if not r['success']: products_from = None else: products_from = r['date'] r = parse_date(request.user, c, request.GET.get('products_to')) if not r['success']: products_to = None else: products_to = r['date'] if products_from and products_to and products_from > products_to: products_from = None products_to = None if products_from and products_to: custom_products = top_products(start_date=products_from, end_date=products_to) else: custom_products = [None for x in range(TOP_PRODUCTS_LEN)] products_data = { 'all_time': top_products(), 'yesterday': top_products(start_date=yesterday, end_date=today), 'week': top_products(start_date=week_start), 'month': top_products(start_date=month_start), 'custom': custom_products, } # convert the products from dict of lists to a simple list of rows for the template products = [] for i in range(TOP_PRODUCTS_LEN): if not products_data['all_time'][i]: break products.append({ 'all_time': products_data['all_time'][i], 'yesterday': products_data['yesterday'][i], 'week': products_data['week'][i], 'month': products_data['month'][i], 'custom': products_data['custom'][i], }) context = { 'company': c, 'earnings': earnings, 'earnings_from': format_date(request.user, c, earnings_from), 'earnings_to': format_date(request.user, c, earnings_to), 'products': products, 'products_from': format_date(request.user, c, products_from), 'products_to': format_date(request.user, c, products_to), 'title': _("Stats"), 'site_title': g.SITE_TITLE, 'date_format_js': get_date_format(request.user, c, 'js') } return render(request, 'pos/manage/stats.html', context)
def manage_stock(request, company, page): c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'stock', 'view'): return no_permission_view(request, c, _("You have no permission to view stock.")) documents = Document.objects.filter(company=c).order_by('-number') search = request.GET.get('search', '') document = request.GET.get('document', '') if search == "": if document == "" or document == "all": stocks = Stock.objects.filter(company=c).order_by('-datetime_created') else: stocks = Stock.objects.filter(company=c, document=document).order_by('-datetime_created') else: stock_products = StockProduct.objects.filter(product__name__icontains=search, stock__in=[s.id for s in Stock.objects.filter(company=c)]) stocks = Stock.objects.filter(Q(name__icontains=search) | Q(id__in=[sp.id for sp in stock_products]), Q(company=c)).order_by('-datetime_created') paginator = Paginator(stocks, g.MISC['stocks_per_page']) if page: stocks = paginator.page(page) else: stocks = paginator.page(1) stocks_json = {} for s in stocks: s.stock_products = StockProduct.objects.filter(stock=s).order_by('product__name') __stock_products = {} for sp in s.stock_products: __stock_products[str(sp.id)] = {'product_id': str(sp.product.id), 'product_name': str(sp.product.name), 'deduction': str(fn(sp.deduction))} stocks_json[s.id] = { 'id': str(s.id), 'stock_type': s.stock_type, 'unit_type': s.unit_type, 'stock': fn(s.stock), 'left_stock': fn(s.left_stock), 'stock_products': __stock_products } currency = get_company_value(request.user, c, 'pos_currency') context = { 'separator': get_company_value(request.user, c, 'pos_decimal_separator'), 'currency': currency, 'decimal_places': get_company_value(request.user, c, 'pos_decimal_places'), 'currency_symbol': currencies[currency][1], 'documents': documents, 'managing': 'stock', 'units': g.UNITS, 'stock_types': g.STOCK_TYPE, 'company': c, 'stocks': stocks, 'stocks_json': json.dumps(stocks_json), # 'searched': searched, # 'filter_form': form, 'title': _("Stock"), 'next_url': reverse('pos:manage_stock', args=[c.url_name, int(page)+1]), 'prev_url': reverse('pos:manage_stock', args=[c.url_name, int(page)-1]), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), 'date_format_js': get_date_format(request.user, c, 'js'), } return render(request, 'pos/manage/manage_stocks.html', context)
def list_bills(request, company): c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'bill', 'view'): return no_permission_view(request, c, _("You have no permission to view bills.")) N = 10 # if no search was made, display last N bills (below) searched = False # use GET for everything: there's little parameters and when using POST, paginator gets # in the way with GET requests form = BillSearchForm(data=request.GET, user=request.user, company=c) if form.is_valid(): # decide which way to order the results # this is the fake switch statement that is missing in python for no obvious reason ordering = { 'serial': 'serial', 'date': 'timestamp', 'amount': 'total' } order = ordering.get(form.cleaned_data.get('sort_by')) if form.cleaned_data.get('sort_order') == 'desc': order = '-' + order bills = Bill.objects.filter(company=c).order_by(order) # filter by whatever is in the form: # issue date: from t = form.cleaned_data.get('issued_from') if t: bills = bills.filter(timestamp__gte=t) # issue date: to t = form.cleaned_data.get('issued_to') if t: bills = bills.filter(timestamp__lte=t) # item: t = form.cleaned_data.get('item_code') if t: ids = [i.id for i in BillItem.objects.only('bill_id').filter(code__icontains=t)] # find all bills that include item that contains this code bills = bills.filter(id__in=ids) # contact t = form.cleaned_data.get('contact') if t: bills = bills.filter(contact__first_name__icontains=t) | \ bills.filter(contact__last_name__icontains=t) | \ bills.filter(contact__company_name__icontains=t) # bill number t = form.cleaned_data.get('serial') if t: bills = bills.filter(serial__icontains=t) # status t = form.cleaned_data.get('status') if t: bills = bills.filter(payment__status=t) # amount: from t = form.cleaned_data.get('amount_from') if t: bills = bills.filter(total__gte=t) # amount: to t = form.cleaned_data.get('amount_to') if t: bills = bills.filter(total__lte=t) # user t = form.cleaned_data.get('user_name') if t: bills = bills.filter(user_name__icontains=t) page = form.cleaned_data.get('page') searched = True else: form = BillSearchForm(data=None, user=request.user, company=c) page = 1 bills = Bill.objects.filter(company=c).order_by('-timestamp') # format all bills manually bills = [bill_to_dict(request.user, c, b) for b in bills] paginator = Paginator(bills, g.MISC['bills_per_page']) if page: bills = paginator.page(page) else: bills = paginator.page(1) context = { 'company': c, 'bills': bills, 'searched': searched, 'filter_form': form, 'title': _("Bills"), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), 'date_format_js': get_date_format(request.user, c, 'js'), 'currency': get_company_value(request.user, c, 'pos_currency'), } return render(request, 'pos/manage/bills.html', context)
def list_discounts(request, company): c = get_object_or_404(Company, url_name=company) # check permissions: needs to be guest if not has_permission(request.user, c, 'discount', 'view'): return no_permission_view(request, c, _("You have no permission to view discounts.")) N = 6 searched = False # show the filter form form = DiscountFilterForm(data=request.GET, user=request.user, company=c) if form.is_valid(): discounts = Discount.objects.filter(company__id=c.id) # filter by whatever is in the form: description if form.cleaned_data.get('search'): discounts = discounts.filter(description__icontains=form.cleaned_data['search']) | \ discounts.filter(code__icontains=form.cleaned_data['search']) # start_date t = form.cleaned_data.get('start_date') if t: discounts = discounts.filter(start_date__gte=t) # end_date t = form.cleaned_data.get('end_date') if t: discounts = discounts.filter(start_date__gte=t) # enabled t = form.cleaned_data.get('enabled') if t is not None: discounts = discounts.filter(enabled=t) page = form.cleaned_data.get('page') searched = True # search results are being displayed else: form = DiscountFilterForm(user=request.user, company=c) discounts = Discount.objects.filter(company=c)[:N] page = 1 paginator = Paginator(discounts, g.MISC['discounts_per_page']) if page: discounts = paginator.page(page) else: discounts = paginator.page(1) context = { 'company': c, 'discounts': discounts, 'searched': searched, 'filter_form': form, 'title': _("Discounts"), 'site_title': g.MISC['site_title'], 'date_format_django': get_date_format(request.user, c, 'django'), 'date_format_js': get_date_format(request.user, c, 'js'), 'currency': get_company_value(request.user, c, 'pos_currency'), } return render(request, 'pos/manage/discounts.html', context)