def list(request):
    req = request.REQUEST
    q = Debits.objects.filter()
    if param_exist("sort", req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit", req):
        start = req["start"]
        limit = req["limit"]
        list = q[start : start + limit]
    else:
        list = q

    res = []
    for exp in list:
        res.append(
            {
                "id": exp.id,
                "amount": exp.amount,
                "since": exp.since,
                "text": exp.text,
                "paymentType_name": exp.paymentType.name,
                "subCategory_name": exp.subCategory.name,
                "paymentTypeId": exp.paymentType.id,
                "subCategoryId": exp.subCategory.id,
                "day": exp.day,
                "last": exp.last,
            }
        )

    data = '{"total": %s, "rows": %s}' % (q.count(), JsonParser.parse(res))
    return data
def monthCalc(request):
    req = request.REQUEST
    if param_exist("date",req):
        date = DateService.parse(req['date'])
    else:
        date = DateService.today()

    fromDate = DateService.firstDateOfMonth(date)
    toDate = DateService.lastDateOfMonth(date)
    
    q = Expense.objects.extra(select={'sum': 'sum(amount)'}).values('sum','date')
    #q = Expense.objects.filter(date__gte=fromDate, date__lte=toDate)
    q = q.filter(date__gte=fromDate, date__lte=toDate).order_by('date')
    if param_exist("subC",req):
        q = q.filter(subCategory=req['subC'])
    elif param_exist("cat",req):
        c = SubCategory.objects.filter(category=req['cat'])
        q = q.filter(subCategory__in=c)
    if param_exist("payT",req):
        q = q.filter(paymentType=req['payT'])
    q.query.group_by = ['date']
    
    list = []
    for exp in q:
        list.append('[%d,%s]' % (int(DateService.toLong(exp['date'])),exp['sum']))
    
    data = "[" + ",".join(list) + "]"
    return data
def list(request):
    req = request.REQUEST
    
    # find close date
    
    dateQuery = CardDates.objects.filter(closeDate__gt=DateService.todayDate())
    dateQuery = dateQuery.order_by('closeDate')
    if dateQuery.count()>0:
        dt = dateQuery[:1][0]
    else:
        dt = CardDates(closeDate=DateService.todayDate(), expireDate=DateService.todayDate())
    
    q = CardData.objects.extra(where=["ADDDATE(date, INTERVAL ((instalments+1) * 30) DAY) > '%s'" % DateService.invert(dt.closeDate)])
    if param_exist("sort",req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit",req):
        start = req['start']
        limit = req['limit']
        list = q[start:start+limit]
    else:
        list = q

    res = []
    for exp in list:
        rem = FinancialService.remainInstalments(exp.date, dt.closeDate, exp.instalments)
        if rem >= 0:
            res.append({'id': exp.id, 'date': exp.date,
                            'shop': exp.shop, 'instalments': exp.instalments,
                            'card_id': exp.card.id, 'card_name': exp.card.name,
                            'total': exp.total, 'own': exp.own,
                            'partial': exp.total / exp.instalments,
                            'remain': rem })
    
    data = '{"total": %s,"close": "%s", "expire": "%s", "rows": %s}' % (CardData.objects.count(), DateService.format(dt.closeDate),DateService.format(dt.expireDate), JsonParser.parse(res))
    return data
def calc(request):
    req = request.REQUEST
    if param_exist("date",req):
        date = DateService.parse(req['date'])
    else:
        date = DateService.today()

    fromDate = DateService.firstDateOfMonth(date)
    toDate = DateService.lastDateOfMonth(date)
    
    q = Expense.objects.filter(date__gte=fromDate, date__lte=toDate)
    if param_exist("subC",req):
        q = q.filter(subCategory=req['subC'])
    elif param_exist("cat",req):
        c = SubCategory.objects.filter(category=req['cat'])
        q = q.filter(subCategory__in=c)
    if param_exist("payT",req):
        q = q.filter(paymentType=req['payT'])
        
    sum=0
    for exp in q:
        sum+=exp.amount
    
    today = DateService.today()
    if today.tm_year==date.tm_year and today.tm_mon==date.tm_mon:
        days=today.tm_mday
    else:
        days=DateService.lastDayOfMonth(date)

    avg = sum / days
    data = '{"data":{"total":%s,"avg":%s}}' % (sum,avg)
    return data
def list(request):
    req = request.REQUEST
    q = Expense.objects.filter()
    if param_exist("amountStart",req):
        q = q.filter(amount__gte=req['amountStart'])
    if param_exist("amountEnd",req):
        q = q.filter(amount__lte=req['amountEnd'])
    if param_exist("dateStart",req):
        q = q.filter(date__gte=DateService.invert(req['dateStart']))
    if param_exist("dateEnd",req):
        q = q.filter(date__lte=DateService.invert(req['dateEnd']))
    if param_exist("subC",req):
        q = q.filter(subCategory=req['subC'])
    elif param_exist("cat",req):
        c = SubCategory.objects.filter(category=req['cat'])
        q = q.filter(subCategory__in=c)
    if param_exist("payT",req):
        q = q.filter(paymentType=req['payT'])
    if param_exist("sort",req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit",req):
        list = q[req['start']:req['start']+req['limit']]
    else:
        list = q
    
    res = []
    for exp in list:
        res.append({'id': exp.id, 'amount': exp.amount, 'date': exp.date,
                    'text': exp.text, 'paymentType_name': exp.paymentType.name,
                    'subCategory_name': exp.subCategory.name, 'paymentTypeId': exp.paymentType.id,
                    'subCategoryId': exp.subCategory.id})

    data = '{"total": %s, "rows": %s}' % (q.count(), JsonParser.parse(res))
    return data
def list(request):
    req = request.REQUEST
    q = Category.objects.filter()
    if param_exist("sort",req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit",request.REQUEST):
        start = request.REQUEST['start']
        limit = request.REQUEST['limit']
        lst = q[start:start+limit]
    else:
        lst = q
    data = '{"total": %s, "rows": %s}' % (Category.objects.count(), JsonParser.parse(lst))
    return data
def list(request):
    req = request.REQUEST
    q = PaymentType.objects.filter()
    if param_exist("sort", req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit", req):
        start = req["start"]
        limit = req["limit"]
        list = q[start : start + limit]
    else:
        list = q
    data = '{"total": %s, "rows": %s}' % (PaymentType.objects.count(), JsonParser.parse(list))
    return data
def get_loan_to_save(data, amount = None, lid = None):
    if not lid:
        l = Loan.objects.get(pk=data['loan.id'])
    else:
        l = Loan.objects.get(pk=lid)
    if not amount:
        amount = round(l.amount / l.instalments,2)
        if amount > l.remain:
            amount = l.remain 
        validate_amount(amount)

    if param_exist("id",data):
        p = Payment.objects.get(pk=data['id'])    
        prevAmount = p.amount
    else:
        p = Payment(loan=l)
        prevAmount = None
    
    if checkPayment(l,amount,prevAmount):
        if prevAmount:
            diff = float(prevAmount) - float(amount)
            l.remain = unicode(float(l.remain) + diff)
        else:
            l.remain = unicode(float(l.remain) - float(amount))

        p.amount=amount
        p.date=DateService.parseDate(data['date'])
    else:
        raise ValidationError(_('The entered amount is greater than the amount owed.'))
    return (l,p)
def list(request):
    req = request.REQUEST
    q = Person.objects.filter()
    if param_exist("sort",req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit",req):
        start = req['start']
        limit = req['limit']
        list = q[start:start+limit]
    else:
        list = q
        
    res = []
    for p in list:
        res.append({'id': p.id, 'name': p.name, 'count': p.loans.active().count()})
    data = '{"total": %s, "rows": %s}' % (Person.objects.count(), JsonParser.parse(res))
    return data
def stats_category(request):
    if param_exist('month', request.REQUEST):
        current = request.REQUEST['month']
    else:
        current = CategoryStatsData.objects.latest().month 
        
    q = StatsData.objects.all().order_by('-month')[:6]
    data = [{'label': "%s-%s" % (str(d.month)[:4], str(d.month)[5:]), 'value': str(d.month)} for d in q]
    chardata, values = StatsService.create_category_chart(current)
    return {'chartdata': chardata, 'values': d, 'monthList': sorted(data, key=lambda d: int(d['value']), reverse=True), 'current': current}    
def fromParams(req):
    s = SubCategory.objects.get(pk=req['subCategory.id'])
    p = PaymentType(pk=req['paymentType.id'])
    if param_exist("text",req):
        text = req['text']
    else:
        text = s.name 

    if param_exist("id",req):
        e = Expense.objects.get(pk=req['id'])
    else:
        e = Expense()
        
    e.text=text
    e.date=DateService.invert(req['date']) 
    e.amount=req['amount']
    e.subCategory=s
    e.paymentType=p
    return e
def list(request):
    req = request.REQUEST
    q = CardDates.objects.filter()
    if param_exist("sort",req):
        q = q.order_by(sortMethod(req))
    if param_exist("limit",req):
        start = req['start']
        limit = req['limit']
        list = q[start:limit]
    else:
        list = q

    res = []
    for exp in list:
        res.append({'id': exp.id, 'closeDate': exp.closeDate,
                    'expireDate': exp.expireDate, 'card': exp.card.name,
                    'card_id': exp.card.id})
    
    data = '{"total": %s, "rows": %s}' % (CardDates.objects.count(), JsonParser.parse(res))
    return data
def save_or_update(request):
    data = '{"success":true}'
    req = request.REQUEST
    loans = []
    
    amount = 0
    try:
        if param_exist('loan.ids', req):
            lids = req.getlist('loan.ids')
            for lid in lids:
                loans.append(get_loan_to_save(req, None, lid));
        else:
            loans.append(get_loan_to_save(req, req['amount']));
    except ValidationError, va1:
        return '{"success":false, "msg": "%s"}' % ("".join(va1.messages))
def list(request):
    req = request.REQUEST
    q = SubCategory.objects.filter()
    if param_exist("filter[0][field]",req):
        q = q.filter(category=req['filter[0][data][value]'])
    if param_exist("sort",req):
        if req['sort'] == "category":
            q = q.order_by(sortMethod(req,"category__name"), "name")
        else:
            q = q.order_by(sortMethod(req))
    if param_exist("limit",request.REQUEST):
        start = request.REQUEST['start']
        limit = request.REQUEST['limit']
        list = q[start:start+limit]
    else:
        list = q
        
    res = []
    for elem in list:
        res.append({'id': elem.id, 'name': elem.name, 'category': elem.category.name,
                    'categoryId': elem.category.id})
        
    data = '{"total": %s, "rows": %s}' % (SubCategory.objects.count(), JsonParser.parse(res))
    return data
def sixMonthCalc(request):
    req = request.REQUEST
    if param_exist("date",req):
        date = DateService.parse(req['date'])
    else:
        date = DateService.today()

    fromDate = DateService.addMonth(DateService.firstDateOfMonth(date),-6)
    toDate = DateService.lastDateOfMonth(date)
    
    query = "SELECT sum(amount), date FROM expense "\
            "WHERE date between '%s' and '%s'" % (str(fromDate), str(toDate))
    if param_exist("subC",req):
        query += " AND sub_category_id = '%s'" % req['subC']
    elif param_exist("cat",req):
        c = SubCategory.objects.filter(category=req['cat'])
        query += " AND sub_category_id in (%s)" % ",".join(["'"+str(s.id)+"'" for s in c])
    if param_exist("payT",req):
        query += " AND payment_type_id = '%s'" % req['payT']
    query += " group by month(date)"
    
    cursor = connection.cursor()
    cursor.execute(query)

    list = []
    for exp in cursor.fetchall():
        sum, date = exp
        i = Income.objects.extra(select={'sum': 'sum(amount)'}).values('sum')
        i = i.filter(period = DateService.firstDateOfMonth(date.timetuple()))
        val = i[0]['sum']
        if val is None:
            val = 0
        list.append({'date': date, 'expense': sum, 'income': val})

    data = '{"rows": %s}' % (JsonParser.parse(list))
    return data
def fromParams(req):
    if param_exist("id",req):
        e = CardData(pk=req['id'])
    else:
        e = CardData()
    
    c = Card(pk=req['card.id'])
    
    e.date=DateService.invert(req['date'])
    e.shop=req['shop']
    e.instalments=req['instalments']
    e.total=req['total']
    e.card = c
    
    return e
def save(request):
    req = request.REQUEST
    p = fromParams(req);
    
    if param_exist("loan",req):
        p.own = False
    else:
        p.own = True
    
    data = '{"success":true}'
    safe = True
    try:
        p.save()
    except _mysql_exceptions.Warning:
        pass
    except Exception, e1:
        safe = False
        data = '{"success":false, msg: "%s"}' % (e1.args)
            logger.error(e)
    validate_amount(amount)
    
    if not amount or float(amount) == 0.0:
        raise ValidationError(_('Enter a valid amount.'))

    try:
        s = SubCategory.objects.get(pk=req['subCategory.id'])
    except SubCategory.DoesNotExist:
        raise ValidationError(_('Select a valid category.'))
    try:
        p = PaymentType.objects.get(pk=req['paymentType.id'])
    except (PaymentType.DoesNotExist, KeyError):
        raise ValidationError(_('Select a valid payment type.'))
        
    if param_exist("text",req):
        text = req['text']
    else:
        text = s.name 

    if param_exist("id",req):
        e = Expense.objects.get(pk=req['id'])
    else:
        e = Expense()
        
    e.text=text
    e.date=DateService.parseDate(req['date']) 
    e.amount=amount
    e.subCategory=s
    e.paymentType=p
    return e
    failed = []
    for l,p in loans:
        try:
            try:
                l.save()
            except _mysql_exceptions.Warning:
                pass        
            try:
                p.save()
                amount += float(p.amount)
            except _mysql_exceptions.Warning:
                pass        
        except Exception, e1:
            failed.append(l.reason)

    if param_exist('subCategory.id', req) and not req['subCategory.id'] == '0':
        try:
            subCategory = SubCategory.objects.get(pk=req['subCategory.id'])
            pt = getattr(settings,'LOAN_PAYMENT_TYPE', None)
            if pt:
                paymentType = PaymentType.objects.get(pk=pt)
                Expense.objects.create(amount=-1*amount,
                              text=subCategory.name,
                              date=DateService.parseDate(req['date']),
                              subCategory=subCategory,
                              paymentType=paymentType)
        except Exception, e2:
            failed.append(e2)

    if len(failed) > 0:
        return '{"success":false, "msg": "Failed to save %s"}' % ",".join(failed)
def calcPayment(request):
    req = request.REQUEST
    q = Loan.objects.filter()
    q = q.filter(person=req['person.id'])    
    
    exclude = []
    if param_exist('exclude',req):
        exc = string.split(req['exclude'],";")
        for e in exc:
            exclude.append(long(e))
           
    modf = dict()
    if param_exist('modf',req):
        moda = json.loads(req['modf'])
        for md in moda:
            modf[md['id']] = md['value']
        
    total = Decimal(req['amount'])
    remain = total
         
    res = []
    for exp in q:
        cursor = connection.cursor()
        cursor.execute("SELECT sum(amount) as sum FROM payment WHERE loan_id = %s", [exp.id])
        row = cursor.fetchone()
        sum = exp.amount
        if row[0]!=None:
            sum = exp.amount - row[0]
        
        partial = exp.amount / exp.instalments 
        pay = 0
        dr = False
        if exp.id in modf.keys():
            remain -= modf[exp.id]
            pay = modf[exp.id]
            sum -= pay
            dr = True
            
        if sum > 0:
            res.append({'id': exp.id, 'amount': exp.amount, 'date': exp.date,
                        'reason': exp.reason, 'balance': sum, 'partial': partial,
                        'pay': pay, 'remain': sum, 'dirty': dr})
    
    while remain > 0:
        resto = 0
        for l in res:
            if not l['id'] in exclude:
                if not l['id'] in modf.keys():
                    if l['remain'] < l['partial']:
                        if l['remain'] > remain:
                            l['pay'] += remain
                            l['remain'] = l['balance'] - l['pay']
                            remain = 0
                        else:
                            l['pay'] += l['remain']
                            remain -= l['remain']
                            l['remain'] = l['balance'] - l['pay']
                    else:
                        if l['partial'] > remain:
                            l['pay'] += remain
                            l['remain'] = l['balance'] - l['pay']
                            remain = 0
                        else:
                            l['pay'] += l['partial']
                            l['remain'] = l['balance'] - l['pay']
                            remain -= l['partial']
                    resto += l['remain']                             
                if remain <= 0:
                    break
        if resto == 0:
            break
    data = '{"total": "0", "rows": %s}' % (JsonParser.parse(res))        
    return data
    data = '{"total": %s, "rows": %s}' % (Income.objects.count(), JsonParser.parse(list))
    return data

@json_response
def save_or_update(request):
    req = request.REQUEST
    dt = DateService.parse(req['period']) 
    dt = datetime.date(dt.tm_year, dt.tm_mon, 1)
    
    amount=req['amount']
    try:
        validate_amount(amount)
    except ValidationError, va1:
        return '{"success":false, "msg": "%s"}' % ("".join(va1.messages))
        
    if param_exist('id', req):
        p = Income(pk=req['id'], period=dt, amount=amount)
    else:
        p = Income(period=dt, amount=amount)
    
    try:
        data = '{"success":true}'
        p.save()
    except _mysql_exceptions.Warning:
        pass
    except Exception, e1:
        data = '{"success":false, "msg": "%s"}' % (e1.args)
            
    return data

        p.own = False
    else:
        p.own = True
    
    data = '{"success":true}'
    safe = True
    try:
        p.save()
    except _mysql_exceptions.Warning:
        pass
    except Exception, e1:
        safe = False
        data = '{"success":false, msg: "%s"}' % (e1.args)
        
    if safe:
        if param_exist("addloan",req):
            pe = Person(pk=req['person.id'])
            l = Loan(person=pe, amount=p.total, date=p.date, reason=p.shop)
            try:
                l.save()
            except _mysql_exceptions.Warning:
                pass
            except Exception, e1:
                safe = False
                data = '{"success":false, "msg": "%s"}' % (e1.args)
    
    return data
    
@json_response    
def update(request):
    req = request.REQUEST