def process_file(database, fname): if PYT3: with open(fname, 'r', encoding='iso-8859-1') as f: data = f.read() else: with open(fname, 'r') as f: data = f.read() interested_id = ObjectId() with CommitContext(database) as ctx: interested = 'import-payment-%s' % interested_id op = CreateToi('members.PGPaymentFile', None, attrData=dict(fileName=[os.path.basename(fname)], data=[data])) ctx.runCommit([op], interested=interested) (toid, ), error = wait_for_commit(database, interested=interested) if error: raise error with CommitContext(database) as ctx: interested = 'process-payment-file-%s' % interested_id op = CallToi(toid, 'process', []) ctx.runCommit([op], interested=interested) _, error = wait_for_commit(database, interested=interested) if error: raise error with ReadonlyContext(database): for paymentFile in blm.members.PGPaymentFile._query(id=toid).run(): for payment in paymentFile.payments: paymentId = payment.id[0] interested = 'match-payment-%s-%s' % (interested_id, paymentId) with CommitContext(database) as ctx: op = CallToi(paymentId, 'match', []) ctx.runCommit([op], interested) _, error = wait_for_commit(database, interested=interested) if error: raise error with ReadonlyContext(database): for payment in blm.members.PGPayment._query(paymentFile=toid).run(): paymentId = payment.id[0] interested = 'send-payment-confirmation-%s-%s' % (paymentId, ObjectId()) with CommitContext(database) as ctx: op = CallToi(paymentId, 'sendConfirmationEmail', []) ctx.runCommit([op], interested) _, error = wait_for_commit(database, interested=interested) if error: raise error archive_file(fname)
def webhook(): data = request.get_json() log.info('WEBHOOK: %r', data) if not 'user_id' in data: return '' # Nothing we know what to do with with ReadonlyContext(g.database) as ctx: provider = blm.accounting.StripeProvider._query(stripe_id = data['user_id']).run() if not provider: return '' org_ug = provider[0].org[0].ug[0] interested = 'stripe-%s-%s-%s' % (data['type'], data['id'], ObjectId()) with CommitContext(g.database, org_ug) as ctx: # Use organisations permissions op = [] if data['type'] == 'invoice.created': op.append(CallBlm('members', 'handleStripeInvoice', [[data], provider])) elif data['type'] == 'charge.succeeded': op.append(CallBlm('members', 'handleStripeCharge', [[data], provider])) elif data['type'] == 'invoice.payment_succeeded': pass ctx.runCommit(op, interested) _, error = wait_for_commit(g.database, interested) if error: raise error return ''
def image2(toid, attribute, index, width, height): with ReadonlyContext(g.database): try: toi, = blm.TO._query(id=toid, _attrList=[attribute]).run() except ValueError: raise werkzeug.exceptions.NotFound() try: attr = getattr(toi, attribute)[index] except AttributeError: raise werkzeug.exceptions.NotFound() if not isinstance(attr, BlobVal): raise werkzeug.exceptions.Forbidden() content_type = attr.content_type if width and height: data, content_type = accounting.thumbnail.thumbnail( attr.getvalue(), content_type, width, height) else: data = attr.getvalue() response = Response(response=data, content_type=content_type) response.headers['Cache-Control'] = 'no-cache' return response
def main(org, selectedAccounting): language = accounting.lang.get_language(request) with ReadonlyContext(g.database, g.user): return render_template('izettle_overview.html', app='izettle/overview', css_files=['izettle.css'], language=language)
def lookup_current_user(): result = None g.user = None if getattr(current_app, 'connection', None) is None: current_app.connection = accounting.db.get_connection() current_app.dbname = config.config.get('accounting', 'mongodb_dbname') g.database = current_app.connection[current_app.dbname] auth = request.headers.get('Authorization') userid = session.get('userid') with ReadonlyContext(g.database): if auth: _, key = auth.split() try: g.user = blm.accounting.APIUser._query( key=key, _attrList={'lastAccess'}).run()[0] except IndexError: raise werkzeug.exceptions.Forbidden() elif userid: try: g.user = blm.accounting.User._query( id=session['userid'], _attrList={'lastAccess'} ).run()[0] except IndexError: del session['userid'] else: invitation = session.pop('invitation', None) if invitation: result = acceptInvitation(g.user, invitation) if g.user: if g.user.lastAccess[0] + USER_ACCESS_RESOLUTION < time.time(): op = ChangeToi(g.user, {'lastAccess': [time.time()]}) with CommitContext.clone() as ctx: ctx.runCommit([op]) # not interested return result
def main(org): language = accounting.lang.get_language(request) with ReadonlyContext(g.database, g.user): return render_template('accountspayable.html', app='accountspayable/accountspayable', css_files=['accountspayable.css','spinner.css'], language=language)
def do_create(self, blmname, tocname, params): tocname = '%s.%s' % (blmname, tocname) toc = blm.getTocByFullname(tocname) interested = 'direct-create-%s' % ObjectId() with CommitContext(self.database, self.user) as ctx: createops = params[0] if isinstance(createops, dict): createops = [createops] ops = [] for attrdata in createops: toid = list(filter(None, attrdata.pop('id', []) + [ObjectId()]))[0] self._toidata_from_json(toc, attrdata) op = CreateToi(tocname, toid, attrdata) ops.append(op) ctx.runCommit(ops, interested=interested) with ReadonlyContext(self.database, self.user) as ctx: result, error = wait_for_commit(self.database, interested) if error: return {'success': False} for i, toid in enumerate(result): query = toc._query(id=toid) query.attrList = toc._attributes.keys() toi, = query.run() result[i] = self._get_toidata(toi, query.attrList) return {'success': True, 'tois': result}
def render(name): language = accounting.lang.get_language(request) with ReadonlyContext(g.database, g.user): return render_template('expense/%s.html' % name, app='expense/%s' % name, css_files=[], language=language)
def account(org, purchase): language = accounting.lang.get_language(request) with ReadonlyContext(g.database, g.user): return render_template('purchase_verification.html', app='purchase/verification', css_files=['purchase_verification.css'], language=language)
def create_account(database, browser, accountingid, number='1000', name='An account'): from pytransact.context import ReadonlyContext import blm.accounting with ReadonlyContext(database): existing = blm.accounting.Account._query().run() print existing element = browser.find(value='[data-recordid="%s"]' % accountingid) element.click() grid = browser.componentQuery('accountingedit grid[name=accounts]') cells = grid.find_elements_by_css_selector('div.x-grid-cell-inner') numbercell = cells[0] browser.ensureVisible(numbercell) numbercell.click() numberfield = WebDriverWait(browser.driver, 10).until( EC.visibility_of_element_located( (By.CSS_SELECTOR, '.account-number input'))) numberfield.send_keys(number, Keys.RETURN) type = WebDriverWait(browser.driver, 10).until( EC.visibility_of_element_located( (By.CSS_SELECTOR, '.accounttype-combo input'))) time.sleep(1) type.send_keys(Keys.ARROW_DOWN) type.send_keys(Keys.ARROW_DOWN) type.send_keys(Keys.RETURN) time.sleep(1) type.send_keys(Keys.RETURN) namefield = browser.locate('.accounts .name input') namefield.send_keys(name, Keys.RETURN) vat = browser.locate('.vatcode-combo input') vat.send_keys(Keys.ARROW_DOWN, Keys.ARROW_DOWN, Keys.RETURN) time.sleep(1) vat.send_keys(Keys.RETURN) budget = browser.locate('.currency-editor input') budget.send_keys('1000.00', Keys.RETURN) #balance = browser.locate('.currency-editor input') #assert budget is not balance #balance.send_keys('2000.00', Keys.RETURN) button = browser.componentQuery('accountingedit button[action=save]') button.click() def checkaccount(): with ReadonlyContext(database): accounts = blm.accounting.Account._query().run() assert len(accounts) == len(existing) + 1 wait_for(checkaccount)
def do_update(self, blmname, tocname, params): tocname = '%s.%s' % (blmname, tocname) interested = 'direct-update-%s' % ObjectId() with CommitContext(self.database, self.user) as ctx: updateops = params[0] if isinstance(updateops, dict): updateops = [updateops] opdata = {} toc = blm.getTocByFullname(tocname) attrList = set() for attrdata in updateops: toid, = map(ObjectId, attrdata.pop('id')) self._toidata_from_json(toc, attrdata) opdata[toid] = attrdata attrList.update(attrdata) q = toc._query(id=[toid for toid in opdata]) q.attrList = attrList ops = [] for toi in q.run(): op = ChangeToi(toi, opdata[toi.id[0]]) ops.append(op) ctx.runCommit(ops, interested=interested) with ReadonlyContext(self.database, self.user) as ctx: result, error = wait_for_commit(self.database, interested) if error: return {'success': False, 'message': error} for i, (toid, sentdata) in enumerate(zip(result, updateops)): query = toc._query(id=toid) query.attrList = sentdata.keys() toi, = query.run() result[i] = self._get_toidata(toi, query.attrList) return {'success': True, 'tois': result}
def invoice_status(toid): with ReadonlyContext(g.database, g.user): try: toi, = blm.members.BasePurchase._query(id=toid).run() except ValueError: raise NotFound return jsonify_toi(toi, ['ocr', 'invoiceUrl', 'paymentState'])
def getTicket(ticket, random): pdf = StringIO.StringIO() with ReadonlyContext(g.database): tickets = blm.members.Ticket._query(id=ticket, random=random).run() members.ticket.generate(pdf, tickets) return Response(response=pdf.getvalue(), mimetype='application/pdf')
def pay(database, providerId, purchaseId, returnto): with ReadonlyContext(database) as ctx: provider, = blm.accounting.PaysonProvider._query(id=providerId).run() org = provider.org[0] purchase, = blm.members.BasePurchase._query(id=purchaseId).run() api = payson.PaysonApi(provider.apiUserId[0], provider.apiPassword[0]) receiver = payson.Receiver(email=provider.receiverEmail[0], amount=purchase.remainingAmount[0]) memo = (u'Betalning till %s' % org.name[0])[:128] ipnBase = (config.config.get('payson', 'ipn_notification_baseurl') or config.config.get('accounting', 'baseurl')) ipnNotificationUrl = urljoin(ipnBase, 'paysonipn') payment_response = api.pay( returnUrl=returnto, cancelUrl=returnto, ipnNotificationUrl=ipnNotificationUrl, memo=memo, senderEmail=purchase.buyerEmail[0], senderFirstName=purchase.buyerName[0].split()[0], senderLastName=purchase.buyerName[0].split()[-1], trackingId=str(purchaseId), custom=str(providerId), receiverList=[receiver]) if payment_response.success: return flask.redirect(payment_response.forward_pay_url) return ''
def ticket(ticket, random, product, sig1, sig2): if random is None: random = ticket & 0xffffffff ticket = ObjectId('%024x' % (ticket >> 32)) accounting.templating.formatters.apply(current_app.jinja_env, 'datetime') autovoid = bool(json.loads(request.cookies.get('autovoid', 'false')) or request.values.get('autovoid')) with ReadonlyContext(g.database) as ctx: ticket = blm.members.Ticket._query(id=ticket, random=random).run() if not ticket: resp = make_response( render_template('ticket.html', ticket=None, canvoid=bool(g.user), autovoid=autovoid)) resp.set_cookie('autovoid', json.dumps(autovoid), path='/ticket', expires=time.time() + 24 * 3600) return resp ticket, = ticket if 'print' in request.values: return redirect(url_for('getTicket', ticket=ticket.id[0], random=base64long.encode(ticket.random[0]))) canvoid = False voided = False if g.user: canvoid = ticket.canWrite(g.user, 'void') if canvoid: if 'unvoid' in request.values: interested = 'ticket-unvoid-%s' % ObjectId() with CommitContext(g.database, g.user) as ctx: op = CallToi(ticket.id[0], 'unvoid', []) ctx.runCommit([op], interested) result, error = wait_for_commit(g.database, interested) if error: raise error elif autovoid or 'void' in request.values: interested = 'ticket-void-%s' % ObjectId() with CommitContext(g.database, g.user) as ctx: op = CallToi(ticket.id[0], 'void', []) ctx.runCommit([op], interested) result, error = wait_for_commit(g.database, interested) voided = result[0][0] if error: raise error resp = make_response( render_template( 'ticket.html', ticket=ticket, canvoid=canvoid, autovoid=autovoid, voided=voided, ticket_url=url_for('ticket_simple', _external=True) ) ) resp.set_cookie('autovoid', json.dumps(autovoid), path='/ticket', expires=time.time() + 24 * 3600) return resp
def cancel(database, providerId, purchaseId, invoiceRef): client, context, seqr_protocol = get_client_and_context(providerId, purchaseId, database=database) resp = call_method(client.service.cancelInvoice, context, invoiceRef) with ReadonlyContext(database) as ctx: purchase, = blm.members.Purchase._query(id=purchaseId).run() return redirect(purchase.invoiceUrl[0])
def product_status(toid): with ReadonlyContext(g.database): try: toi, = blm.members.Product._query(id=toid).run() except ValueError: raise NotFound return jsonify_toi(toi, ['name', 'description', 'price', 'vatAccount'], ['accountingRules'])
def do_read(self, blmname, tocname, params): tocname = '%s.%s' % (blmname, tocname) result = [] assert len(params) == 1 params, = params success = True with ReadonlyContext(self.database, self.user) as ctx: toc = blm.getTocByFullname(tocname) query_params = {} if 'id' in params: query_params['id'] = params['id'] if query_params['id'] is None: success = False for filter in params.get('filter', []): try: attr, cond = filter2cond(filter) query_params[attr] = cond except IgnoreFilter: pass if 'query' in params: if isinstance(params['query'], dict): query_params.update(params['query']) # xxx # We need a real design for complex queries, this exists # to support transaction text searching, see # Bokf.lib.TransactionTextEditor for attr, string in params.get('like', {}).items(): query_params[attr] = qops.Ilike(string) # find first sorter, or None sort = reduce(lambda x, y: x, params.get('sort', []) + [None]) query = toc._query(**query_params) if sort and sort['property'] != 'id': query.attrList = params['attributes'] + [sort['property']] else: query.attrList = params['attributes'] tois = query.run() if sort: if sort['property'] == 'id': key = lambda toi: toi[sort['property']] else: key = lambda toi: toi[sort['property']].value tois.sort(key=key, reverse=sort['direction'] == 'DESC') for toi in tois: result.append( self._get_toidata(toi, params['attributes'], params.get('polymorph', False))) return {'success': success, 'tois': result}
def cleanup_toirefs(database): log.info('Cleaning up toirefs') from pytransact.context import ReadonlyContext with ReadonlyContext(database) as ctx: known_toids = set(toi.id[0] for toi in blm.TO._query().run()) for _blm in blm.__blms__.values(): for toc in _blm._tocs.values(): log.info('Checking %s', toc._fullname) query = toc._query() query.attrList = [] query.clear() for attr in toc._attributes.values(): if isinstance(attr, (ToiRef, ToiRefMap)): query.attrList.append(attr.name) query.pushDict({attr.name: q.NotEmpty()}) if query: for toi in query.run(): for attrName in query.attrList: save = False attr = getattr(toi, attrName) if isinstance(attr, ToiRef): value = attr[:] for ref in value[:]: if ref.id[ 0] not in known_toids or ref.__class__ == blm.TO: value.remove(ref) save = True if len(set(value)) != len(value): value = list( pytransact.iterate.uniq(value)) log.info('%s.%s has duplicate values.', toi, attrName) save = True if save: log.info('Cleaning up %s.%s: %s', toi, attrName, value) pytransact.mongo.update( database.tois, {'_id': toi.id[0]}, {'$set': { attrName: value }}) elif isinstance(attr, ToiRefMap): items = attr.items() for k, ref in items: if ref.id[ 0] not in known_toids or ref.__class__ == blm.TO: items.remove((k, ref)) save = True if save: log.info('Cleaning up %s.%s: %s', toi, attrName, value) pytransact.mongo.update( database.tois, {'_id': toi.id[0]}, {'$set': { attrName: dict(items) }})
def subscription(self): if self._subscription is None: with ReadonlyContext(self.db) as ctx: openend, = blm.accounting.Org._query( orgnum=self.OE_ORGNUM).run() self._subscription = str( blm.members.Product._query( org=openend, notes='subscription').run()[0].id[0]) return self._subscription
def invoice_list(): with ReadonlyContext(g.database, g.user): ids = flask.request.values.getlist('id') if ids: query = {'id': ids} else: query = {} tois = blm.members.BasePurchase._query(**query).run() return [jsonify_toi(toi, ['ocr', 'invoiceUrl', 'paymentState']) for toi in tois]
def process(database): with ReadonlyContext(database): for order in blm.accounting.PGOrder._query(sent=[False]).run(): with CommitContext.clone() as ctx: op = CallToi(order.id[0], 'send', []) interested = 'sendpg-%s' % ObjectId() ctx.runCommit([op], interested) result, error = wait_for_commit(database, interested) if error: raise error
def products(self): if self._products is None: with ReadonlyContext(self.db) as ctx: openend, = blm.accounting.Org._query( orgnum=self.OE_ORGNUM).run() self._products = [] for toi in blm.members.Product._query( org=[openend], notes=q.RegEx('^plusgiro ')).run(): limit = decimal.Decimal(toi.notes[0][len('plusgiro '):]) self._products.append((limit, str(toi.id[0]))) self._products.sort() return self._products
def acceptInvitation(user, code): with ReadonlyContext(g.database): q = blm.accounting.Invitation._query(inviteCode=code) for invitation in q.run(): user, = blm.accounting.User._query(id=user.id).run() op = CallToi(invitation.id[0], 'accept', [[user]]) interested = ObjectId() with CommitContext.clone() as ctx: ctx.runCommit([op], interested=interested) result, error = wait_for_commit(g.database, interested) if error: return redirect(url_for('invitation_expired'))
def createOrders(database): with ReadonlyContext(database): for org in blm.accounting.identifyOrgsWithDueTransfers(): supInvList = blm.accounting.identifyDueTransfers(org=org) with CommitContext.clone() as ctx: op = CallBlm('accounting', 'createSignedBgcOrder', [[org], supInvList]) interested = 'createSignedBgcOrder_org-%s_%s' % (org.id[0], ObjectId()) ctx.runCommit([op], interested) result, error = wait_for_commit(database, interested) if error: raise error
def webshop(orgid): translation_files = [] language = accounting.lang.get_language(request) fname = '/webshop/%s.js' % language client_dir = config.config.get('accounting', 'client_dir') if os.path.exists(os.path.join(client_dir, *(fname.split('/')))): translation_files.append(fname) with ReadonlyContext(g.database): org, = blm.accounting.Org._query(id=orgid).run() return make_response( render_template('webshop.html', org=org, translation_files=translation_files))
def invoice(org): language = accounting.lang.get_language(request) with ReadonlyContext(g.database, g.user): org, = blm.accounting.Org._query(id=org).run() return render_template('invoicing/invoice.html', app='invoicing/invoice', css_files=[ 'webshop2.css', 'product-list.css', 'shopping-cart.css', 'order.css', ], language=language, org=org)
def sendOrders(database, out): with ReadonlyContext(database): for order in blm.accounting.BgcOrder._query( order_signed=NotEmpty(), sent=Empty()).run(): with CommitContext.clone() as ctx: op = CallBlm('accounting', 'sendBgcOrder', [[order]]) interested = 'sendBgcOrder_order-%s_%s' % (order.id[0], ObjectId()) ctx.runCommit([op], interested) result, error = wait_for_commit(database, interested) if error: raise error for r in result: out.write('Sent {}\n'.format(r))
def do_call(self, blmname, methodname, params): interested = 'direct-call-%s' % ObjectId() with CommitContext(self.database, self.user) as ctx: if params is None: params = [] for i, param in enumerate(params): if not isinstance(param, list): params[i] = [param] op = CallBlm(blmname, methodname, params) ctx.runCommit([op], interested=interested) with ReadonlyContext(self.database, self.user) as ctx: result, error = wait_for_commit(self.database, interested) assert not error, error return result[0]
def main(): database = db.connect() database.local.foo.find().count() # force connection to initialize with ReadonlyContext(database): users = len(blm.accounting.User._query().run()) activeusers = len( blm.accounting.User._query(lastAccess=Greater(time.time() - 24 * 60 * 60)).run()) orgs = len(blm.accounting.Org._query().run()) suborgs = len( blm.accounting.Org._query(subscriptionLevel='subscriber').run()) log.info( 'users: %(users)s active: %(activeusers)s orgs: %(orgs)s subscribers: %(suborgs)s', locals())