コード例 #1
0
ファイル: stats.py プロジェクト: rokj/sellout
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)
コード例 #2
0
ファイル: contact.py プロジェクト: rokj/sellout
def validate_contact(user, company, data):
    # data format (*-required data):
    # type*
    # company_name* (only if Company)
    # first_name* (only if Individual)
    # last_name* (only if Individual)
    # date_of_birth - list of discount ids (checked in create/edit_product)
    # street_address
    # postcode
    # city
    # country
    # state
    # email
    # phone
    # vat

    def err(msg):  # the value that is returned if anything goes wrong
        return {'status': False, 'data': None, 'message': msg}

    # return:
    # status: True if validation passed, else False
    #  data: 'cleaned' data if validation succeeded, else False
    #  message: error message or empty if validation succeeded

    if 'type' not in data:
        return err(_("No type specified"))
    if data['type'] not in [x[0] for x in g.CONTACT_TYPES]:
        return err(_("Wrong contact type"))

    # check credentials for Individual
    if data['type'] == 'Individual':
        # first name: check length (mandatory)
        if not data.get('first_name'):
            return err(_("No first name"))
        elif len(data['first_name']) > max_field_length(Contact, 'first_name'):
            return err(_("First name too long"))
        
        # last name: check length (mandatory)
        if not data.get('last_name'):
            return err(_("No last name"))
        elif len(data['last_name']) > max_field_length(Contact, 'last_name'):
            return err(_("Last name too long"))
        
        # sex: must be in g.SEXES
        if 'sex' not in data and data['sex'] not in [x[0] for x in g.SEXES]:
            return err(_("Wrong sex"))
        
        # date of birth: parse date
        if 'date_of_birth' in data and len(data['date_of_birth']) > 0:
            r = parse_date(user, company, data['date_of_birth'])
            if not r['success']:
                return err(_("Wrong format of date of birth"))
            else:
                data['date_of_birth'] = r['date']
        else:
            data['date_of_birth'] = None
        
    # check credentials for company
    else:
        if not data.get('company_name'):
            return err(_("No company name"))
            
        if len(data['company_name']) > max_field_length(Contact, 'company_name'):
            return err(_("Company name too long"))
        
        # one shalt not save u'' into date field.
        data['date_of_birth'] = None
            
    # common fields:
    # email is not required
    if 'email' in data:
        if len(data['email']) > max_field_length(Contact, 'email'):
            return err(_("Email address too long"))
        if 0 < len(data['email']) < 6:  # there's something entered, but nothing useful
            return err(_("Email address too short"))

        # validate email with regex:
        # ^[\w\d._+%]+  a string with any number of characters, numbers, and ._+% signs
        # @[\w\d.-]{2,} an @ sign followed by domain name of at least 2 characters long (can contain . and -)
        # \.\w{2,4}$'   domain (2-4 alphabetic characters)
        m = re.search('([\w.-]+)@([\w.-]+)', data['email'])
        if not m or not m.group() or data['email'] not in m.group():
            return err(_("Invalid email address"))
    else:
        data['email'] = None

    # country: check for correct code
    if 'country' in data:
        if data['country'] not in country_by_code:
            return err(_("Country does not exist"))
    
    # other, non-mandatory fields: check length only
    def check_length(d, l):
        if d:
            if len(d) > l:
                return False
            else:
                return True
        else:
            return True
        
    # street_address
    if not check_length(data.get('street_address'), max_field_length(Contact, 'street_address')):
        return err(_("Street address too long"))
    
    # postcode
    if not check_length(data.get('postcode'), max_field_length(Contact, 'postcode')):
        return err(_("Post code too long"))
        
    # city
    if not check_length(data.get('city'), max_field_length(Contact, 'city')):
        return err(_("City name too long"))
    
    # state 
    if not check_length(data.get('state'), max_field_length(Contact, 'state')):
        return err(_("State name too long"))
    
    # phone
    if not check_length(data.get('phone'), max_field_length(Contact, 'phone')):
        return err(_("Phone number too long"))

    # vat
    if not check_length(data.get('vat'), max_field_length(Contact, 'vat')):
        return err(_("VAT number too long"))
    
    # everything OK
    return {'status': True, 'data': data, 'message': None}