Example #1
0
def make_wsgi_app(dbcontext, auth_decorator, jinja_env, dbapi, actionlogged):
    w = Bottle()

    # bind apis
    bind_dbapi_rest('/app/api/client', dbapi, Client, w)
    bind_dbapi_rest('/app/api/user', dbapi, User, w)

    @w.get('/app/cliente/<id>')
    @dbcontext
    @auth_decorator
    def modificar_cliente_form(id, message=None):
        client = dbapi.get(id, Client)
        if client is None:
            message = 'Cliente {} no encontrado'.format(id)
        temp = jinja_env.get_template('crear_cliente.html')
        return temp.render(client=client,
                           message=message,
                           action='/app/modificar_cliente',
                           button_text='Modificar')

    @w.post('/app/modificar_cliente')
    @dbcontext
    @auth_decorator
    def modificar_cliente():
        clientid = request.forms.codigo
        client = Client(codigo=clientid)
        dbapi.update(client, request.forms)
        redirect('/app/cliente/{}'.format(clientid))

    @w.get('/app/cliente')
    @dbcontext
    @auth_decorator
    def search_cliente_result():
        prefix = request.query.prefijo
        clientes = list(dbapi.search(Client, **{'apellidos-prefix': prefix}))
        temp = jinja_env.get_template('search_cliente_result.html')
        return temp.render(clientes=clientes)

    @w.post('/app/crear_cliente')
    @dbcontext
    @auth_decorator
    def crear_cliente():
        cliente = Client.deserialize(request.forms)
        cliente.cliente_desde = datetime.date.today()
        try:
            dbapi.create(cliente)
            dbapi.db_session.commit()
        except ItemAlreadyExists:
            return crear_cliente_form('Cliente con codigo {} ya existe'.format(
                cliente.codigo))
        return crear_cliente_form('Cliente {} {} creado'.format(
            cliente.apellidos, cliente.nombres))

    @w.get('/app/secuencia')
    @dbcontext
    @auth_decorator
    def get_secuencia():
        users = dbapi.search(User)
        temp = jinja_env.get_template('secuencia.html')
        store_dict = {s.almacen_id: s.nombre for s in dbapi.search(Store)}
        store_dict[-1] = 'Ninguno'
        return temp.render(users=users, stores=store_dict)

    @w.post('/app/secuencia')
    @dbcontext
    @auth_decorator
    @actionlogged
    def post_secuencia():
        username = request.forms.usuario
        seq = request.forms.secuencia
        user = User(username=username)
        dbapi.update(user, {'last_factura': seq})
        redirect('/app/secuencia')

    @w.get('/app/ver_cliente')
    @dbcontext
    @auth_decorator
    def ver_cliente():
        temp = jinja_env.get_template('ver_item.html')
        return temp.render(title='Ver Cliente',
                           baseurl='/app/cliente',
                           apiurl='/api/cliente')

    @w.get('/app/crear_cliente')
    @dbcontext
    @auth_decorator
    def crear_cliente_form(message=None):
        temp = jinja_env.get_template('crear_cliente.html')
        return temp.render(client=None,
                           message=message,
                           action='/app/crear_cliente',
                           button_text='Crear')

    bind_dbapi_rest('/app/api/client', dbapi, Client, w)
    return w
Example #2
0
def make_import_apis(prefix, auth_decorator, dbapi,
                     jinja_env):
    app = Bottle()
    dbcontext = DBContext(dbapi.session)

    bind_dbapi_rest(prefix + '/purchase', dbapi, Purchase, app)
    bind_dbapi_rest(prefix + '/purchase_item', dbapi, PurchaseItem, app)
    bind_dbapi_rest(prefix + '/universal_prod', dbapi, UniversalProd, app)
    bind_dbapi_rest(prefix + '/declaredgood', dbapi, DeclaredGood, app)
    bind_dbapi_rest(prefix + '/custom_item', dbapi, CustomItem, app)

    @app.get(prefix + '/universal_prod_with_declared')
    @dbcontext
    @auth_decorator(0)
    def get_universal_prod_with_declared():
        all_prod = dbapi.search(UniversalProd)
        all_declared = dbapi.search(DeclaredGood)

        return json_dumps({
            'prod': all_prod,
            'declared': all_declared
        })

    @app.get(prefix + '/purchase_filtered/<uid>')
    @dbcontext
    @auth_decorator
    def purchase_fitered(uid):
        purchase = get_purchase_full(dbapi, uid)
        map(normal_filter, purchase.items)
        total = sum(i.item.price_rmb * i.item.quantity for i in purchase.items)
        purchase.meta.total_rmb = total
        res = purchase.serialize()
        res['units'] = {x.uid: x for x in dbapi.search(Unit)}
        return json_dumps(res)

    @app.get(prefix + '/purchase_full/<uid>')
    @dbcontext
    @auth_decorator(0)
    def get_purchase_full_http(uid):
        res = get_purchase_full(dbapi, uid).serialize()
        res['units'] = {x.uid: x for x in dbapi.search(Unit)}
        return json_dumps(res)

    @app.post(prefix + '/purchase_full')
    @dbcontext
    @auth_decorator(0)
    def create_full_purchase():
        rows = json.loads(request.body.read())
        purchase = Purchase()
        purchase.timestamp = datetime.datetime.now()
        pid = dbapi.create(purchase)

        def make_item(r):
            return PurchaseItem(
                upi=r['prod']['upi'],
                quantity=Decimal(r['cant']),
                price_rmb=Decimal(r['price']),
                purchase_id=pid)

        items = map(make_item, rows)
        total = sum((r.price_rmb * r.quantity for r in items))
        dbapi.update(purchase, {'total_rmb': total})
        map(dbapi.create, items)
        return {'uid': pid}

    @app.put(prefix + '/purchase_full/<uid>')
    @dbcontext
    def update_purchase_full(uid):
        data = json.loads(request.body.read())
        print data
        # update meta
        updated = Purchase.deserialize(data['meta'])
        print updated.timestamp
        updated.last_edit_timestamp = datetime.datetime.now()
        dbapi.update_full(updated)

        to_create_item = map(PurchaseItem.deserialize, data.get('create_items', []))
        for pi in to_create_item:
            pi.purchase_id = uid
            dbapi.create(pi)
        to_delete_item = map(PurchaseItem.deserialize, data.get('delete_items', []))
        for pi in to_delete_item:
            dbapi.delete(pi)
        to_edit_item = map(PurchaseItem.deserialize, data.get('edit_items', []))
        for pi in to_edit_item:
            dbapi.update_full(pi)
        return {'status': 'success'}

    @app.get(prefix + '/custom_full/<uid>')
    @dbcontext
    @auth_decorator(0)
    def post_sale():
        content = Sale.deserialize(json.loads(request.body.read()))
        if list(dbapi.search(
                Sale, seller_codename=content.seller_codename,
                seller_inv_uid=content.seller_inv_uid)):
            return {'status': 'failed', 'reason': 'sale with the id already exists'}
        dbapi.create(content)
        return {'status': 'success'}

    @app.put(prefix + '/custom_full/<uid>')
    @dbcontext
    @auth_decorator(0)
    def get_sales():
        start, end = parse_start_end_date(request.query)
        result = list(get_sales_by_date_and_user(dbapi, start, end))
        return json_dumps(result)

    @app.post(prefix + '/split_custom_items')
    @dbcontext
    @auth_decorator(0)
    def delete_sale():
        content = Sale.deserialize(json.loads(request.body.read()))
        deleted = dbapi.db_session.query(NSale).filter_by(
            seller_codename=content.seller_codename, seller_inv_uid=content.seller_inv_uid
        ).update({'status': Status.DELETED})
        return {'deleted': deleted}

    @app.post(prefix + '/custom_full/purchase/<uid>')
    @dbcontext
    @auth_decorator(0)
    def post_inv_movement_set():
        raw_inv = request.body.read()
        inv_movement = InvMovementFull.deserialize(json.loads(raw_inv))
        meta = inv_movement.meta
        meta.origin = get_or_create_inventory_id(dbapi, meta.inventory_codename, meta.origin)
        meta.dest = get_or_create_inventory_id(dbapi, meta.inventory_codename, meta.dest)

        if list(dbapi.search(InvMovementMeta,
                             inventory_codename=meta.inventory_codename,
                             inventory_docid=meta.inventory_docid,
                             trans_type=meta.trans_type)):
            # already exists
            return {'created': 0, 'reason': 'already exists'}
        for igcant in inv_movement.items:
            prod_id = igcant.itemgroup.prod_id
            ig_real = dbapi.getone(ProdItemGroup, prod_id=prod_id)
            # itemgroup does not exist, create
            if not ig_real:
                dbapi.create(igcant.itemgroup)
            else:  # replace itemgroup as the itemgroup id might be distinct
                igcant.itemgroup = ig_real
        inv_movement = invmomanager.create(inv_movement)
        return {'created': inv_movement.meta.uid}

    @app.get(prefix + '/inv_movement/<day>')
    @dbcontext
    def last_inv_movements(day):
        today = parse_iso_date(day)
        tomorrow = today + datetime.timedelta(days=1)
        print today, tomorrow
        movements = list(dbapi.search(InvMovementMeta, **{'timestamp-gte': today, 'timestamp-lte': tomorrow}))
        return json_dumps({'result': movements})

    @app.get(prefix + '/sales_report')
    @dbcontext
    def get_sales_report():
        start, end = parse_start_end_date(request.query)
        sales_by_date = list(client_sale_report(dbapi, start, end))
        return json_dumps({'result': sales_by_date})

    # @app.post(prefix + '/raw_inv_movement')
    @dbcontext
    def post_raw_inv_movement():
        raw_data = json.loads(request.body.read())
        ig = ProdItemGroup.deserialize(raw_data[0])
        trans = map(InventoryMovement.deserialize, raw_data[1])
        codename = raw_data[2]

        if dbapi.getone(ProdItemGroup, prod_id=ig.prod_id) is None:
            if dbapi.get(ig.uid, ProdItemGroup) is not None:
                #  prod_id does not exist but uid is used so we cannot create
                #  using the same uid
                ig.uid = None
            dbapi.create(ig)

        for i in trans:
            i.itemgroup_id = ig.uid
            if dbapi.getone(Inventory, entity_codename=codename, external_id=i.from_inv_id) is None:
                # create new Inventory if none
                i.from_inv_id = get_or_create_inventory_id(dbapi, codename, i.from_inv_id)
                i.to_inv_id = get_or_create_inventory_id(dbapi, codename, i.to_inv_id)
                i.reference_id = codename + (i.reference_id or '')
            inventoryapi.save(i)

    return app
Example #3
0
def make_wsgi_app(dbcontext, auth_decorator, jinja_env, dbapi, actionlogged):
    w = Bottle()

    # bind apis
    bind_dbapi_rest('/app/api/client', dbapi, Client, w)
    bind_dbapi_rest('/app/api/user', dbapi, User, w)

    @w.get('/app/cliente/<id>')
    @dbcontext
    @auth_decorator(0)
    def modificar_cliente_form(id, message=None):
        client = dbapi.get(id, Client)
        if client is None:
            message = 'Cliente {} no encontrado'.format(id)
        temp = jinja_env.get_template('crear_cliente.html')
        return temp.render(client=client, message=message, action='/app/modificar_cliente',
                           button_text='Modificar')

    @w.post('/app/modificar_cliente')
    @dbcontext
    @auth_decorator(0)
    def modificar_cliente():
        clientid = request.forms.codigo
        client = Client(codigo=clientid)
        dbapi.update(client, request.forms)
        redirect('/app/cliente/{}'.format(clientid))

    @w.get('/app/cliente')
    @dbcontext
    @auth_decorator(0)
    def search_cliente_result():
        prefix = request.query.prefijo
        clientes = list(dbapi.search(Client, **{'apellidos-prefix': prefix}))
        temp = jinja_env.get_template('search_cliente_result.html')
        return temp.render(clientes=clientes)

    @w.post('/app/crear_cliente')
    @dbcontext
    @auth_decorator(0)
    def crear_cliente():
        cliente = Client.deserialize(request.forms)
        cliente.cliente_desde = datetime.date.today()
        try:
            dbapi.create(cliente)
            dbapi.db_session.commit()
        except ItemAlreadyExists:
            return crear_cliente_form('Cliente con codigo {} ya existe'.format(cliente.codigo))
        return crear_cliente_form('Cliente {} {} creado'.format(cliente.apellidos, cliente.nombres))

    @w.get('/app/secuencia')
    @dbcontext
    @auth_decorator(1)
    def get_secuencia():
        users = dbapi.search(User)
        temp = jinja_env.get_template('secuencia.html')
        store_dict = {s.almacen_id: s.nombre for s in dbapi.search(Store)}
        store_dict[-1] = 'Ninguno'
        return temp.render(users=users, stores=store_dict)

    @w.post('/app/secuencia')
    @dbcontext
    @auth_decorator(1)
    @actionlogged
    def post_secuencia():
        username = request.forms.usuario
        seq = request.forms.secuencia
        user = User(username=username)
        dbapi.update(user, {'last_factura': seq})
        redirect('/app/secuencia')

    @w.get('/app/ver_cliente')
    @dbcontext
    @auth_decorator(0)
    def ver_cliente():
        temp = jinja_env.get_template('ver_item.html')
        return temp.render(title='Ver Cliente', baseurl='/app/cliente',
                           apiurl='/api/cliente')

    @w.get('/app/crear_cliente')
    @dbcontext
    @auth_decorator(0)
    def crear_cliente_form(message=None):
        temp = jinja_env.get_template('crear_cliente.html')
        return temp.render(client=None, message=message, action='/app/crear_cliente',
                           button_text='Crear')

    bind_dbapi_rest('/app/api/client', dbapi, Client, w)
    return w
Example #4
0
def make_wsgi_api(prefix, sessionmanager, dbcontext, auth_decorator, dbapi):
    app = Bottle()

    @app.post(prefix + '/item_full')
    @dbcontext
    @auth_decorator
    def create_item_full():
        """
            input format:
            {
                "prod" : {prod_id, name, desc, base_unit}< - information on item group
                "items": [{multiplier}, {unit}<- information on items requires multiplier be distinct
                "prices": [{unit, almacen_id, display_name, price1, price2, cant}]
                "new_unit": []
            }
        """

        content = request.body.read()
        content = json.loads(content)
        valid, message = validate_full_item(content, dbapi)
        if not valid:
            return {'status': 'failure', 'msg': message}
        create_full_item_from_dict(dbapi, content)
        sessionmanager.session.commit()
        return {'status': 'success'}

    @app.get(prefix + '/item_full/<item_id>')
    @dbcontext
    def get_item_full(item_id):
        itemgroup = dbapi.get(item_id, ProdItemGroup)
        items = dbapi.search(ProdItem, itemgroupid=itemgroup.uid)
        prices_by_item = {}
        for x in items:
            prices_by_item[x.prod_id] = dbapi.search(PriceList,
                                                     prod_id=x.prod_id)
        return json_dumps(make_full_items(itemgroup, items, prices_by_item))

    @app.post(prefix + '/item_with_price')
    @dbcontext
    def save_item_with_price():
        # TODO: VALIDATION
        item_with_price = json.loads(request.body.read())
        item = ProdItem.deserialize(item_with_price)
        prod_id = item_with_price['prod_id']
        if int(item_with_price['multiplier']) > 1:
            prod_id += '+'
        item.prod_id = prod_id
        uid = dbapi.create(item)
        for aid, x in item_with_price['price'].items():
            p = PriceList()
            p.almacen_id = aid
            p.prod_id = prod_id
            p.precio1 = int(Decimal(x['price1']) * 100)
            p.precio2 = int(Decimal(x['price2']) * 100)
            p.nombre = x['display_name']
            p.cant_mayorista = x['cant']
            p.unidad = item.unit
            p.multiplicador = item.multiplier
            dbapi.create(p)
        dbapi.db_session.commit()
        return {'status': 'success', 'uid': uid}

    bind_dbapi_rest(prefix + '/pricelist', dbapi, PriceList, app)
    bind_dbapi_rest(prefix + '/itemgroup', dbapi, ProdItemGroup, app)
    bind_dbapi_rest(prefix + '/item', dbapi, ProdItem, app)
    return app
Example #5
0
def make_wsgi_api(prefix, sessionmanager, dbcontext, auth_decorator, dbapi):
    app = Bottle()

    @app.post(prefix + '/item_full')
    @dbcontext
    @auth_decorator
    def create_item_full():
        """
            input format:
            {
                "prod" : {prod_id, name, desc, base_unit}< - information on item group
                "items": [{multiplier}, {unit}<- information on items requires multiplier be distinct
                "prices": [{unit, almacen_id, display_name, price1, price2, cant}]
                "new_unit": []
            }
        """

        content = request.body.read()
        content = json.loads(content)
        valid, message = validate_full_item(content, dbapi)
        if not valid:
            return {'status': 'failure', 'msg': message}
        create_full_item_from_dict(dbapi, content)
        sessionmanager.session.commit()
        return {'status': 'success'}

    @app.get(prefix + '/item_full/<item_id>')
    @dbcontext
    def get_item_full(item_id):
        itemgroup = dbapi.get(item_id, ProdItemGroup)
        items = dbapi.search(ProdItem, itemgroupid=itemgroup.uid)
        prices_by_item = {}
        for x in items:
            prices_by_item[x.prod_id] = dbapi.search(PriceList, prod_id=x.prod_id)
        return json_dumps(make_full_items(itemgroup, items, prices_by_item))

    @app.post(prefix + '/item_with_price')
    @dbcontext
    def save_item_with_price():
        # TODO: VALIDATION
        item_with_price = json.loads(request.body.read())
        item = ProdItem.deserialize(item_with_price)
        prod_id = item_with_price['prod_id']
        if int(item_with_price['multiplier']) > 1:
            prod_id += '+'
        item.prod_id = prod_id
        uid = dbapi.create(item)
        for aid, x in item_with_price['price'].items():
            p = PriceList()
            p.almacen_id = aid
            p.prod_id = prod_id
            p.precio1 = int(Decimal(x['price1']) * 100)
            p.precio2 = int(Decimal(x['price2']) * 100)
            p.nombre = x['display_name']
            p.cant_mayorista = x['cant']
            p.unidad = item.unit
            p.multiplicador = item.multiplier
            dbapi.create(p)
        dbapi.db_session.commit()
        return {'status': 'success', 'uid': uid}


    bind_dbapi_rest(prefix + '/pricelist', dbapi, PriceList, app)
    bind_dbapi_rest(prefix + '/itemgroup', dbapi, ProdItemGroup, app)
    bind_dbapi_rest(prefix + '/item', dbapi, ProdItem, app)
    return app
Example #6
0
def make_wsgi_api(dbapi, invapi, dbcontext, auth_decorator, paymentapi, imgserver):
    w = Bottle()

    @w.get('/app/api/sales')
    @dbcontext
    def get_sales():
        """ start=<start>&end=<end>
        """
        start_date, end_date = parse_start_end_date(request.query)
        if not end_date:
            end_date = datetime.date.today()
        end_date = end_date + datetime.timedelta(hours=23)
        query = dbapi.db_session.query(
            NNota.almacen_id, func.sum(NNota.total)).filter(
            NNota.timestamp >= start_date).filter(
            NNota.timestamp <= end_date).filter(
            NNota.status != Status.DELETED).group_by(NNota.almacen_id)
        result = []
        for aid, total in query:
            result.append((aid, Decimal(total) / 100))
        return json_dumps({'result': result})

    @w.get('/app/api/payment')
    @dbcontext
    def get_all_payments():
        start, end = parse_start_end_date(request.query)
        result = list(paymentapi.list_payments(start, end))
        return json_dumps({'result': result})

    @w.get('/app/api/gasto')
    @dbcontext
    def get_all_gastos():
        day = parse_iso(request.query.get('date'))
        result = dbapi.search(Spent, inputdate=day)
        return json_dumps(result)

    @w.get('/app/api/account_transaction')
    @dbcontext
    def get_account_transactions_mult_days():
        start, end = parse_start_end_date(request.query)
        result = get_transactions(dbapi, paymentapi, invapi, imgserver, start, end)
        return json_dumps(result)

    @w.get('/app/api/check')
    @dbcontext
    def get_checks():
        save_date = request.query.get('save_date')
        save_date_end = request.query.get('save_date_end')
        deposit_date = request.query.get('deposit_date')
        deposit_date_end = request.query.get('deposit_date_end')
        if save_date:
            save_date = (save_date, save_date_end)
        if deposit_date:
            deposit_date = (deposit_date, deposit_date_end)
        checks = paymentapi.list_checks(save_date, deposit_date)
        for x in checks:
            x.imgdeposit = imgserver.get_url_path(x.imgdeposit)
            x.imgcheck = imgserver.get_url_path(x.imgcheck)
            x.value = Decimal(x.value) / 100
        return json_dumps({'result': checks})

    @w.post('/app/api/acct_transaction')
    @dbcontext
    def post_acct_transaction():
        data = request.body.read()
        acct = AccountTransaction.deserialize(json.loads(data))
        acct.input_timestamp = datetime.datetime.now()
        acct.deleted = False
        pkey = dbapi.create(acct)
        return {'pkey': pkey}

    @w.put('/app/api/acct_transaction/<uid>')
    @dbcontext
    def put_acct_transaction(uid):
        data = json.loads(request.body.read())
        acct = AccountTransaction(uid=uid)
        count = dbapi.update(acct, data)
        return {'updated': count}

    @w.get('/app/api/noncash_sales_with_payments')
    @dbcontext
    @auth_decorator
    def ver_ventas_no_efectivos():
        start, end = parse_start_end_date(request.query)
        end += datetime.timedelta(hours=23)
        sales = dbapi.db_session.query(NNota).filter(
            NNota.timestamp >= start).filter(NNota.timestamp <= end).filter(
            NNota.payment_format != PaymentFormat.CASH)

        sales = map(InvMetadata.from_db_instance, sales)
        payments = list(paymentapi.list_payments(start, end))

        result = {}
        for x in sales:
            if x.client.codigo not in result:
                result[x.client.codigo] = {}
                result[x.client.codigo]['sales'] = []
                result[x.client.codigo]['payments'] = []
            result[x.client.codigo]['sales'].append(x)

        unused_payments = []
        for x in payments:
            if x.client_id in result:
                result[x.client_id]['payments'].append(x)
            else:
                unused_payments.append(x)

        result['unused_payments'] = unused_payments
        return json_dumps({
            'unused_payments': unused_payments,
            'sales': result.items()
        })

    @w.get('/app/api/account_deposit_with_img')
    @dbcontext
    @auth_decorator
    def get_account_deposit_with_img():
        today = datetime.datetime.today()
        thisyear = today - datetime.timedelta(days=365)
        turned_in = sorted(get_turned_in_cash(dbapi, thisyear, today, imgserver),
                           key=lambda x: x.date, reverse=True)
        result = defaultdict(list)
        for x in turned_in:
            if getattr(x, 'img', None):
                if len(result['with_deposit']) < 10:
                    result['with_deposit'].append(x)
            else:
                result['without_deposit'].append(x)
        return json_dumps(result)


    # account stat
    bind_dbapi_rest('/app/api/account_stat', dbapi, AccountStat, w)
    bind_dbapi_rest('/app/api/bank_account', dbapi, DepositAccount, w)
    bind_dbapi_rest('/app/api/account_deposit', dbapi, AccountTransaction, w)

    bind_dbapi_rest('/app/api/spent', dbapi, Spent, w, skips_method=('DELETE', ))

    @w.get('/app/api/pago/<uid>')
    @dbcontext
    def get_pago_with_id(uid):
        elm = dbapi.db_session.query(NPayment).filter_by(uid=uid).first()
        if elm is None:
            response.status = 404
            return ''
        return json_dumps(Payment().merge_from(elm).serialize())

    @w.delete('/app/api/pago/<uid>')
    @dbcontext
    def mark_pago_deleted(uid):
        success = dbapi.db_session.query(NPayment).filter_by(uid=uid).update({'deleted': True})
        dbapi.db_session.commit()
        return {'success': success > 0}

    @w.put('/app/api/pago/<uid>')
    @dbcontext
    def modify_payment(uid):
        data = json.loads(request.body.read())
        success = dbapi.db_session.query(NPayment).filter_by(uid=uid).update(data)
        dbapi.db_session.commit()
        return {'success': success > 0}

    @w.delete('/app/api/spent/<uid>')
    @dbcontext
    def mark_pago_deleted(uid):
        spent = Spent(uid=uid)
        sucess = dbapi.update(spent, {'deleted': True})
        dbapi.db_session.commit()
        return {'success': sucess > 0}

    return w
Example #7
0
def make_sale_records_api(prefix, auth_decorator, dbapi,
                          invmomanager, inventoryapi):
    app = Bottle()
    dbcontext = DBContext(dbapi.session)

    bind_dbapi_rest(prefix + '/entity', dbapi, Entity, app)

    @app.post(prefix + '/client_sale')
    @dbcontext
    @auth_decorator
    def post_sale():
        content = Sale.deserialize(json.loads(request.body.read()))
        if list(dbapi.search(
                Sale, seller_codename=content.seller_codename,
                seller_inv_uid=content.seller_inv_uid)):
            return {'status': 'failed', 'reason': 'sale with the id already exists'}
        dbapi.create(content)
        return {'status': 'success'}

    @app.get(prefix + '/client_sale')
    @dbcontext
    @auth_decorator
    def get_sales():
        start, end = parse_start_end_date(request.query)
        result = list(get_sales_by_date_and_user(dbapi, start, end))
        return json_dumps(result)

    @app.delete(prefix + '/client_sale')
    @dbcontext
    @auth_decorator
    def delete_sale():
        content = Sale.deserialize(json.loads(request.body.read()))
        deleted = dbapi.db_session.query(NSale).filter_by(
            seller_codename=content.seller_codename, seller_inv_uid=content.seller_inv_uid
        ).update({'status': Status.DELETED})
        return {'deleted': deleted}

    @app.post(prefix + '/inv_movement_set')
    @dbcontext
    @auth_decorator
    def post_inv_movement_set():
        raw_inv = request.body.read()
        inv_movement = InvMovementFull.deserialize(json.loads(raw_inv))
        meta = inv_movement.meta
        meta.origin = get_or_create_inventory_id(dbapi, meta.inventory_codename, meta.origin)
        meta.dest = get_or_create_inventory_id(dbapi, meta.inventory_codename, meta.dest)

        if list(dbapi.search(InvMovementMeta,
                             inventory_codename=meta.inventory_codename,
                             inventory_docid=meta.inventory_docid,
                             trans_type=meta.trans_type)):
            # already exists
            return {'created': 0, 'reason': 'already exists'}
        for igcant in inv_movement.items:
            prod_id = igcant.itemgroup.prod_id
            ig_real = dbapi.getone(ProdItemGroup, prod_id=prod_id)
            # itemgroup does not exist, create
            if not ig_real:
                dbapi.create(igcant.itemgroup)
            else:  # replace itemgroup as the itemgroup id might be distinct
                igcant.itemgroup = ig_real
        inv_movement = invmomanager.create(inv_movement)
        return {'created': inv_movement.meta.uid}

    @app.get(prefix + '/inv_movement/<day>')
    @dbcontext
    def last_inv_movements(day):
        today = parse_iso_date(day)
        tomorrow = today + datetime.timedelta(days=1)
        print today, tomorrow
        movements = list(dbapi.search(InvMovementMeta, **{'timestamp-gte': today, 'timestamp-lte': tomorrow}))
        return json_dumps({'result': movements})

    @app.get(prefix + '/sales_report')
    @dbcontext
    def get_sales_report():
        start, end = parse_start_end_date(request.query)
        sales_by_date = list(client_sale_report(dbapi, start, end))
        return json_dumps({'result': sales_by_date})

    # @app.post(prefix + '/raw_inv_movement')
    # expects [proditemgroup, inventoryMovement, codename]
    @dbcontext
    def post_raw_inv_movement():
        raw_data = json.loads(request.body.read())
        ig = ProdItemGroup.deserialize(raw_data[0])
        trans = map(InventoryMovement.deserialize, raw_data[1])
        codename = raw_data[2]

        if dbapi.getone(ProdItemGroup, prod_id=ig.prod_id) is None:
            if dbapi.get(ig.uid, ProdItemGroup) is not None:
                #  prod_id does not exist but uid is used so we cannot create
                #  using the same uid
                ig.uid = None
            dbapi.create(ig)

        for i in trans:
            i.itemgroup_id = ig.uid
            if dbapi.getone(Inventory, entity_codename=codename, external_id=i.from_inv_id) is None:
                # create new Inventory if none
                i.from_inv_id = get_or_create_inventory_id(dbapi, codename, i.from_inv_id)
                i.to_inv_id = get_or_create_inventory_id(dbapi, codename, i.to_inv_id)
                i.reference_id = codename + (i.reference_id or '')
            inventoryapi.save(i)

    return app
Example #8
0
def make_wsgi_api(dbapi, invapi, dbcontext, auth_decorator, paymentapi,
                  imgserver):
    w = Bottle()

    @w.get('/app/api/sales')
    @dbcontext
    def get_sales():
        """ start=<start>&end=<end>
        """
        start_date, end_date = parse_start_end_date(request.query)
        if not end_date:
            end_date = datetime.date.today()
        end_date = end_date + datetime.timedelta(hours=23)
        query = dbapi.db_session.query(NNota.almacen_id, func.sum(
            NNota.total)).filter(NNota.timestamp >= start_date).filter(
                NNota.timestamp <= end_date).filter(
                    NNota.status != Status.DELETED).group_by(NNota.almacen_id)
        result = []
        for aid, total in query:
            result.append((aid, Decimal(total) / 100))
        return json_dumps({'result': result})

    @w.get('/app/api/payment')
    @dbcontext
    def get_all_payments():
        start, end = parse_start_end_date(request.query)
        result = list(paymentapi.list_payments(start, end))
        return json_dumps({'result': result})

    @w.get('/app/api/gasto')
    @dbcontext
    def get_all_gastos():
        day = parse_iso(request.query.get('date'))
        result = dbapi.search(Spent, inputdate=day)
        return json_dumps(result)

    @w.get('/app/api/account_transaction')
    @dbcontext
    def get_account_transactions_mult_days():
        start, end = parse_start_end_date(request.query)
        result = get_transactions(dbapi, paymentapi, invapi, imgserver, start,
                                  end)
        return json_dumps(result)

    @w.get('/app/api/check')
    @dbcontext
    def get_checks():
        save_date = request.query.get('save_date')
        save_date_end = request.query.get('save_date_end')
        deposit_date = request.query.get('deposit_date')
        deposit_date_end = request.query.get('deposit_date_end')
        if save_date:
            save_date = (save_date, save_date_end)
        if deposit_date:
            deposit_date = (deposit_date, deposit_date_end)
        checks = paymentapi.list_checks(save_date, deposit_date)
        for x in checks:
            x.imgdeposit = imgserver.get_url_path(x.imgdeposit)
            x.imgcheck = imgserver.get_url_path(x.imgcheck)
            x.value = Decimal(x.value) / 100
        return json_dumps({'result': checks})

    @w.post('/app/api/acct_transaction')
    @dbcontext
    def post_acct_transaction():
        data = request.body.read()
        acct = AccountTransaction.deserialize(json.loads(data))
        acct.input_timestamp = datetime.datetime.now()
        acct.deleted = False
        pkey = dbapi.create(acct)
        return {'pkey': pkey}

    @w.put('/app/api/acct_transaction/<uid>')
    @dbcontext
    def put_acct_transaction(uid):
        data = json.loads(request.body.read())
        acct = AccountTransaction(uid=uid)
        count = dbapi.update(acct, data)
        return {'updated': count}

    @w.get('/app/api/noncash_sales_with_payments')
    @dbcontext
    @auth_decorator
    def ver_ventas_no_efectivos():
        start, end = parse_start_end_date(request.query)
        end += datetime.timedelta(hours=23)
        sales = dbapi.db_session.query(NNota).filter(
            NNota.timestamp >= start).filter(NNota.timestamp <= end).filter(
                NNota.payment_format != PaymentFormat.CASH)

        sales = map(InvMetadata.from_db_instance, sales)
        payments = list(paymentapi.list_payments(start, end))

        result = {}
        for x in sales:
            if x.client.codigo not in result:
                result[x.client.codigo] = {}
                result[x.client.codigo]['sales'] = []
                result[x.client.codigo]['payments'] = []
            result[x.client.codigo]['sales'].append(x)

        unused_payments = []
        for x in payments:
            if x.client_id in result:
                result[x.client_id]['payments'].append(x)
            else:
                unused_payments.append(x)

        result['unused_payments'] = unused_payments
        return json_dumps({
            'unused_payments': unused_payments,
            'sales': result.items()
        })

    @w.get('/app/api/account_deposit_with_img')
    @dbcontext
    @auth_decorator
    def get_account_deposit_with_img():
        today = datetime.datetime.today()
        thisyear = today - datetime.timedelta(days=365)
        turned_in = sorted(get_turned_in_cash(dbapi, thisyear, today,
                                              imgserver),
                           key=lambda x: x.date,
                           reverse=True)
        result = defaultdict(list)
        for x in turned_in:
            if getattr(x, 'img', None):
                if len(result['with_deposit']) < 10:
                    result['with_deposit'].append(x)
            else:
                result['without_deposit'].append(x)
        return json_dumps(result)

    # account stat
    bind_dbapi_rest('/app/api/account_stat', dbapi, AccountStat, w)
    bind_dbapi_rest('/app/api/bank_account', dbapi, DepositAccount, w)
    bind_dbapi_rest('/app/api/account_deposit', dbapi, AccountTransaction, w)

    bind_dbapi_rest('/app/api/spent',
                    dbapi,
                    Spent,
                    w,
                    skips_method=('DELETE', ))

    @w.get('/app/api/pago/<uid>')
    @dbcontext
    def get_pago_with_id(uid):
        elm = dbapi.db_session.query(NPayment).filter_by(uid=uid).first()
        if elm is None:
            response.status = 404
            return ''
        return json_dumps(Payment().merge_from(elm).serialize())

    @w.delete('/app/api/pago/<uid>')
    @dbcontext
    def mark_pago_deleted(uid):
        success = dbapi.db_session.query(NPayment).filter_by(uid=uid).update(
            {'deleted': True})
        dbapi.db_session.commit()
        return {'success': success > 0}

    @w.put('/app/api/pago/<uid>')
    @dbcontext
    def modify_payment(uid):
        data = json.loads(request.body.read())
        success = dbapi.db_session.query(NPayment).filter_by(
            uid=uid).update(data)
        dbapi.db_session.commit()
        return {'success': success > 0}

    @w.delete('/app/api/spent/<uid>')
    @dbcontext
    def mark_pago_deleted(uid):
        spent = Spent(uid=uid)
        sucess = dbapi.update(spent, {'deleted': True})
        dbapi.db_session.commit()
        return {'success': sucess > 0}

    return w
Example #9
0
def make_wsgi_api(prefix, sessionmanager, dbcontext, auth_decorator, dbapi, inventoryapi):
    app = Bottle()

    @app.post(prefix + "/item_full")
    @dbcontext
    @auth_decorator
    def create_item_full():
        """
            input format:
            {
                "prod" : {prod_id, name, desc, base_unit}< - information on item group
                "items": [{multiplier}, {unit}<- information on items requires multiplier be distinct
                "prices": [{unit, almacen_id, display_name, price1, price2, cant}]
                "new_unit": []
            }
        """

        content = request.body.read()
        content = json.loads(content)
        valid, message = validate_full_item(content, dbapi)
        if not valid:
            return {"status": "failure", "msg": message}
        create_full_item_from_dict(dbapi, content)
        sessionmanager.session.commit()
        return {"status": "success"}

    @app.get(prefix + "/item_full/<item_id>")
    @dbcontext
    def get_item_full(item_id):
        itemgroup = dbapi.get(item_id, ProdItemGroup)
        items = dbapi.search(ProdItem, itemgroupid=itemgroup.uid)
        prices_by_item = {}
        for x in items:
            prices_by_item[x.prod_id] = dbapi.search(PriceList, prod_id=x.prod_id)
        return json_dumps(make_full_items(itemgroup, items, prices_by_item))

    @app.post(prefix + "/item_with_price")
    @dbcontext
    def save_item_with_price():
        # TODO: VALIDATION
        item_with_price = json.loads(request.body.read())
        item = ProdItem.deserialize(item_with_price)
        prod_id = item_with_price["prod_id"]
        if int(item_with_price["multiplier"]) > 1:
            prod_id += "+"
        item.prod_id = prod_id
        uid = dbapi.create(item)
        for aid, x in item_with_price["price"].items():
            p = PriceList()
            p.almacen_id = aid
            p.prod_id = prod_id
            p.precio1 = int(Decimal(x["price1"]) * 100)
            p.precio2 = int(Decimal(x["price2"]) * 100)
            p.nombre = x["display_name"]
            p.cant_mayorista = x["cant"]
            p.unidad = item.unit
            p.multiplicador = item.multiplier
            dbapi.create(p)
        dbapi.db_session.commit()
        return {"status": "success", "uid": uid}

    @app.get(prefix + "/prod_quantity/<uid>")
    @dbcontext
    def get_prod_quantity(uid):
        current_record = inventoryapi.get_current_quantity(uid)
        bodegas = dbapi.search(Bodega)
        return json_dumps({"inv": bodegas, "itemgroup_id": uid, "quantity": current_record})

    @app.get(prefix + "/itemgroup/<uid>/transaction")
    @dbcontext
    def get_transactions_of_item_group(uid):
        start, end = parse_start_end_date(request.query)
        start = start.date()
        end = end.date()
        return json_dumps({"results": list(inventoryapi.list_transactions(uid, start, end))})

    bind_dbapi_rest(prefix + "/pricelist", dbapi, PriceList, app)
    bind_dbapi_rest(prefix + "/itemgroup", dbapi, ProdItemGroup, app)
    bind_dbapi_rest(prefix + "/item", dbapi, ProdItem, app)
    return app
Example #10
0
def make_wsgi_api(prefix, sessionmanager, dbcontext, 
                  auth_decorator, dbapi, inventoryapi, sync_api):
    app = Bottle()

    @app.post(prefix + '/item_full')
    @dbcontext
    @auth_decorator(0)
    def create_item_full():
        """
            input format:
            {
                "prod" : {prod_id, name, desc, base_unit}< - information on item group
                "items": [{multiplier}, {unit}<- information on items requires multiplier be distinct
                "prices": [{unit, almacen_id, display_name, price1, price2, cant}]
                "new_unit": []
            }
        """

        content = request.body.read()
        content = json.loads(content)
        valid, message = validate_full_item(content, dbapi)
        if not valid:
            return {'status': 'failure', 'msg': message}
        create_full_item_from_dict(dbapi, content)
        # write new prod to log
        sync_api.write_new_prod(content)
        sessionmanager.session.commit()
        return {'status': 'success'}

    @app.get(prefix + '/item_full/<item_id>')
    @dbcontext
    def get_item_full(item_id):
        itemgroup = dbapi.get(item_id, ProdItemGroup)
        items = dbapi.search(ProdItem, itemgroupid=itemgroup.uid)
        prices_by_item = {}
        for x in items:
            prices_by_item[x.prod_id] = dbapi.search(PriceList, prod_id=x.prod_id)
        return json_dumps(make_full_items(itemgroup, items, prices_by_item))

    @app.post(prefix + '/item_with_price')
    @dbcontext
    def save_item_with_price():
        # TODO: VALIDATION
        item_with_price = json.loads(request.body.read())
        item = ProdItem.deserialize(item_with_price)
        prod_id = item_with_price['prod_id']
        if int(item_with_price['multiplier']) > 1:
            prod_id += '+'
        item.prod_id = prod_id
        uid = dbapi.create(item)
        for aid, x in item_with_price['price'].items():
            p = PriceList()
            p.almacen_id = aid
            p.prod_id = prod_id
            p.precio1 = int(Decimal(x['price1']) * 100)
            p.precio2 = int(Decimal(x['price2']) * 100)
            p.nombre = x['display_name']
            p.cant_mayorista = x['cant']
            p.unidad = item.unit
            p.multiplicador = item.multiplier
            dbapi.create(p)
        dbapi.db_session.commit()
        return {'status': 'success', 'uid': uid}

    @app.get(prefix + '/prod_quantity/<uid>')
    @dbcontext
    def get_prod_quantity(uid):
        current_record = inventoryapi.get_current_quantity(uid)
        bodegas = dbapi.search(Bodega)
        return json_dumps({
            'inv': bodegas,
            'itemgroup_id': uid,
            'quantity': current_record
        })

    @app.get(prefix + '/itemgroup/<uid>/transaction')
    @dbcontext
    def get_transactions_of_item_group(uid):
        start, end = parse_start_end_date(request.query)
        start = start.date()
        end = end.date()
        return json_dumps({'results': list(inventoryapi.list_transactions(uid, start, end))})

    bind_restapi(prefix + '/pricelist', 
        RestApi(dbapi, PriceList, logging=sync_api.log_price_list_change), app)
    bind_dbapi_rest(prefix + '/itemgroup', dbapi, ProdItemGroup, app)
    bind_dbapi_rest(prefix + '/item', dbapi, ProdItem, app)
    return app