1# gnucash_business.py -- High level python wrapper classes for the business 2# parts of GnuCash 3# 4# Copyright (C) 2008,2010 ParIT Worker Co-operative <paritinfo@parit.ca> 5# This program is free software; you can redistribute it and/or 6# modify it under the terms of the GNU General Public License as 7# published by the Free Software Foundation; either version 2 of 8# the License, or (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; if not, contact: 17# Free Software Foundation Voice: +1-617-542-5942 18# 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 19# Boston, MA 02110-1301, USA gnu@gnu.org 20# 21# @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca> 22# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca> 23## @file 24# @brief High level python wrapper classes for the business parts of GnuCash 25# @author Mark Jenkins, ParIT Worker Co-operative <mark@parit.ca> 26# @author Jeff Green, ParIT Worker Co-operative <jeff@parit.ca> 27# @ingroup python_bindings 28 29import gnucash.gnucash_core_c as gnucash_core_c 30 31from gnucash.function_class import \ 32 ClassFromFunctions, extract_attributes_with_prefix, \ 33 default_arguments_decorator, method_function_returns_instance, \ 34 methods_return_instance, methods_return_instance_lists 35 36from gnucash.gnucash_core import \ 37 GnuCashCoreClass, GncNumeric, GncCommodity, Transaction, \ 38 Split, Book, GncLot, Account, GUID 39 40from gnucash.gnucash_core_c import GNC_OWNER_CUSTOMER, GNC_OWNER_JOB, \ 41 GNC_OWNER_EMPLOYEE, GNC_OWNER_VENDOR, \ 42 GNC_PAYMENT_CASH, GNC_PAYMENT_CARD, \ 43 GNC_DISC_PRETAX, GNC_DISC_SAMETIME, GNC_DISC_POSTTAX, \ 44 GNC_TAXINCLUDED_YES, GNC_TAXINCLUDED_NO, GNC_TAXINCLUDED_USEGLOBAL, \ 45 GNC_AMT_TYPE_VALUE, GNC_AMT_TYPE_PERCENT, GNC_ID_INVOICE 46 47import datetime 48 49class GnuCashBusinessEntity(GnuCashCoreClass): 50 def __init__(self, book=None, id=None, currency=None, name=None, 51 instance=None): 52 if instance == None: 53 if book==None or id==None or currency==None: 54 raise Exception( 55 "you must call GnuCashBusinessEntity.__init__ " 56 "with either a book, id, and currency, or an existing " 57 "low level swig proxy in the argument instance") 58 GnuCashCoreClass.__init__(self, book) 59 self.BeginEdit() 60 self.SetID(id) 61 self.SetCurrency(currency) 62 if name != None: 63 self.SetName(name) 64 self.CommitEdit() 65 else: 66 GnuCashCoreClass.__init__(self, instance=instance) 67 68class Customer(GnuCashBusinessEntity): pass 69 70class Employee(GnuCashBusinessEntity): pass 71 72class Vendor(GnuCashBusinessEntity): pass 73 74class Job(GnuCashBusinessEntity): 75 # override the superclass constructor, as Job doesn't require 76 # a currency but it does require an owner 77 def __init__(self, book=None, id=None, owner=None, name=None, 78 instance=None): 79 if instance == None: 80 if book==None or id==None or owner==None: 81 raise Exception( 82 "you must call Job.__init__ " 83 "with either a book, id, and owner or an existing " 84 "low level swig proxy in the argument instance") 85 GnuCashCoreClass.__init__(self, book) 86 self.SetID(id) 87 self.SetOwner(owner) 88 if name != None: 89 self.SetName(name) 90 else: 91 GnuCashCoreClass.__init__(self, instance=instance) 92 93class Address(GnuCashCoreClass): pass 94 95class BillTerm(GnuCashCoreClass): pass 96 97class TaxTable(GnuCashCoreClass): 98 def __init__(self, book=None, name=None, first_entry=None, instance=None): 99 if instance == None: 100 if book==None or name==None or first_entry==None: 101 raise Exception( 102 "you must call TaxTable.__init__ with either a " 103 "book, name, and first_entry, or an existing " 104 "low level swig proxy in the argument instance") 105 GnuCashCoreClass.__init__(self, book) 106 self.SetName(name) 107 self.AddEntry(first_entry) 108 else: 109 GnuCashCoreClass.__init__(self, instance=instance) 110 111class TaxTableEntry(GnuCashCoreClass): 112 def __init__(self, account=None, percent=True, amount=None, instance=None): 113 """TaxTableEntry constructor 114 115 You must provide an account, or be initizing this with an existing 116 swig proxy object via the instance keyword argument. 117 118 You may also optionally set the percent keyword argument to False to get 119 a fixed value instead of percentage based tax (which is the default, or 120 when percent=True). 121 122 The tax will be zero percent or zero unless you set the amount keyword 123 argument to a GncNumeric value as well. 124 """ 125 126 if instance == None: 127 if account==None: 128 raise Exception( 129 "you must call TaxTableEntry.__init__ with either a " 130 "account or an existing " 131 "low level swig proxy in the argument instance") 132 GnuCashCoreClass.__init__(self) 133 self.SetAccount(account) 134 if percent: 135 self.SetType(GNC_AMT_TYPE_PERCENT) 136 else: 137 self.SetType(GNC_AMT_TYPE_VALUE) 138 if amount != None: 139 self.SetAmount(amount) 140 else: 141 GnuCashCoreClass.__init__(self, instance=instance) 142 143class Invoice(GnuCashCoreClass): 144 def __init__(self, book=None, id=None, currency=None, owner=None, 145 date_opened=None, instance=None): 146 """Invoice Constructor 147 148 You must provide a book, id, currency and owner 149 (Customer, Job, Employee, Vendor) or an existing swig proxy object 150 in the keyword argument instance. 151 152 Optionally, you may provide a date the invoice is opened on 153 (datetime.date or datetime.datetime), otherwise today's date is used. 154 """ 155 if instance == None: 156 if book==None or id==None or currency==None or owner==None: 157 raise Exception( 158 "you must call Invoice.__init__ " 159 "with either a book, id, currency and owner, or an existing" 160 "low level swig proxy in the argument instance") 161 GnuCashCoreClass.__init__(self, book) 162 self.BeginEdit() 163 self.SetID(id) 164 self.SetCurrency(currency) 165 self.SetOwner(owner) 166 if date_opened == None: 167 date_opened = datetime.date.today() 168 self.SetDateOpened(date_opened) 169 self.CommitEdit() 170 else: 171 GnuCashCoreClass.__init__(self, instance=instance) 172 173class Bill(Invoice): 174 pass 175 176def decorate_to_return_instance_instead_of_owner(dec_function): 177 def new_get_owner_function(self): 178 (owner_type, instance) = dec_function(self) 179 if owner_type == GNC_OWNER_CUSTOMER: 180 return Customer(instance=instance) 181 elif owner_type == GNC_OWNER_JOB: 182 return Job(instance=instance) 183 elif owner_type == GNC_OWNER_EMPLOYEE: 184 return Employee(instance=instance) 185 elif owner_type == GNC_OWNER_VENDOR: 186 return Vendor(instance=instance) 187 else: 188 return None 189 return new_get_owner_function 190 191class Entry(GnuCashCoreClass): 192 def __init__(self, book=None, invoice=None, date=None, instance=None): 193 """Invoice Entry constructor 194 195 You must provide a book or be initizing this with an existing 196 swig proxy object via the instance keyword argument. 197 198 The optional invoice argument can be set to a Bill or Invoice 199 that you would like to associate the entry with. You might as well 200 assign one now, as an Entry can't exist without one, but you can 201 always use Invoice.AddEntry or Bill.AddEntry later on. 202 203 By default, the entry will be set to today's date unless you 204 override with the date argument. 205 """ 206 if instance == None: 207 if book==None: 208 raise Exception( 209 "you must call Entry.__init__ with either a " 210 "book or an existing " 211 "low level swig proxy in the argument instance") 212 GnuCashCoreClass.__init__(self, book) 213 214 if date == None: 215 date = datetime.date.today() 216 self.SetDate(date) 217 if invoice != None: 218 invoice.AddEntry(self) 219 else: 220 GnuCashCoreClass.__init__(self, instance=instance) 221 222 def test_type(self, invoice): 223 if invoice.GetTypeString() == "Invoice" and self.GetInvoice() == None: 224 raise Exception("Entry type error. Check that Entry type matches Invoice.") 225 if invoice.GetTypeString() == "Bill" and self.GetBill() == None: 226 raise Exception("Entry type error. Check that Entry type matches Bill.") 227 228# Owner 229GnuCashBusinessEntity.add_methods_with_prefix('gncOwner') 230 231owner_dict = { 232 'GetGUID' : GUID, 233 'GetCustomer' : Customer, 234 'GetVendor' : Vendor, 235 'GetEmployee' : Employee, 236 'GetJob' : Job, 237 'GetAddr' : Address, 238 'GetCurrency' : GncCommodity, 239 'GetEndOwner': GnuCashBusinessEntity, 240 'GetBalanceInCurrency': GncNumeric, 241 } 242methods_return_instance(GnuCashBusinessEntity, owner_dict) 243 244methods_return_instance_lists( 245 GnuCashBusinessEntity, { 246 'GetCommoditiesList': GncCommodity 247 }) 248 249# Customer 250Customer.add_constructor_and_methods_with_prefix('gncCustomer', 'Create') 251Customer.add_method('gncOwnerApplyPaymentSecs', 'ApplyPayment') 252 253customer_dict = { 254 'GetAddr' : Address, 255 'GetShipAddr' : Address, 256 'GetDiscount' : GncNumeric, 257 'GetCredit' : GncNumeric, 258 'GetTerms' : BillTerm, 259 'GetCurrency' : GncCommodity, 260 'GetTaxTable': TaxTable, 261 } 262methods_return_instance(Customer, customer_dict) 263 264# Employee 265Employee.add_constructor_and_methods_with_prefix('gncEmployee', 'Create') 266 267employee_dict = { 268 'GetBook' : Book, 269 'GetAddr' : Address, 270 'GetWorkday' : GncNumeric, 271 'GetRate' : GncNumeric, 272 'GetCurrency' : GncCommodity 273 } 274methods_return_instance(Employee, employee_dict) 275 276# Vendor 277Vendor.add_constructor_and_methods_with_prefix('gncVendor', 'Create') 278 279vendor_dict = { 280 'GetAddr' : Address, 281 'GetTerms' : BillTerm, 282 'GetCurrency' : GncCommodity, 283 'GetTaxTable': TaxTable, 284 } 285methods_return_instance(Vendor, vendor_dict) 286 287# Job 288Job.add_constructor_and_methods_with_prefix('gncJob', 'Create') 289Job.decorate_functions( 290 decorate_to_return_instance_instead_of_owner, 291 'GetOwner') 292 293# Address 294Address.add_constructor_and_methods_with_prefix('gncAddress', 'Create') 295 296# BillTerm 297BillTerm.add_constructor_and_methods_with_prefix('gncBillTerm', 'Create') 298 299billterm_dict = { 300 'LookupByName' : BillTerm, 301 'GetDiscount' : GncNumeric, 302 'GetParent' : BillTerm, 303 'ReturnChild' : BillTerm 304 } 305methods_return_instance(BillTerm, billterm_dict) 306 307# TaxTable 308TaxTable.add_constructor_and_methods_with_prefix('gncTaxTable', 'Create') 309 310taxtable_dict = { 311 'GetParent': TaxTable, 312 } 313methods_return_instance(TaxTable, taxtable_dict) 314 315# TaxTableEntry 316TaxTableEntry.add_constructor_and_methods_with_prefix( 317 'gncTaxTableEntry', 'Create') 318 319taxtableentry_dict = { 320 'GetAccount': Account, 321 'GetAmount': GncNumeric, 322 } 323 324# Invoice 325Invoice.add_constructor_and_methods_with_prefix('gncInvoice', 'Create') 326methods_return_instance_lists( 327 Invoice, { 'GetEntries': Entry }) 328 329Invoice.add_method('gncInvoiceRemoveEntry', 'RemoveEntry') 330Invoice.add_method('gncInvoiceUnpost', 'Unpost') 331 332# Bill 333Bill.add_methods_with_prefix('gncBill') 334 335invoice_dict = { 336 'GetTerms': BillTerm, 337 'GetCurrency': GncCommodity, 338 'GetToChargeAmount': GncNumeric, 339 'GetPostedLot': GncLot, 340 'GetPostedTxn': Transaction, 341 'GetPostedAcc': Account, 342 'GetTotal': GncNumeric, 343 'GetTotalOf': GncNumeric, 344 'GetTotalSubtotal': GncNumeric, 345 'GetTotalTax': GncNumeric, 346 'PostToAccount': Transaction, 347 'GetBook': Book, 348 } 349methods_return_instance(Invoice, invoice_dict) 350Invoice.decorate_functions( 351 decorate_to_return_instance_instead_of_owner, 352 'GetOwner', 'GetBillTo') 353 354# Entry 355Entry.add_constructor_and_methods_with_prefix('gncEntry', 'Create') 356 357Entry.add_method('gncEntryGetGUID', 'GetGUID') 358Entry.add_method('gncEntryDestroy', 'Destroy') 359 360entry_dict = { 361 'GetGUID' : GUID, 362 'GetQuantity': GncNumeric, 363 'GetInvAccount': Account, 364 'GetInvPrice': GncNumeric, 365 'GetInvDiscount': GncNumeric, 366 'GetInvTaxTable': TaxTable, 367 'GetBillAccount': Account, 368 'GetBillPrice': GncNumeric, 369 'GetBillTaxTable': TaxTable, 370 'Copy': Entry, 371 'GetInvoice': Invoice, 372 'GetBill': Invoice 373 } 374methods_return_instance(Entry, entry_dict) 375Entry.decorate_functions( 376 decorate_to_return_instance_instead_of_owner, 377 'GetBillTo' ) 378 379from gnucash.gnucash_core import decorate_monetary_list_returning_function 380Entry.decorate_functions(decorate_monetary_list_returning_function, 'GetBalTaxValues') 381