def parse_transaction(self, transaction, account): trans = [] if transaction['transactionStatus'] in [u'Créé', u'Annulé', u'Suspendu', u'Mis à jour', u'Actif', u'Payé', u'En attente', u'Rejeté', u'Expiré', \ u'Created']: return [] if transaction['transactionDescription'].startswith(u'Offre de remboursement') or transaction['transactionDescription'].startswith(u'Commande à'): return [] t = FrenchTransaction(transaction['transactionId']) if not transaction['transactionAmount']['currencyCode'] == account.currency: cc = self.browser.convert_amount(account, transaction, 'https://www.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id=' + transaction['transactionId']) if not cc: return [] t.original_amount = Decimal('%.2f' % transaction['transactionAmount']['currencyDoubleValue']) t.original_currency = u'' + transaction['transactionAmount']['currencyCode'] t.amount = abs(cc) if not transaction['debit'] else -abs(cc) else: t.amount = Decimal('%.2f' % transaction['net']['currencyDoubleValue']) date = parse_french_date(transaction['transactionTime']) raw = transaction['transactionDescription'] if raw.startswith(u'Paiement \xe0') or raw.startswith('Achat de'): payback_id, payback_raw, payback_amount, payback_currency = self.browser.check_for_payback(transaction, 'https://www.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id=' + transaction['transactionId']) if payback_id and payback_raw and payback_amount and payback_currency: t_payback = FrenchTransaction(payback_id) t_payback.amount = payback_amount t_payback.original_currency = payback_currency t_payback.type = FrenchTransaction.TYPE_TRANSFER t_payback.parse(date=date, raw=u'Prélèvement pour %s' % raw) trans.append(t_payback) t.commission = Decimal('%.2f' % transaction['fee']['currencyDoubleValue']) t.parse(date=date, raw=raw) trans.append(t) return trans
def parse_transaction(self, transaction, account): trans = [] if 'transactionStatus' in transaction and transaction[ 'transactionStatus'] in [ u'Créé', u'Annulé', u'Suspendu', u'Mis à jour', u'Actif', u'Payé', u'En attente', u'Rejeté', u'Expiré', u'Created', u'Brouillon', u'Paid', u'Pending', u'Canceled' ]: return [] for pattern in [u'Commande à', u'Offre de remboursement', u'Bill to']: if 'description' not in transaction[ 'transactionDescription'] or transaction[ 'transactionDescription']['description'].startswith( pattern): return [] t = FrenchTransaction(transaction['transactionId']) # Those are not really transactions. if not 'currency' in transaction['grossAmount'] \ or transaction['transactionDescription']['description'].startswith("Conversion de devise"): return [] original_currency = unicode(transaction['grossAmount']['currency']) if not original_currency == account.currency: if original_currency in self.browser.account_currencies: return [] cc = [tr['grossAmount']['amountUnformatted'] for tr in transaction['secondaryTransactions'] \ if account.currency == tr['grossAmount']['currency'] \ and (tr['grossAmount']['amountUnformatted'] < 0) == (transaction['grossAmount']['amountUnformatted'] < 0) \ and tr['transactionDescription']['description'].startswith('Conversion de devise')] if not cc: return [] assert len(cc) == 1 t.original_amount = Decimal( str(transaction['grossAmount']['amountUnformatted'])) t.original_currency = original_currency t.amount = Decimal(str(cc[0])) else: t.amount = Decimal( str(transaction['netAmount']['amountUnformatted'])) date = parse_french_date(transaction['transactionTime']) raw = "%s %s" % (transaction['transactionDescription']['description'], transaction['transactionDescription']['name']) if raw == "Transfert de Compte bancaire": t.type = FrenchTransaction.TYPE_TRANSFER t.commission = Decimal( str(transaction['feeAmount']['amountUnformatted'])) t.parse(date=date, raw=raw) trans.append(t) return trans
def parse_transaction(self, transaction, account): trans = [] if transaction['transactionStatus'] in [u'Créé', u'Annulé', u'Suspendu', u'Mis à jour', u'Actif', u'Payé', u'En attente', u'Rejeté', u'Expiré', \ u'Created', u'Canceled']: return [] if transaction['transactionDescription'].startswith( u'Offre de remboursement' ) or transaction['transactionDescription'].startswith(u'Commande à'): return [] t = FrenchTransaction(transaction['transactionId']) original_currency = unicode( transaction['transactionAmount']['currencyCode']) if not original_currency == account.currency: if original_currency in self.browser.account_currencies: return [] cc = self.browser.convert_amount( account, transaction, 'https://www.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id=' + transaction['transactionId']) if not cc: return [] t.original_amount = Decimal( '%.2f' % transaction['transactionAmount']['currencyDoubleValue']) t.original_currency = original_currency t.amount = abs(cc) if not transaction['debit'] else -abs(cc) else: t.amount = Decimal('%.2f' % transaction['net']['currencyDoubleValue']) date = parse_french_date(transaction['transactionTime']) raw = transaction['transactionDescription'] if raw.startswith(u'Paiement \xe0') or raw.startswith('Achat de'): payback_id, payback_raw, payback_amount, payback_currency = self.browser.check_for_payback( transaction, 'https://www.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id=' + transaction['transactionId']) if payback_id and payback_raw and payback_amount and payback_currency: t_payback = FrenchTransaction(payback_id) t_payback.amount = payback_amount t_payback.original_currency = payback_currency t_payback.type = FrenchTransaction.TYPE_TRANSFER t_payback.parse(date=date, raw=u'Prélèvement pour %s' % raw) trans.append(t_payback) t.commission = Decimal('%.2f' % transaction['fee']['currencyDoubleValue']) t.parse(date=date, raw=raw) trans.append(t) return trans
def parse_transaction(self, transaction, account): if transaction['transactionStatus'] in [u'Créé', u'Annulé', u'Suspendu', u'Mis à jour', u'Actif']: return t = FrenchTransaction(transaction['transactionId']) if not transaction['transactionAmount']['currencyCode'] == account.currency: cc = self.browser.convert_amount(account, transaction, 'https://www.paypal.com/cgi-bin/webscr?cmd=_history-details-from-hub&id=' + transaction['transactionId']) if not cc: return t.original_amount = Decimal(transaction['transactionAmount']['currencyDoubleValue']) t.original_currency = u'' + transaction['transactionAmount']['currencyCode'] t.set_amount(cc) else: t.amount = Decimal(transaction['transactionAmount']['currencyDoubleValue']) date = parse_french_date(transaction['transactionTime']) raw = transaction['transactionDescription'] t.commission = Decimal(transaction['fee']['currencyDoubleValue']) t.parse(date=date, raw=raw) return t
def parse(self): for tr in self.document.xpath('//tbody/tr'): tlink = tr.xpath('./td[@class="desc"]/a[@class="rowClick"]')[0].attrib['href'].strip() t = FrenchTransaction(tlink[tlink.find('&id=')+4:]) date = parse_french_date(tr.xpath('./td[@class="date"]')[0].text.strip()) raw = tr.xpath('./td[@class="desc"]/a[@class="rowClick"]')[0].tail.strip() # Filter lines that do not actually modify the balance if raw.startswith('Autorisation ') or raw.endswith(' en attente par PayPal'): continue t.parse(date=date, raw=raw) amount = tr.xpath('./td[@class="price-value net"]')[0].text.strip() t.set_amount(amount) commission = tr.xpath('./td[@class="price-value fee"]')[0].text.strip() t.commission = Decimal(t.clean_amount(commission)) t.label = t.raw if t.commission: t.label += " (%s)" % tr.xpath('./td[@class="price-value gross"]')[0].text.strip() t._currency = Account.get_currency(amount) yield t
def parse_transaction(self, transaction, account): trans = [] # Add secondary transactions on label condition. for t in transaction['secondaryTransactions']: if t['transactionDescription'][ 'description'] == u'Virement à partir de': trans.extend(self.parse_transaction(t, account)) if 'transactionStatus' in transaction and transaction[ 'transactionStatus'] in [ u'Créé', u'Annulé', u'Suspendu', u'Mis à jour', u'Actif', u'Payé', u'En attente', u'Rejeté', u'Expiré', u'Created', u'Brouillon', u'Paid', u'Pending', u'Canceled', u'Suspended' ]: return [] for pattern in [u'Commande à', u'Offre de remboursement', u'Bill to']: if 'description' not in transaction[ 'transactionDescription'] or transaction[ 'transactionDescription']['description'].startswith( pattern): return [] t = FrenchTransaction(transaction['transactionId']) # Those are not really transactions. if 'grossAmount' not in transaction or not 'currency' in transaction['grossAmount'] \ or transaction['transactionDescription']['description'].startswith("Conversion de devise"): return [] original_currency = unicode(transaction['grossAmount']['currency']) if not original_currency == account.currency: if original_currency in self.browser.account_currencies: return [] cc = [tr['grossAmount']['amountUnformatted'] for tr in transaction['secondaryTransactions'] \ if account.currency == tr['grossAmount']['currency'] \ and (tr['grossAmount']['amountUnformatted'] < 0) == (transaction['grossAmount']['amountUnformatted'] < 0) \ and tr['transactionDescription']['description'].startswith('Conversion de devise')] if not cc: return [] assert len(cc) == 1 t.original_amount = Decimal( str(transaction['netAmount']['amountUnformatted'])) t.original_currency = original_currency t.amount = Decimal(str(cc[0])) else: t.amount = Decimal( str(transaction['netAmount']['amountUnformatted'])) date = parse_french_date(transaction['transactionTime']) raw = "%s %s" % (transaction['transactionDescription']['description'], transaction['transactionDescription']['name']) if raw == "Transfert de Compte bancaire": t.type = FrenchTransaction.TYPE_TRANSFER if raw == u'Annulation des frais de PayPal': return [] # Dougs told us that commission should always be netAmount minus grossAmount grossAmount = Decimal( str(transaction['grossAmount']['amountUnformatted'])) t.commission = Decimal( str(transaction['feeAmount']['amountUnformatted'])) if t.commission: if original_currency == account.currency: assert abs(t.amount - grossAmount) == abs(t.commission) t.commission = t.amount - grossAmount else: t.commission = (t.commission * t.amount / t.original_amount).quantize( Decimal('.01'), rounding=ROUND_DOWN) t.parse(date=date, raw=raw) trans.append(t) return trans
def parse_transaction(self, transaction, account): trans = [] # Add secondary transactions on label condition. for t in transaction['secondaryTransactions']: if t['transactionDescription']['description'] == u'Virement à partir de': trans.extend(self.parse_transaction(t, account)) if 'transactionStatus' in transaction and transaction['transactionStatus'] in [u'Créé', u'Annulé', u'Suspendu', u'Mis à jour', u'Actif', u'Payé', u'En attente', u'Rejeté', u'Expiré', u'Created', u'Brouillon', u'Paid', u'Pending', u'Canceled', u'Suspended']: return [] for pattern in [u'Commande à', u'Offre de remboursement', u'Bill to']: if 'description' not in transaction['transactionDescription'] or transaction['transactionDescription']['description'].startswith(pattern): return [] t = FrenchTransaction(transaction['transactionId']) # Those are not really transactions. if 'grossAmount' not in transaction or not 'currency' in transaction['grossAmount'] \ or transaction['transactionDescription']['description'].startswith("Conversion de devise"): return [] original_currency = unicode(transaction['grossAmount']['currency']) if not original_currency == account.currency: if original_currency in self.browser.account_currencies: return [] cc = [tr['grossAmount']['amountUnformatted'] for tr in transaction['secondaryTransactions'] \ if account.currency == tr['grossAmount']['currency'] \ and (tr['grossAmount']['amountUnformatted'] < 0) == (transaction['grossAmount']['amountUnformatted'] < 0) \ and tr['transactionDescription']['description'].startswith('Conversion de devise')] if not cc: return [] assert len(cc) == 1 t.original_amount = Decimal(str(transaction['netAmount']['amountUnformatted'])) t.original_currency = original_currency t.amount = Decimal(str(cc[0])) else: t.amount = Decimal(str(transaction['netAmount']['amountUnformatted'])) date = parse_french_date(transaction['transactionTime']) raw = "%s %s" % (transaction['transactionDescription']['description'], transaction['transactionDescription']['name']) if raw == "Transfert de Compte bancaire": t.type = FrenchTransaction.TYPE_TRANSFER if raw == u'Annulation des frais de PayPal': return [] # Dougs told us that commission should always be netAmount minus grossAmount grossAmount = Decimal(str(transaction['grossAmount']['amountUnformatted'])) t.commission = Decimal(str(transaction['feeAmount']['amountUnformatted'])) if t.commission: if original_currency == account.currency: assert abs(t.amount - grossAmount) == abs(t.commission) t.commission = t.amount - grossAmount else: t.commission = (t.commission * t.amount / t.original_amount).quantize(Decimal('.01'), rounding=ROUND_DOWN) t.parse(date=date, raw=raw) trans.append(t) return trans