Permalink
Browse files

Initial checkin from Sourceforge-based repository.

Historical changes ignored; taking the opportunity to restructure app
for the much better Django-1.4 layout.
  • Loading branch information...
1 parent 363c543 commit 7e4b9e9b5f3347fea1771d2cc62e9442b7c08c2f @chmarr committed Aug 2, 2012
Showing with 7,701 additions and 0 deletions.
  1. +339 −0 COPYING
  2. +16 −0 COPYRIGHT
  3. +39 −0 README
  4. +20 −0 artshow-utils/apply_space_fees.py
  5. +52 −0 artshow-utils/apply_winnings_and_commission.py
  6. +72 −0 artshow-utils/createinvforbidder.py
  7. +101 −0 artshow-utils/email1.py
  8. +44 −0 artshow-utils/integrate_cheques.py
  9. +94 −0 artshow-utils/integrate_reg_db.py
  10. +33 −0 artshow-utils/invoicegen.py
  11. +22 −0 artshow-utils/loadbatchscan.py
  12. +68 −0 artshow-utils/overgrid.py
  13. +229 −0 artshow-utils/print_cheques.py
  14. +36 −0 artshow-utils/scanner_reader.py
  15. +30 −0 artshow-utils/sent_cheque_details.py
  16. +25 −0 artshow-utils/tweak.py
  17. 0 artshow/__init__.py
  18. +83 −0 artshow/addbidder.py
  19. +432 −0 artshow/admin.py
  20. +14 −0 artshow/artshow_settings.py
  21. +76 −0 artshow/bidsheets.py
  22. +111 −0 artshow/cashier.py
  23. +114 −0 artshow/cheques.py
  24. +157 −0 artshow/csvreports.py
  25. +40 −0 artshow/email1.py
  26. +1 −0 artshow/fixtures/artshowpaymenttypes.json
  27. +1 −0 artshow/fixtures/artshowspaces.json
  28. +155 −0 artshow/invoicegen.py
  29. +10 −0 artshow/media/styles.css
  30. +497 −0 artshow/migrations/0001_initial.py
  31. +247 −0 artshow/migrations/0002_invoicepayment.py
  32. +234 −0 artshow/migrations/0003_auto__del_field_invoice_total_paid.py
  33. +235 −0 artshow/migrations/0004_auto__add_field_artist_website.py
  34. +236 −0 artshow/migrations/0005_auto__add_field_piece_code.py
  35. +234 −0 artshow/migrations/0006_fixup_piece_codes.py
  36. +237 −0 artshow/migrations/0007_auto__add_field_piece_media.py
  37. +248 −0 artshow/migrations/0008_auto__add_chequepayment.py
  38. 0 artshow/migrations/__init__.py
  39. +94 −0 artshow/mod11codes.py
  40. +332 −0 artshow/models.py
  41. +135 −0 artshow/pdfreports.py
  42. +298 −0 artshow/processbatchscan.py
  43. +189 −0 artshow/reports.py
  44. +74 −0 artshow/static/cashierscript.js
  45. +2 −0 artshow/static/cashierstyle.css
  46. +4 −0 artshow/static/jquery.min.js
  47. +37 −0 artshow/templates/admin/email_selected_confirmation.html
  48. +7 −0 artshow/templates/artshow/artist-mailing-label.html
  49. +12 −0 artshow/templates/artshow/artist-panel-report.html
  50. +23 −0 artshow/templates/artshow/artist-payment-report.html
  51. +10 −0 artshow/templates/artshow/artist-piece-report.html
  52. +18 −0 artshow/templates/artshow/artist_main.html
  53. +7 −0 artshow/templates/artshow/bidderadd.html
  54. +16 −0 artshow/templates/artshow/bidderbulkadd.html
  55. +20 −0 artshow/templates/artshow/cashier.html
  56. +47 −0 artshow/templates/artshow/cashier_bidder.html
  57. +6 −0 artshow/templates/artshow/cashier_invoice.html
  58. +10 −0 artshow/templates/artshow/dataentry.html
  59. +7 −0 artshow/templates/artshow/generate-piece-stickers.html
  60. +7 −0 artshow/templates/artshow/index.html
  61. +7 −0 artshow/templates/artshow/kit-contents.html
  62. +12 −0 artshow/templates/artshow/panel-artist-report.html
  63. +18 −0 artshow/templates/artshow/reports-artists.html
  64. +19 −0 artshow/templates/artshow/reports-balances.html
  65. +38 −0 artshow/templates/artshow/reports-winning-bidders.html
  66. +35 −0 artshow/templates/artshow/reports.html
  67. +12 −0 artshow/templates/artshow/sales-percentiles.html
  68. +51 −0 artshow/templates/artshow/show-summary.html
  69. +19 −0 artshow/templates/artshow/voice-auction.html
  70. +23 −0 artshow/templates/base_generic.html
  71. +23 −0 artshow/tests.py
  72. +38 −0 artshow/urls.py
  73. +17 −0 artshow/views.py
  74. 0 artshowjockey/__init__.py
  75. +169 −0 artshowjockey/settings.py
  76. +154 −0 artshowjockey/settings.py.orig
  77. +11 −0 artshowjockey/urls.py
  78. +28 −0 artshowjockey/wsgi.py
  79. +10 −0 manage_artshowjockey.py
  80. +1 −0 num2word/__init__.py
  81. +62 −0 num2word/num2word.py
  82. +154 −0 num2word/num2word_DE.py
  83. +137 −0 num2word/num2word_EN.py
  84. +63 −0 num2word/num2word_EN_GB.py
  85. +55 −0 num2word/num2word_EN_GB_old.py
  86. +147 −0 num2word/num2word_ES.py
  87. +44 −0 num2word/num2word_EU.py
  88. +119 −0 num2word/num2word_FR.py
  89. +264 −0 num2word/num2word_base.py
  90. +34 −0 num2word/orderedmapping.py
View
339 COPYING

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -0,0 +1,16 @@
+Artshow-Jockey - Art Show Management Software
+Copyright (C) 2009,2010 Chris Cogdon
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
View
39 README
@@ -0,0 +1,39 @@
+Artshow-Jockey - Art Show Management Software
+Copyright (c) 2009,2010 Chris Cogdon
+
+Installation
+------------
+
+This is a Django application. Install Django by following the standard Django instructions
+and create a new project. Copy the "artshow" directory from this installation into
+your project (or symlink from there to here) and make the following modifications
+to the top-level files:
+
+to urls.py, urlpatters, add:
+
+ (r'^artshow/', include ( 'yourprojectname.artshow.urls' ) ),
+
+you should also enable django's administration interface, if you haven't already,
+as Artshow Jockey relies heavily on it.
+
+to settings.py, TEMPLATE_DIRS, add:
+
+ "/full/path/to/yourprojectname/artshow/templates/",
+
+to settings.py, INSTALLED_APPS, add:
+
+ "yourprojectname.artshow',
+
+and add the following to settings.py as well, with appropriate mods:
+
+ARTSHOW_SHOW_NAME = "MY AWESOME ART SHOW"
+ARTSHOW_TAX_RATE = "0.0925"
+ARTSHOW_TAX_DESCRIPTION = "%9.25 CA TAX"
+
+Once all that's done, you should be able to go ./manage.py syncdb and get everything set up.
+
+Setting up the data
+-------------------
+
+First thing you'll want to do is add some space types so you can allocate spaces.
+
@@ -0,0 +1,20 @@
+#! /usr/bin/env python
+# Artshow Jockey
+# Copyright (C) 2009, 2010 Chris Cogdon
+# See file COPYING for licence details
+
+from artshow.models import Artist, Payment, PaymentType
+import datetime
+
+for a in Artist.objects.all():
+ payment_type = PaymentType.objects.get(name="Panel Fee")
+ total = 0
+ for alloc in a.allocation_set.all():
+ total += alloc.space.price * alloc.allocated
+ if total <= 0:
+ print a, total, "not applying fees"
+ else:
+ print a, total
+ allocated_spaces_str = ", ".join ( "%s:%s" % (al.space.shortname,al.allocated) for al in a.allocation_set.all() )
+ payment = Payment ( artist=a, amount=-total, payment_type=payment_type, description="Panel Fee (%s)" % allocated_spaces_str, date=datetime.datetime.now() )
+ payment.save ()
@@ -0,0 +1,52 @@
+#! /usr/bin/env python
+# Artshow Jockey
+# Copyright (C) 2009, 2010 Chris Cogdon
+# See file COPYING for licence details
+
+from artshow.models import Artist, Payment, PaymentType, Bid
+import datetime, decimal
+import optparse
+from settings import ARTSHOW_COMMISSION
+
+def apply_winnings_and_commissions ( ids=None ):
+ if ids:
+ artists = Artist.objects.filter(id__in=ids)
+ else:
+ artists = Artist.objects.all()
+ for a in artists:
+ pt_winning = PaymentType.objects.get(name="Winnings")
+ pt_commission = PaymentType.objects.get(name="Commission")
+ total_winnings = 0
+ total_pieces = 0
+ pieces_with_bids = 0
+ for piece in a.piece_set.all():
+ if piece.status != 0:
+ total_pieces += 1
+ try:
+ top_bid = piece.top_bid()
+ total_winnings += top_bid.amount
+ pieces_with_bids += 1
+ except Bid.DoesNotExist:
+ pass
+ commission = total_winnings * decimal.Decimal(ARTSHOW_COMMISSION)
+
+ if total_pieces > 0:
+ payment = Payment ( artist=a, amount=total_winnings, payment_type=pt_winning, description="Sales (%d piece%s, %d with bid%s)" % ( total_pieces, total_pieces!=1 and "s" or "", pieces_with_bids, pieces_with_bids != 1 and "s" or ""), date=datetime.datetime.now() )
+ payment.save ()
+
+ if commission > 0:
+ payment = Payment ( artist=a, amount=-commission, payment_type=pt_commission, description="10% Commission on sales", date=datetime.datetime.now() )
+ payment.save ()
+
+def get_options ():
+ parser = optparse.OptionParser ()
+ parser.add_option ( "--ids", type="str", default=None )
+ opts, args = parser.parse_args ()
+ if opts.ids:
+ opts.ids = opts.ids.split(",")
+ opts.ids = [int(x) for x in opts.ids]
+ return opts
+
+if __name__ == "__main__":
+ opts = get_options ()
+ apply_winnings_and_commissions ( opts.ids )
@@ -0,0 +1,72 @@
+#! /usr/bin/env python26
+# Artshow Jockey
+# Copyright (C) 2009, 2010 Chris Cogdon
+# See file COPYING for licence details
+
+from artshow.models import Bidder, BidderId, Invoice, InvoiceItem
+import optparse, datetime
+import decimal
+import settings
+
+
+def get_options ():
+ parser = optparse.OptionParser ()
+ parser.add_option ( "--test", default=False, action="store_true" )
+ opts, args = parser.parse_args()
+ opts.bidderid = args[0]
+ return opts
+
+def create_invoice ( bidderid_id, test=False ):
+
+ now = datetime.datetime.now ()
+
+ bidderid = BidderId.objects.get ( id=bidderid_id )
+ bidder = bidderid.bidder
+ print "Bidder is", unicode(bidder)
+
+ pieces_to_add = []
+ total = 0
+
+ for b in bidder.top_bids():
+ print b.piece.id, unicode(b), b.buy_now_bid and "BuyNow" or "", b.piece.status, b.piece.voice_auction and "Voice auction" or ""
+ if b.piece.status == 2:
+ print "adding"
+ print
+ pieces_to_add.append ( b.piece )
+ else:
+ print "NOT ADDING ***"
+ print
+
+ input = raw_input ( "Proceed?" )
+ if input != "y":
+ raise SystemExit
+
+ if not test:
+ items_to_add = []
+ invoice = Invoice ( payer = bidder, paid_date=now )
+ total = 0
+ for p in pieces_to_add:
+ top_bid = p.top_bid ()
+ item = InvoiceItem ( piece=p, invoice=invoice, price=top_bid.amount )
+ items_to_add.append ( item )
+ total += top_bid.amount
+ tax_rate = decimal.Decimal(settings.ARTSHOW_TAX_RATE)
+ tax_paid = total * tax_rate
+ total_incl_tax = total + tax_paid
+ invoice.tax_paid = tax_paid
+ invoice.total_paid = total_incl_tax
+ invoice.save ()
+ for i in items_to_add:
+ i.invoice = invoice
+ i.save ()
+ for p in pieces_to_add:
+ p.status = 3
+ p.save ()
+
+ print "Invoice Created:", invoice.id
+
+
+if __name__ == "__main__":
+ opts = get_options ()
+ create_invoice ( opts.bidderid, test=opts.test )
+
View
@@ -0,0 +1,101 @@
+#! /usr/bin/env python26
+# Artshow Jockey
+# Copyright (C) 2009, 2010 Chris Cogdon
+# See file COPYING for licence details
+
+# TODO: Handle setting DJANGO environment variable
+
+import optparse, subprocess
+from django.template import Template, Context
+from artshow.models import Artist
+from artshow.email1 import make_email
+import sqlite3
+
+default_db = "data/artshowproj.db"
+default_wrap_cols = 79
+
+def send_email ( data, test=False ):
+
+ if test:
+ print data
+ print "-----------"
+ else:
+ p = subprocess.Popen ( ("/usr/lib/sendmail", "-t"), stdin=subprocess.PIPE )
+ p.stdin.write ( data )
+ p.stdin.close ()
+ print "sent email"
+
+
+def get_template ( db, template_name ):
+ cur = db.cursor ()
+ cur.execute ( "select template from artshow_emailtemplate where name=? limit 1", ( template_name, ) )
+ row = cur.fetchone ()
+ if row == None:
+ raise KeyError ( "email template %s not found" % template_name )
+ return row[0]
+
+def get_artist_ids ( db, ids, filters ):
+
+ cur = db.cursor ()
+ if filters:
+ cur.execute ( "create temporary table filters ( id int, state bool )" )
+ for f_str in filters:
+ checkoff,state = f_str.split("=")
+ state = {"yes":True,"no":False}[state.lower()]
+ cur.execute ( "insert into filters values ( (select id from artshow_checkoff where name=? or shortname=?), ? )", ( checkoff, checkoff, state ) )
+ cur.execute ( """
+create temporary table match_list as
+select artshow_artist.id as artist_id, count(positive_checkoffs.checkoff_id) as positive_matches, count(negative_checkoffs.checkoff_id) as negative_matches from artshow_artist
+left join ( select artshow_artist_checkoffs.artist_id as artist_id, artshow_artist_checkoffs.checkoff_id as checkoff_id from artshow_artist_checkoffs join filters on artshow_artist_checkoffs.checkoff_id=filters.id where filters.state=?) as negative_checkoffs on artshow_artist.id=negative_checkoffs.artist_id
+left join ( select artshow_artist_checkoffs.artist_id as artist_id, artshow_artist_checkoffs.checkoff_id as checkoff_id from artshow_artist_checkoffs join filters on artshow_artist_checkoffs.checkoff_id=filters.id where filters.state=?) as positive_checkoffs on artshow_artist.id=positive_checkoffs.artist_id
+group by artshow_artist.id
+having positive_matches=(select count(*) from filters where state=?) and negative_matches=0
+""", ( False, True, True ) )
+ else:
+ cur.execute ( "create temporary table match_list as select artshow_artist.id as artist_id from artshow_artist" )
+
+ if ids == "active":
+ cur.execute ( "select artshow_artist.id from artshow_artist join match_list on artshow_artist.id=match_list.artist_id where ( select sum(requested) from artshow_allocation where artist_id = artshow_artist.id) > 0" )
+ elif ids == "showing":
+ cur.execute ( "select artshow_artist.id from artshow_artist join match_list on artshow_artist.id=match_list.artist_id where ( select sum(allocated) from artshow_allocation where artist_id = artshow_artist.id) > 0" )
+ elif ids == "all":
+ cur.execute ( "select artshow_artist.id from artshow_artist join match_list on artshow_artist.id=match_list.artist_id" )
+ else:
+ cur.execute ( "create temporary table temp_ids ( id int )" )
+ for id in ids:
+ cur.execute ( "insert into temp_ids values (?)", ( id, ) )
+ cur.execute ( "select artshow_artist.id from artshow_artist where artistid in temp_ids" )
+
+ while True:
+ row = cur.fetchone()
+ if row==None: break
+ yield row[0]
+
+
+def send_emails ( template_name, db_name, ids=None, cols=default_wrap_cols, test=False, filters=[] ):
+ db = sqlite3.connect ( db_name )
+ template_str = get_template ( db, template_name )
+ for artist_id in get_artist_ids ( db, ids, filters ):
+ artist_obj = Artist.objects.get(id=artist_id)
+ email = make_email ( artist_obj, template_str, cols=cols )
+ send_email ( email, test=test )
+
+
+def get_opts ():
+ parser = optparse.OptionParser ()
+ parser.add_option ( "--test", default=False, action="store_true" )
+ parser.add_option ( "--db", default=default_db )
+ parser.add_option ( "--ids", default="active", type="str" )
+ parser.add_option ( "--cols", type="int", default=default_wrap_cols )
+ parser.add_option ( "--filter", action="append", default=[] )
+ opts, args = parser.parse_args ()
+ if opts.ids not in ( "active", "showing", "all" ):
+ s1 = opts.ids.split(',')
+ opts.ids = [ int(x) for x in s1 ]
+ opts.template = args[0]
+ return opts
+
+
+if __name__ == "__main__":
+ opts = get_opts ()
+ send_emails ( opts.template, opts.db, ids=opts.ids, cols=opts.cols, test=opts.test, filters=opts.filter )
@@ -0,0 +1,44 @@
+#! /usr/bin/env python
+# Artshow Jockey
+# Copyright (C) 2009, 2010 Chris Cogdon
+# See file COPYING for licence details
+
+from artshow.models import Artist, Payment, PaymentType
+import optparse, decimal, csv, datetime
+
+def integrate_cheques ( csv_file ):
+ c = csv.DictReader(open(csv_file))
+
+ pt = PaymentType.objects.get(name='Payment Sent')
+
+ for row in c:
+ try:
+ artistid = row['artist']
+ chq = row['chq']
+ amount = decimal.Decimal(row['amount'])
+ except:
+ print >>sys.stderr, "bad row:", row
+ continue
+ try:
+ artist = Artist.objects.get(artistid=artistid)
+ except Artist.DoesNotExist:
+ print >>sys.stderr, "artist %d not found"
+ continue
+
+ payment = Payment(artist=artist, amount=-amount, payment_type=pt, description="Disbursement Cheque #"+chq, date=datetime.datetime.now() )
+ payment.save ()
+
+
+def get_options ():
+ parser = optparse.OptionParser ()
+ opts, args = parser.parse_args()
+ opts.infile = args[0]
+ return opts
+
+
+def main ():
+ opts = get_options ()
+ integrate_cheques ( opts.infile )
+
+if __name__ == "__main__":
+ main ()
Oops, something went wrong.

0 comments on commit 7e4b9e9

Please sign in to comment.