-
Notifications
You must be signed in to change notification settings - Fork 0
/
record-invoices.py
executable file
·216 lines (134 loc) · 5.55 KB
/
record-invoices.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/env python
"""record_invoices.
Record invoices.
For each customer, infer from their memebership type the amount for
which they should be invoiced. Record an invoice dated the first of
this month for that amount.
Optionally, specify one customer, or override date or amount.
Usage:
record_invoices [options]
record_invoices --all-customers [options]
Options:
--debug Print debugging output. [default: False]
--date=<INVDATE> The date of record for the invoice. [default: the first]
--all-customers Create invoices for all active customers [default: False]
--custid=<ID> Create an invoice for this particular customer [default: -1]
--amount=<AMT> Override amount of the invoice(s).
--description=<DESC> Override description on the invoice(s).
--inactive Permit assigning invoices to inactive customers [default: False]
--doit Actually send the invoices. Otherwise, is a no-op. [default: False]
--nobatch DO NOT send in batches. [default: False]
--batchsize=<SIZE> Size of batches to send [default: 10]
"""
from docopt import docopt
import requests
import json
import hackerspace_utils as hu
import qbo_utils as qu;
import pandas as pd;
import sys
import dateparser
from quickbooks import Oauth2SessionManager
from quickbooks import QuickBooks
from quickbooks.objects.customer import Customer
from quickbooks.objects import Account
from quickbooks.objects import Invoice
from quickbooks.objects import Item
from quickbooks.batch import batch_create
from quickbooks.objects.detailline import *
cols_we_want = {
"QBO ID" : "QBOID",
"Name" : "name",
"Email" : 'email',
"Phone Number" : 'phone',
"TYPE" : 'type',
"Join Date" : 'joindate',
}
authbag = hu.get_auth_bag()
def make_invoice():
pass
def display_invoice(inv):
bag = {}
fmt="{name}: {amount}, on {date} "
bag['name'] = inv.CustomerRef.name
bag['amount'] = inv.TotalAmt
bag['date'] = inv.TxnDate
return fmt.format(**bag)
def do_batch(thebatch,qbo_client):
if(debug):
print("Batch create..")
results = batch_create(thebatch,qb=qbo_client)
if (len(results.faults) > 0):
print("Invoice submission errors...")
print("\n".join([x.to_json() for x in results.faults]))
sys.exit()
return results
def main():
global subset
total_amount = 0
if (arguments['--inactive']):
subset = hu.all_cust_df(cols_we_want)
else:
subset = hu.active_cust_df(cols_we_want)
qbo_client = qu.open_qbo_client()
thedate = arguments['--date']
itemlist = pd.DataFrame([ { 'obj':item , 'desc': item.Description , 'id': int(item.Id)} for item in Item.filter(qb=qbo_client) ])
qbolist = pd.DataFrame([ { 'obj':cust , 'id': int(cust.Id)} for cust in qu.cust_iterable(Active=True) ])
if ( arguments['--custid'] != -1 ):
if (debug):
print("# Custid '{0}' specified. ".format(arguments['--custid']))
subset = subset[subset['QBOID'] == arguments['--custid']]
newlen = len(subset)
if (newlen != 1):
print("# More than one customer matched '{0}'? fail.".format(arguments['--custid']))
print(subset)
sys.exit()
batch = []
count = 0
for index, row in subset.iterrows():
cust =qbolist[qbolist['id']==int(row['QBOID'])].iloc[0]['obj']
print("# Processing {name} ".format(**row))
if ( arguments['--date'].date() < dateparser.parse(row['joindate']).date() ):
# Is the date of before this person joined?
print("# Invoice date precedes member join date; skipping.")
continue
myinv = qu.build_invoice(itemlist,cust,row,thedate)
if(not (arguments['--description'] is None)):
myinv.CustomerMemo = {'value': arguments['--description']}
total_amount += myinv.TotalAmt
myinv.TxnDate = arguments['--date'].date().isoformat()
print(display_invoice(myinv))
count += 1
if (arguments['--doit']):
if ( arguments['--nobatch'] ) :
myinv = myinv.save(qb=qbo_client)
else:
batch.append(myinv)
if (len(batch) >= arguments['--batchsize']):
results = do_batch(batch,qbo_client)
batch = []
else:
print ("# Not saving")
if ( len(batch) > 0 and arguments['--doit'] ):
results = do_batch(batch,qbo_client)
print(" Found {0} invoices to submit, ".format(count))
print(" Totalling ${0:.2f} ".format(total_amount))
if __name__ == '__main__':
arguments = docopt(__doc__, version='Naval Fate 2.0')
debug = arguments['--debug']
arguments['--batchsize'] = int(arguments['--batchsize'])
arguments['--custid'] = int(arguments['--custid'])
# if (debug): api_functions.debug=True
if ( arguments['--date'] == "the first" ) :
arguments['--date'] = dateparser.parse("{0} days ago".format(dateparser.parse("today").day -1 ))
else:
arguments['--date'] = dateparser.parse(arguments['--date'])
if (arguments['--doit'] ) :
qu.doit =True;
else:
print("\n Not saving invoices. Specify '--doit' or get a no-op\n")
if (debug):
hu.debug = True;
qu.debug=True
print(arguments)
main()