From 8dbff0717b180919e88bcd205b519ff2d04d25ca Mon Sep 17 00:00:00 2001 From: Refik Turkeli Date: Tue, 11 Dec 2012 19:39:20 +0000 Subject: [PATCH 01/10] waiving invoice (undocumented api call) --- sharpy/product.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sharpy/product.py b/sharpy/product.py index cd6c0bc..deff4d0 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -250,6 +250,29 @@ def get_customer(self, code): customers_data = customer_parser.parse_xml(response.content) return Customer(product=self, **customers_data[0]) + + def waive_invoice(self, number=None, id=None): + ''' + Adds a charge to an invoice for balancing it to 0. Useful for + getting rid of an old invoice that is now irrelevant but gets + in the way of reactivating a customer account. + + Must call run_outstanding_invoice on customer to get rid of that + invoice completely. + ''' + data = {} + + if id: + data['id'] = id + elif number: + data['number'] = number + else: + raise Exception('Must provide id or number of invoice as argument') + + response = self.client.make_request( + path='invoices/waive', + data=data, + ) def delete_all_customers(self): ''' From d1b6b3d598c05891542ea50297fce45bce9b6e3c Mon Sep 17 00:00:00 2001 From: Refik Turkeli Date: Tue, 11 Dec 2012 19:41:33 +0000 Subject: [PATCH 02/10] run outstanding invoice call --- sharpy/product.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/sharpy/product.py b/sharpy/product.py index deff4d0..680f948 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -527,6 +527,25 @@ def charge(self, code, each_amount, quantity=1, description=None): ) return self.load_data_from_xml(response.content) + def run_outstanding_invoice(self, cc_card_code=None, remote_address=None): + ''' + Execute an outstanding invoice + ''' + data = {} + + if cc_card_code: + data['ccCardCode'] = cc_card_code + + if remote_address: + data['remoteAddress'] = remote_address + + response = self.client.make_request( + path='customers/run-outstanding', + params={'code': self.code}, + data=data, + ) + return self.load_data_from_xml(response.content) + def create_one_time_invoice(self, charges): ''' Charges should be a list of charges to execute immediately. Each From 00bc5de7c22b67132b9432baa94cf0515522aa05 Mon Sep 17 00:00:00 2001 From: Cenk Alti Date: Fri, 14 Dec 2012 18:05:19 +0200 Subject: [PATCH 03/10] fix NoneType error --- sharpy/product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sharpy/product.py b/sharpy/product.py index 680f948..f0dca92 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -539,7 +539,7 @@ def run_outstanding_invoice(self, cc_card_code=None, remote_address=None): if remote_address: data['remoteAddress'] = remote_address - response = self.client.make_request( + response = self.product.client.make_request( path='customers/run-outstanding', params={'code': self.code}, data=data, From 12aefb825259ca254af2d1805019d2cd14a2e95a Mon Sep 17 00:00:00 2001 From: Cenk Alti Date: Fri, 14 Dec 2012 18:09:16 +0200 Subject: [PATCH 04/10] POST run_outstanding_invoice --- sharpy/product.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sharpy/product.py b/sharpy/product.py index f0dca92..e416fc8 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -543,6 +543,7 @@ def run_outstanding_invoice(self, cc_card_code=None, remote_address=None): path='customers/run-outstanding', params={'code': self.code}, data=data, + method='POST', ) return self.load_data_from_xml(response.content) From 2a0085b717d5286fc4858a69e35d32b0a8315365 Mon Sep 17 00:00:00 2001 From: Cenk Alti Date: Fri, 4 Jan 2013 18:23:15 +0200 Subject: [PATCH 05/10] get customer data --- sharpy/product.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sharpy/product.py b/sharpy/product.py index e416fc8..0eec01d 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -449,7 +449,16 @@ def load_data_from_xml(self, xml): customers_data = customer_parser.parse_xml(xml) customer_data = customers_data[0] self.load_data(product=self.product, **customer_data) - + + def get_data(self): + response = self.product.client.make_request( + path='customers/get', + params={'code': self.code}, + ) + customer_parser = CustomersParser() + customers_data = customer_parser.parse_xml(response.content) + return customers_data[0] + def update(self, first_name=None, last_name=None, email=None, \ company=None, is_vat_exempt=None, vat_number=None, \ notes=None, first_contact_datetime=None, \ From ddeb82852cea2d82d9098343c9da66515c00375b Mon Sep 17 00:00:00 2001 From: Cenk Alti Date: Thu, 7 Feb 2013 14:51:41 +0200 Subject: [PATCH 06/10] save all subscriptions to customer --- sharpy/product.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/sharpy/product.py b/sharpy/product.py index 0eec01d..fb9f0ac 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -437,13 +437,20 @@ def load_data(self, code, first_name, last_name, email, product, id=None,\ if meta_data: for datum in meta_data: self.meta_data[datum['name']] = datum['value'] - subscription_data = subscriptions[0] - subscription_data['customer'] = self - if hasattr(self, 'subscription'): - self.subscription.load_data(**subscription_data) - else: - self.subscription = Subscription(**subscription_data) - + + self.subscriptions = [] + for i, subscription_data in enumerate(subscriptions): + subscription_data['customer'] = self + if i == 0: + if hasattr(self, 'subscription'): + self.subscription.load_data(**subscription_data) + else: + self.subscription = Subscription(**subscription_data) + + self.subscriptions.append(self.subscription) + else: + self.subscriptions.append(Subscription(**subscription_data)) + def load_data_from_xml(self, xml): customer_parser = CustomersParser() customers_data = customer_parser.parse_xml(xml) From 4caf8f6e1fec8195c7e8c3c1cddd9cb562162073 Mon Sep 17 00:00:00 2001 From: Refik Turkeli Date: Fri, 15 Feb 2013 15:02:46 +0200 Subject: [PATCH 07/10] get customer by invoice --- sharpy/product.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/sharpy/product.py b/sharpy/product.py index fb9f0ac..6653499 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -240,11 +240,18 @@ def get_customers(self, filter_data=None): return customers - def get_customer(self, code): - + def get_customer(self, code=None, invoice_number=None): + + if code: + parameters = {'code': code} + elif invoice_number: + parameters = {'invoiceNumber': invoice_number} + else: + raise ValueError('code or invoice_number must be provided') + response = self.client.make_request( path='customers/get', - params={'code': code}, + params=parameters, ) customer_parser = CustomersParser() customers_data = customer_parser.parse_xml(response.content) From 6cf73bbffb34bee5e44942c6fcb39eac4266e4f9 Mon Sep 17 00:00:00 2001 From: Refik Turkeli Date: Tue, 26 Feb 2013 19:40:56 +0200 Subject: [PATCH 08/10] added refund information to invoice --- sharpy/parsers.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sharpy/parsers.py b/sharpy/parsers.py index 6d4b417..ae10e94 100644 --- a/sharpy/parsers.py +++ b/sharpy/parsers.py @@ -284,6 +284,23 @@ def parse_invoice(self, invoice_element): invoice['created_datetime'] = self.parse_datetime(invoice_element.findtext('createdDatetime')) invoice['charges'] = self.parse_charges(invoice_element.find('charges')) + + invoice['refunded'] = False + if invoice['paid_transaction_id']: + paid_transaction_amount = Decimal('0') + childeren_of_paid_transaction_sum = Decimal('0') + transactions = invoice_element.find('transactions') + if transactions: + for transaction in transactions: + if transaction.findtext('parentId') == invoice['paid_transaction_id']: + amount = self.parse_decimal(transaction.findtext('amount')) + childeren_of_paid_transaction_sum += amount + elif transaction.attrib['id'] == invoice['paid_transaction_id']: + paid_transaction_amount = self.parse_decimal(transaction.findtext('amount')) + + refunded_equals_received = (childeren_of_paid_transaction_sum.copy_negate() == paid_transaction_amount) + if paid_transaction_amount != 0 and refunded_equals_received: + invoice['refunded'] = True return invoice From 8b85cd309eac38297cc98e399f0d78acbf30287e Mon Sep 17 00:00:00 2001 From: Refik Turkeli Date: Fri, 1 Mar 2013 13:27:22 +0200 Subject: [PATCH 09/10] paid datetime --- sharpy/parsers.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/sharpy/parsers.py b/sharpy/parsers.py index ae10e94..746a289 100644 --- a/sharpy/parsers.py +++ b/sharpy/parsers.py @@ -282,21 +282,27 @@ def parse_invoice(self, invoice_element): invoice['billing_datetime'] = self.parse_datetime(invoice_element.findtext('billingDatetime')) invoice['paid_transaction_id'] = invoice_element.findtext('paidTransactionId') invoice['created_datetime'] = self.parse_datetime(invoice_element.findtext('createdDatetime')) - invoice['charges'] = self.parse_charges(invoice_element.find('charges')) + + invoice['paid_datetime'] = '' + if invoice['paid_transaction_id']: + transactions = invoice_element.find('transactions') + for transaction in transactions: + if transaction.attrib['id'] == invoice['paid_transaction_id']: + invoice['paid_datetime'] = self.parse_datetime(transaction.findtext('transactedDatetime')) + break invoice['refunded'] = False if invoice['paid_transaction_id']: paid_transaction_amount = Decimal('0') childeren_of_paid_transaction_sum = Decimal('0') transactions = invoice_element.find('transactions') - if transactions: - for transaction in transactions: - if transaction.findtext('parentId') == invoice['paid_transaction_id']: - amount = self.parse_decimal(transaction.findtext('amount')) - childeren_of_paid_transaction_sum += amount - elif transaction.attrib['id'] == invoice['paid_transaction_id']: - paid_transaction_amount = self.parse_decimal(transaction.findtext('amount')) + for transaction in transactions: + if transaction.findtext('parentId') == invoice['paid_transaction_id']: + amount = self.parse_decimal(transaction.findtext('amount')) + childeren_of_paid_transaction_sum += amount + elif transaction.attrib['id'] == invoice['paid_transaction_id']: + paid_transaction_amount = self.parse_decimal(transaction.findtext('amount')) refunded_equals_received = (childeren_of_paid_transaction_sum.copy_negate() == paid_transaction_amount) if paid_transaction_amount != 0 and refunded_equals_received: From e7b0588e24825b8a5ab7b3d8dc55e82ef402e229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Or=C3=A7un=20Av=C5=9Far?= Date: Wed, 6 May 2015 17:30:42 +0300 Subject: [PATCH 10/10] Let use of coupon codes. --- sharpy/product.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/sharpy/product.py b/sharpy/product.py index 6653499..067d03a 100644 --- a/sharpy/product.py +++ b/sharpy/product.py @@ -47,7 +47,7 @@ def get_plan(self, code): return plans[0] def create_customer(self, code, first_name, last_name, email, plan_code, \ - company=None, is_vat_exempt=None, vat_number=None, \ + coupon_code=None, company=None, is_vat_exempt=None, vat_number=None, \ notes=None, first_contact_datetime=None, \ referer=None, campaign_term=None, \ campaign_name=None, campaign_source=None, \ @@ -61,7 +61,7 @@ def create_customer(self, code, first_name, last_name, email, plan_code, \ cancel_url=None, charges=None, items=None): data = self.build_customer_post_data(code, first_name, last_name, \ - email, plan_code, company, is_vat_exempt, vat_number, \ + email, plan_code, coupon_code, company, is_vat_exempt, vat_number, \ notes, first_contact_datetime, referer, campaign_term, \ campaign_name, campaign_source, campaign_medium, \ campaign_content, meta_data, initial_bill_date, method, \ @@ -90,7 +90,7 @@ def create_customer(self, code, first_name, last_name, email, plan_code, \ def build_customer_post_data(self, code=None, first_name=None,\ last_name=None, email=None, plan_code=None, \ - company=None, is_vat_exempt=None, vat_number=None, \ + coupon_code=None, company=None, is_vat_exempt=None, vat_number=None, \ notes=None, first_contact_datetime=None, \ referer=None, campaign_term=None, \ campaign_name=None, campaign_source=None, \ @@ -119,6 +119,9 @@ def build_customer_post_data(self, code=None, first_name=None,\ if plan_code: data['subscription[planCode]'] = plan_code + + if coupon_code: + data['subscription[couponCode]'] = coupon_code if company: data['company'] = company @@ -484,12 +487,12 @@ def update(self, first_name=None, last_name=None, email=None, \ cc_card_code=None, cc_first_name=None, \ cc_last_name=None, cc_company=None, cc_email=None,\ cc_country=None, cc_address=None, cc_city=None, \ - cc_state=None, cc_zip=None, plan_code=None, bill_date=None, + cc_state=None, cc_zip=None, plan_code=None, coupon_code=None, bill_date=None, return_url=None, cancel_url=None,): data = self.product.build_customer_post_data( first_name=first_name, last_name=last_name, email=email, plan_code=plan_code, - company=company, is_vat_exempt=is_vat_exempt, + coupon_code=coupon_code, company=company, is_vat_exempt=is_vat_exempt, vat_number=vat_number, notes=notes, referer=referer, campaign_term=campaign_term, campaign_name=campaign_name,