Пример #1
0
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)
Пример #2
0
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 ''
Пример #3
0
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
Пример #4
0
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)
Пример #5
0
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
Пример #6
0
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)
Пример #7
0
 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}
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
    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}
Пример #12
0
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'])
Пример #13
0
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')
Пример #14
0
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 ''
Пример #15
0
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
Пример #16
0
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])
Пример #17
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'])
Пример #18
0
    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}
Пример #19
0
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)
                                        }})
Пример #20
0
 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
Пример #21
0
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]
Пример #22
0
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
Пример #23
0
 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
Пример #24
0
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'))
Пример #25
0
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
Пример #26
0
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))
Пример #27
0
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)
Пример #28
0
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))
Пример #29
0
    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]
Пример #30
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())