示例#1
0
 async def on_req_delete_node(self, node_id=None):
     if node_id is None:
         pass  # deleting the node that is being inserted
     else:
         await self.db_obj.init(display=False,
                                init_vals={'row_id': node_id})
         if not await self.db_obj.getval('parent_id'):
             raise AibError(head='Error', body='Cannot delete root node')
         if await self.db_obj.getval('children'):
             raise AibError(head='Error',
                            body='Cannot delete node with children')
         await self.db_obj.delete()
     self.session.responder.send_delete_node(self.ref, node_id)
示例#2
0
async def claim_task(session, task_id):
    if task_id not in active_tasks:
        raise AibError(
            head='Claim task',
            body='Task {} already completed/cancelled'.format(task_id))
    task, claimed_by = active_tasks[task_id]
    if claimed_by is not None:
        user_name = await db.cache.get_user_name(claimed_by.user_row_id)
        raise AibError(head='Claim task',
                       body='Task {} already claimed by {}'.format(
                           task.title, user_name))
    active_tasks[task_id] = (task, session)
    bump_version()
    await task.start_task(session)
示例#3
0
    async def on_selected(self, node_id):
        # await self.db_obj.init(init_vals={'row_id': node_id})
        await self.db_obj.select_row({'row_id': node_id})

        if self.group is not None:
            node_type = await self.db_obj.getval('type')
            data_row_id = await self.db_obj.getval('data_row_id')

            node_type = await self.db_obj.getval('type')
            if node_type == 'group':
                # # await self.group.init(init_vals={'row_id': data_row_id})
                # await self.group.select_row({'row_id': data_row_id})
                raise AibError(head='Lookup',
                               body='Cannot select {} here'.format(
                                   self.group.table_name))
            else:  # must be 'member'
                # await self.member.init(init_vals={'row_id': data_row_id})
                await self.member.select_row({'row_id': data_row_id})

        self.session.responder.send_end_form(self.form)
        await self.form.close_form()
        callback, caller, *args = self.form.callback
        state = 'completed'
        return_params = None
        await callback(caller, state, return_params, *args)
示例#4
0
async def eval_exp(src, chk, tgt, db_obj, fld, value):
    if chk == 'pyfunc':
        if fld is None:  # called from db.objects
            fld = await db_obj.getfld(src)  # src is the field name to check
        src_val = await eval_elem(src, db_obj, fld, value)
        func_name = tgt
        if '.' in func_name:
            module_name, func_name = func_name.rsplit('.', 1)
            module = importlib.import_module(module_name)
            result = await getattr(module, func_name)(db_obj, fld, src_val)
        else:  # e.g. check_not_null
            result = await globals()[func_name](db_obj, fld, src_val)
        if result not in (True, False):
            raise AibError(
                head='pyfunc error',
                body=f'pyfunc {func_name} must return True or False')
    else:
        src_val = await eval_elem(src, db_obj, fld, value)
        tgt_val = await eval_elem(tgt, db_obj, fld, value)
        # don't know what could go wrong here [2019-07-08]
        # try:
        #     result = CHKS[chk](src_val, tgt_val)
        # except ValueError:
        #     result = False
        result = CHKS[chk](src_val, tgt_val)
    return result
示例#5
0
async def exch_rate(fld, xml, debug):
    code_xml, date_xml = xml  # must be two elements
    curr_id = await globals()[code_xml.tag](fld, code_xml, debug)
    if curr_id is None:
        return None
    eff_date = await globals()[date_xml.tag](fld, date_xml, debug)
    if eff_date is None:
        return None

    curr_rates = await db.cache.get_curr_rates(fld.db_obj.company)
    col_names = ['rate']
    where = []
    where.append(('WHERE', '', 'currency_id', '=', curr_id, ''))
    where.append(('AND', '', 'eff_date', '<=', eff_date, ''))
    order = [('eff_date', True)]
    limit = 1

    async with fld.db_obj.context.db_session.get_connection() as db_mem_conn:
        conn = db_mem_conn.db
        cur = await conn.full_select(curr_rates,
                                     col_names,
                                     where=where,
                                     order=order,
                                     limit=limit)
        try:
            rate, = await cur.__anext__()
        except StopAsyncIteration:
            raise AibError(head='Exchange rate', body='No exchange rate found')

    return rate
示例#6
0
async def setup_balance_date(caller, xml):
    # called from ar_balances before_start_form
    fin_periods = await db.cache.get_adm_periods(caller.company)
    ledger_periods = await db.cache.get_ledger_periods(
        caller.company, *caller.context.mod_ledg_id)
    if not ledger_periods:
        raise AibError(head='Periods',
                       body='No periods set up for {}'.format(
                           caller.context.mod_ledg_id))
    current_period = ledger_periods.current_period  # set initial period_no to current_period

    today = dt.today()
    current_closing_date = fin_periods[current_period].closing_date
    if today > current_closing_date:
        balance_date = current_closing_date
    else:
        balance_date = today

    var = caller.data_objects['balance_date_vars']
    await var.setval('balance_date', balance_date)
    await var.setval(
        'settings',
        [
            'P',  # select_method
            current_period,  # period_no
            balance_date,
        ])
示例#7
0
async def set_tran_lock(caller, xml):
    obj_name = xml.get('obj_name')
    tran_obj = caller.context.data_objects[obj_name]
    if not tran_obj.exists:
        return  # only applies if amending an existing transaction

    # 'lock' is called 'before_start_form', 'unlock' is called 'on_close_form'
    # this assumes that one form instance amends only one transaction
    # if we have one form instance that amends a series of transactions,
    #   this will not work
    key = (caller.company, tran_obj.db_table.data_tableid, await
           tran_obj.getval('row_id'))
    action = xml.get('action')
    if action == 'lock':
        with await tran_lock:
            if key in tran_locks:
                locking_caller = tran_locks[key]
                locking_user = await get_user_name(
                    locking_caller.context.user_row_id)
                raise AibError(
                    head='Transaction locked',
                    body='{}: transaction is currently in use by {}'.format(
                        tran_obj.db_table.short_descr, locking_user))
            tran_locks[key] = caller
    elif action == 'unlock':
        if key in tran_locks:
            if tran_locks[key] is caller:
                del tran_locks[key]
示例#8
0
async def get_mod_id(company, mod_id):
    # mod_id could be numeric, asking for module_id, or alpha, asking for module_row_id
    if mod_id is None:
        raise AibError(head='Module', body='Module id is None')
    with await mod_lock:
        if company not in mod_ids:
            mod_ids[company] = {}
            async with db_session.get_connection() as db_mem_conn:
                conn = db_mem_conn.db
                sql = f'SELECT row_id, module_id, descr FROM {company}.db_modules WHERE deleted_id = 0'
                async for row_id, module_id, descr in await conn.exec_sql(sql):
                    mod_ids[company][row_id] = (module_id, descr)
                    mod_ids[company][module_id] = row_id
    try:
        return mod_ids[company][mod_id]
    except KeyError:
        raise AibError(head='Module', body=f'"{mod_id}" not found')
示例#9
0
async def check_wh_date(db_obj, fld, ledger_row_id):
    # called from various ledger_row_id col_checks using pyfunc

    if ledger_row_id is None:  # no dflt_val for ledger_row_id
        return True  # will be called after entry of ledger_row_id

    try:
        period_row_id = await db_obj.getval(
            'tran_det_row_id>tran_row_id>period_row_id')
    except KeyError:
        period_row_id = await db_obj.getval('tran_row_id>period_row_id')
    module_row_id = await db.cache.get_mod_id(db_obj.company, 'in')

    ledger_periods = await db.cache.get_ledger_periods(db_obj.company,
                                                       module_row_id,
                                                       ledger_row_id)

    if ledger_periods is None:
        raise AibError(head=fld.col_defn.short_descr,
                       body='Warehouse period not set up')

    if period_row_id not in ledger_periods:
        # if period_row_id == ledger_periods['curr'] + 1:  # create new open period
        if period_row_id == ledger_periods.current_period + 1:  # create new open period
            ledger_period = await db.objects.get_db_object(
                db.cache.cache_context, db_obj.company, 'in_ledger_periods')
            await ledger_period.init(
                init_vals={
                    'ledger_row_id': ledger_row_id,
                    'period_row_id': period_row_id,
                    'state': 'open',
                })
            await ledger_period.save()

            ledger_periods = await db.cache.get_ledger_periods(
                db_obj.company, module_row_id, ledger_row_id)

    if period_row_id not in ledger_periods:
        raise AibError(head=fld.col_defn.short_descr,
                       body='Warehouse period not open')
    if ledger_periods[period_row_id].state not in ('current', 'open',
                                                   'reopened'):
        raise AibError(head=fld.col_defn.short_descr,
                       body='Warehouse period is closed')

    return True
示例#10
0
async def chk_constraint(caller, constraint, value=None, errmsg=None):
    # can be a column constraint (col_chk) or a table constraint (upd_chk or del_chk)
    try:
        db_obj = caller.db_obj  # this is a column constraint
        fld = caller
        descr = caller.col_defn.short_descr
    except AttributeError:
        db_obj = caller  # this is a table constraint
        fld = None
        descr = db_obj.db_table.short_descr

    result = await eval_expr(constraint, db_obj, fld, value)

    if result not in (True, False):
        raise AibError(
            head='constraint error',
            body=f'constraint {constraint} must return True or False')
    if result is False:
        raise AibError(head=descr, body=errmsg)
示例#11
0
 async def on_req_delete_node(self, node_id=None):
     if node_id is not None:  # else deleting the node that is being inserted
         await self.db_obj.init(display=False,
                                init_vals={'row_id': node_id})
         if node_id == 1:
             raise AibError(head='Error', body='Cannot delete root node')
         node_type = await self.db_obj.getval('type')
         data_row_id = await self.db_obj.getval('data_row_id')
         if node_type == 'group':
             obj_to_delete = self.group
         else:  # must be 'member'
             obj_to_delete = self.member
         if await obj_to_delete.getval('children'):
             raise AibError(head='Error',
                            body='Cannot delete node with children')
         await obj_to_delete.delete()
         # self.db_obj.init(display=False)
         # await self.db_obj.setval('type', node_type)
         # await self.db_obj.setval('data_row_id', data_row_id)
         await self.db_obj.delete()
     self.session.responder.send_delete_node(self.ref, node_id)
示例#12
0
async def dump_form_xml(caller, xml):
    # called from setup_form 'before_save'
    form_defn = caller.data_objects['form']
    form_vars = caller.data_objects['form_vars']
    frame_vars = caller.data_objects['frame_vars']

    form_xml = etree.Element('form')
    form_xml.set('name', await form_defn.getval('form_name'))
    form_xml.set('title', await form_defn.getval('title'))

    await set_if_not_none(form_xml, form_vars, 'before_start_form')
    await set_if_not_none(form_xml, form_vars, 'after_start_form')
    await set_if_not_none(form_xml, form_vars, 'on_end_form')

    form_xml.append(await form_vars.getval('dbobj_xml'))
    form_xml.append(await form_vars.getval('memobj_xml'))
    form_xml.append(await form_vars.getval('inputs_xml'))
    form_xml.append(await form_vars.getval('outputs_xml'))

    frame_xml = etree.SubElement(form_xml, 'frame')

    await set_if_not_none(frame_xml, frame_vars, 'main_object')
    await set_if_not_none(frame_xml, frame_vars, 'obj_descr')

    frame_xml.append(await frame_vars.getval('toolbar_xml'))
    frame_xml.append(await frame_vars.getval('body_xml'))
    frame_xml.append(await frame_vars.getval('buttonrow_xml'))
    frame_xml.append(await frame_vars.getval('methods_xml'))

    inline_vars = caller.data_objects['inline_vars']
    all_inline = inline_vars.select_many(where=[], order=[])
    async for _ in all_inline:
        inline_xml = etree.SubElement(form_xml, 'inline_form')
        inline_xml.set('name', await inline_vars.getval('name'))
        inline_xml.set('title', await inline_vars.getval('title'))
        inline_xml.append(await inline_vars.getval('frame_xml'))

    # inline_params = await form_vars.getval('inline_xml')
    # for name, frame_xml in inline_params:
    #     inline_xml = etree.SubElement(form_xml, 'inline_form')
    #     inline_xml.set('name', name)
    #     inline_xml.append(frame_xml)

    # validate result using schema
    try:
        etree.fromstring(etree.tostring(form_xml), parser=xsd_parser)
    except (etree.XMLSyntaxError, ValueError, TypeError) as e:
        raise AibError(head='XmlError', body=e.args[0])

    # update form_definition with new form_xml
    await form_defn.setval('form_xml', form_xml)

    """
示例#13
0
    async def handle_unhandled_cust():
        if 'ar_customers' not in caller.context.data_objects:
            caller.context.data_objects[
                'ar_customers'] = await db.objects.get_db_object(
                    caller.context, caller.company, 'ar_customers')
        ar_cust = caller.context.data_objects['ar_customers']
        if 'ar_stat_dates' not in caller.context.data_objects:
            caller.context.data_objects[
                'ar_stat_dates'] = await db.objects.get_db_object(
                    caller.context, caller.company, 'ar_stat_dates')
        stat_dates = caller.context.data_objects['ar_stat_dates']
        if 'ar_ledg_per' not in caller.context.data_objects:
            caller.context.data_objects[
                'ar_ledg_per'] = await db.objects.get_db_object(
                    caller.context, caller.company, 'ar_ledger_periods')
        ledg_per = caller.context.data_objects['ar_ledg_per']

        unhandled_cust = ar_cust.select_many(
            where=[['WHERE', '', 'current_stat_date', 'IS', None, '']],
            order=[])
        async for _ in unhandled_cust:
            await stat_dates.init()
            await stat_dates.setval('cust_row_id', await
                                    ar_cust.getval('row_id'))
            await stat_dates.setval('period_row_id', params['current_period'])
            if stat_dates.exists:
                raise AibError(head='Closing flag',
                               body='Closing flag already set')
            await stat_dates.setval('statement_date', params['statement_date'])
            await stat_dates.setval('state', 'closing')
            await stat_dates.save()

        await ledg_per.setval('ledger_row_id', caller.context.mod_ledg_id[1])
        await ledg_per.setval('period_row_id', params['current_period'])
        if await ledg_per.getval('state') != 'open':
            raise AibError(head='Closing flag',
                           body='Closing flag already set')
        await ledg_per.setval('statement_date', params['statement_date'])
        await ledg_per.setval('state', 'closing')
        await ledg_per.save()
示例#14
0
async def dump_tristates(caller, xml):
    # called from dbcols_setup before_save
    db_cols = caller.data_objects['db_cols']
    var = caller.data_objects['var']

    if await var.getval('allow_amend') == 'false':
        allow_amend = False
    elif await var.getval('allow_amend') == 'true':
        allow_amend = True
    else:
        amend = caller.data_objects['amend']
        if await amend.getval('param') is None:
            raise AibError(head='Allow amend', body='Parameters required')
        allow_amend = [
            await amend.getval('param'), await amend.getval('test'), {
                'False': False,
                'True': True,
                'None': None
            }[await amend.getval('value')]
        ]
    await db_cols.setval('allow_amend', allow_amend)

    if await var.getval('calculated') == 'false':
        calculated = False
    elif await var.getval('calculated') == 'true':
        calculated = True
    else:
        calc = caller.data_objects['calc']
        if await calc.getval('name') is None:
            raise AibError(head='Calculated', body='Parameters required')
        calculated = [
            f'{await calc.getval("type")}.{await calc.getval("name")}', await
            calc.getval('test'), {
                'False': False,
                'True': True,
                'None': None
            }[await calc.getval('value')]
        ]
    await db_cols.setval('calculated', calculated)
示例#15
0
 async def setup_form(form_name):
     xml = open('{}/{}.xml'.format(form_path, form_name)).read()
     await form_defn.init()
     await form_defn.setval('form_name', form_name)
     xml = xml.replace('`', '&quot;').replace('<<', '&lt;').replace(
         '>>', '&gt;').replace('&&', '&amp;')
     try:
         form_xml = etree.fromstring(xml, parser=parser)
     except (etree.XMLSyntaxError, ValueError, TypeError) as e:
         raise AibError(head=form_name, body=e.args[0])
     await form_defn.setval('title', form_xml.get('title'))
     await form_defn.setval('form_xml', form_xml)
     await form_defn.save()
示例#16
0
async def assign(caller, xml):
    source = xml.get('src')
    target = xml.get('tgt')
    format = xml.get('format')

    #-------------------------------
    # source could be an expression!
    #-------------------------------

    if format:
        """
        <source>
          <format>{0} {1}</format>
          <arg>dir_users.first_name</arg>
          <arg>dir_users.surname</arg>
        </source>
        <target>var.full_name</target>
        """
        # print('formatting')
        format_string = format.text
        format_args = []
        for arg in source.arg:
            if '.' in arg.text:
                arg_objname, arg_colname = arg.text.split('.')
                arg_record = caller.data_objects[arg_objname]
                arg_field = await arg_record.getfld(arg_colname)
                format_arg = await arg_field.getval()
            else:
                raise AibError(head='Error',
                               body='Unknown format argument {}'.format(
                                   arg.text))
            format_args.append(format_arg)
        value_to_assign = format_string.format(*format_args)
    else:
        value_to_assign = await get_val(caller, source)

    # target can be objname.colname or objname.colname.keyname if data_type is a JSON dict
    target_objname, target_colname = target.split('.', maxsplit=1)
    if target_objname == '_ctx':
        setattr(caller.context, target_colname, value_to_assign)
    else:
        target_obj = caller.data_objects[target_objname]
        if '.' in target_colname:
            target_colname, target_key = target_colname.split('.')
            target_fld = await target_obj.getfld(target_colname)
            assert target_fld.col_defn.data_type == 'JSON'
            target_dict = await target_fld.getval()
            target_dict[target_key] = value_to_assign
            await target_fld.setval(target_dict)
        else:
            await target_obj.setval(target_colname, value_to_assign)
示例#17
0
 async def on_req_insert_node(self, args):
     parent_id, seq, node_type = args
     if not parent_id:
         raise AibError(head='Error', body='Cannot create new root')
     self.node_inserted = True
     self.insert_params = {'parent_id': parent_id, 'seq': seq}
     if self.levels:
         await self.db_obj.init(display=False,
                                init_vals={'row_id': parent_id})
         self.insert_params['level'] = await self.db_obj.getval('level') + 1
     await self.db_obj.init()
     self.session.responder.send_insert_node(self.ref, parent_id, seq, -1)
     if self.tree_frame is not None:
         await self.tree_frame.restart_frame()
示例#18
0
 async def setup_process(process_id):
     xml = open('{}/{}.xml'.format(proc_path, process_id)).read()
     await proc_defn.init()
     await proc_defn.setval('process_id', process_id)
     xml = xml.replace('`', '&quot;').replace('<<', '&lt;').replace(
         '>>', '&gt;').replace('&&', '&amp;')
     try:
         proc_xml = etree.fromstring(xml, parser=parser)
         schema.assertValid(proc_xml.find(S + 'definitions'))
     except (etree.XMLSyntaxError, ValueError, TypeError) as e:
         raise AibError(head=process_id, body=e.args[0])
     await proc_defn.setval('descr', proc_xml.get('descr'))
     await proc_defn.setval('proc_xml', proc_xml)
     await proc_defn.save()
示例#19
0
async def get_val(caller, value):
    if value.startswith('('):  # expression
        # for now assume a simple expression -
        #    (lft [spc] op [spc] rgt)
        # e.g. (item_row_id>balance_cust + alloc_cust)
        lft, op, rgt = value[1:-1].split(' ')
        lft = await get_val(caller, lft)
        rgt = await get_val(caller, rgt)
        op = getattr(operator, {
            '+': 'add',
            '-': 'sub',
            '*': 'mul',
            '/': 'truediv'
        }[op])
        if lft is None or rgt is None:
            return None
        else:
            return op(lft, rgt)
    if '.' in value:
        obj_name, col_name = value.split('.')
        if obj_name == '_ctx':
            if col_name == 'ledger_row_id':
                return getattr(caller.context, 'mod_ledg_id')[1]
            elif col_name == 'current_period':
                ledger_periods = await db.cache.get_ledger_periods(
                    caller.company, *caller.context.mod_ledg_id)
                return ledger_periods.current_period
            else:
                return getattr(caller.context, col_name)
        else:
            if obj_name == '_param':
                db_obj = await db.cache.get_adm_params(caller.company)
            elif obj_name == '_ledger':
                module_row_id, ledger_row_id = caller.context.mod_ledg_id
                db_obj = await db.cache.get_ledger_params(
                    caller.company, module_row_id, ledger_row_id)
            else:
                db_obj = caller.data_objects[obj_name]
            return await db_obj.getval(col_name)
    if value.startswith("'"):
        return value[1:-1]
    if value == '$True':
        return True
    if value == '$False':
        return False
    if value == '$None':
        return None
    if value.isdigit():
        return int(value)
    raise AibError(head='Get value', body='Unknown value "{}"'.format(value))
示例#20
0
async def set_per_closing_flag(caller, params):
    print('set_closing_flag')

    if 'ar_ledg_per' not in caller.context.data_objects:
        caller.context.data_objects[
            'ar_ledg_per'] = await db.objects.get_db_object(
                caller.context, caller.company, 'ar_ledger_periods')
    ledg_per = caller.context.data_objects['ar_ledg_per']
    await ledg_per.setval('ledger_row_id', caller.context.mod_ledg_id[1])
    await ledg_per.setval('period_row_id', params['current_period'])
    if await ledg_per.getval('state') not in ('current', 'open'):
        raise AibError(head='Closing flag', body='Period is not open')
    await ledg_per.setval('state', 'closing')
    await ledg_per.save()
示例#21
0
 async def handle_single_cust():
     cust_row_id = params['cust_row_id']
     if 'ar_stat_dates' not in caller.context.data_objects:
         caller.context.data_objects[
             'ar_stat_dates'] = await db.objects.get_db_object(
                 caller.context, caller.company, 'ar_stat_dates')
     stat_dates = caller.context.data_objects['ar_stat_dates']
     await stat_dates.setval('cust_row_id', cust_row_id)
     await stat_dates.setval('period_row_id', params['current_period'])
     if stat_dates.exists:
         raise AibError(head='Closing flag',
                        body='Closing flag already set')
     await stat_dates.setval('statement_date', params['statement_date'])
     await stat_dates.setval('state', 'closing')
     await stat_dates.save()
示例#22
0
 async def handle_all_cust():
     if 'ar_ledg_per' not in caller.context.data_objects:
         caller.context.data_objects[
             'ar_ledg_per'] = await db.objects.get_db_object(
                 caller.context, caller.company, 'ar_ledger_periods')
     ledg_per = caller.context.data_objects['ar_ledg_per']
     await ledg_per.setval('ledger_row_id', caller.context.mod_ledg_id[1])
     await ledg_per.setval('period_row_id', params['current_period'])
     if await ledg_per.getval('statement_state') != 'open':
         raise AibError(head='Closing flag',
                        body='Statement period is not open')
     await ledg_per.setval('statement_state', 'closing')
     process_row_id = await caller.manager.process.root.bpm_detail.getval(
         'header_row_id')
     await ledg_per.setval('stmnt_process_id', process_row_id)
     await ledg_per.save()
示例#23
0
async def get_form_title(company, form_name):
    with await title_lock:
        if '.' in form_name:
            company, form_name = form_name.split('.')
        async with db_session.get_connection() as db_mem_conn:
            conn = db_mem_conn.db
            sql = (f"SELECT title FROM {company}.sys_form_defns "
                   f"WHERE form_name = {conn.constants.param_style}")
            params = (form_name, )
            cur = await conn.exec_sql(sql, params)
            try:
                title, = await cur.__anext__()
            except StopAsyncIteration:  # no rows selected
                raise AibError(
                    head='Error',
                    body=f'Form {company}.{form_name} does not exist')
        return title
示例#24
0
async def after_party_id(caller, xml):
    # called from setup_party after var.party_id
    var = caller.data_objects['var']
    var_id = await var.getval('party_id')
    party = caller.data_objects['party']
    await party.setval('party_id', var_id)

    if var_id == '<new>':
        return

    if party.exists:
        party_id = await party.getval('party_id')
        await var.setval('party_id', party_id)  # to change 'a001' to 'A001'
    else:
        param_obj = await db.cache.get_adm_params(var.company)
        if await param_obj.getval('auto_party_id') is not None:
            raise AibError(head='Error', body='Does not exist')
示例#25
0
async def init_xml(caller, xml):
    # called from setup_process after process_id if process does not exist
    proc = caller.data_objects['proc']
    process_id = await proc.getval('process_id')

    proc_xml = etree.Element('process_root')
    proc_xml.set('process_id', process_id)
    etree.SubElement(proc_xml, 'db_objects')
    etree.SubElement(proc_xml, 'mem_objects')
    etree.SubElement(proc_xml, 'input_params')
    etree.SubElement(proc_xml, 'output_params')

    S = "{http://www.omg.org/spec/BPMN/20100524/MODEL}"
    nsmap = {}
    nsmap['semantic'] = 'http://www.omg.org/spec/BPMN/20100524/MODEL'
    nsmap['bpmndi'] = 'http://www.omg.org/spec/BPMN/20100524/DI'
    nsmap['di'] = 'http://www.omg.org/spec/DD/20100524/DI'
    nsmap['dc'] = 'http://www.omg.org/spec/DD/20100524/DC'
    nsmap['dbobj'] = 'http://www.accinabox.org/bpmn/dbobj_definitions'
    nsmap['memobj'] = 'http://www.accinabox.org/bpmn/memobj_definitions'

    bpmn_xml = etree.SubElement(proc_xml, S + 'definitions', nsmap=nsmap)
    bpmn_xml.set('id', f'{process_id}_0')
    bpmn_xml.set('targetNamespace', 'http://www.accinabox.org/bpmn')

    proc_elem = etree.SubElement(bpmn_xml,
                                 f"{{{bpmn_xml.nsmap['semantic']}}}process")
    proc_elem.set('id', process_id + '_1')
    proc_elem.set('isExecutable', "true")

    diag_elem = etree.SubElement(bpmn_xml,
                                 f"{{{bpmn_xml.nsmap['bpmndi']}}}BPMNDiagram")
    diag_elem.set('id', process_id + '_2')
    # diag_elem.set('name', ???)
    # diag_elem.set('resolution', ???)
    plane_elem = etree.SubElement(diag_elem,
                                  f"{{{bpmn_xml.nsmap['bpmndi']}}}BPMNPlane")
    plane_elem.set('bpmnElement', proc_elem.get('id'))

    try:
        etree.fromstring(etree.tostring(bpmn_xml), parser=xsd_parser)
    except (etree.XMLSyntaxError, ValueError, TypeError) as e:
        raise AibError(head='XmlError', body=e.args[0])

    await proc.setval('proc_xml', proc_xml)
    await load_proc_xml(caller, xml)
示例#26
0
    async def _fetch_row(self, row_no):  # overridden in db.cur_sqlite3
        # i.e. set up self.row_data
        if self.debug:
            print('fetch row', row_no, 'cursor_pos =', self.cursor_pos)
        if row_no in self.new_rows:
            self.row_data = self.new_rows[row_no]
            if self.debug:
                print(self.row_data)
            return
        if row_no >= self.num_rows:
            print('should not get here - {},{}'.format(row_no, self.num_rows))
            self.debugger()
            raise AibError(head=self.db_obj.table_name,
                           body='Should not get here - {}, {}'.format(
                               row_no, self.num_rows))
        row_no = self._grid_to_cursor(row_no)
        diff = row_no - self.cursor_pos
        if diff == 0:
            if self.debug:
                print('fetch relative 0 from _aib')
            cur = await self.conn.exec_sql('fetch relative 0 from _aib')
        elif diff == 1:
            if self.debug:
                print('fetch next from _aib')
            cur = await self.conn.exec_sql('fetch next from _aib')
        elif diff == -1:
            if self.debug:
                print('fetch prior from _aib')
            cur = await self.conn.exec_sql('fetch prior from _aib')
        else:
            if self.debug:
                print('fetch absolute {} from _aib'.format(row_no + 1))
            # python is 0-based, cursor is 1-based
            cur = await self.conn.exec_sql(
                'fetch absolute {} from _aib'.format(row_no + 1))
        self.cursor_pos = row_no

        # self.row_data = await cur.__anext__()
        row = await cur.__anext__()
        self.row_data = [
            await self.db_obj.get_val_from_sql(col_name, dat)
            for col_name, dat in zip(self.col_names, row)
        ]

        if self.debug:
            print('POS =', self.cursor_pos, ', DATA =', self.row_data)
示例#27
0
async def error(ctx, fld, value, xml):
    body = xml.get('body')
    if body is not None:
        if '$value' in body:
            body = body.replace('$value', str(value))
        if '{' in body:
            pos1 = body.index('{')
            pos2 = body.index('}')
            sub_col = body[pos1 + 1:pos2]
            if '.' in sub_col:
                sub_tbl, sub_col = sub_col.split('.')
                sub_dbobj = ctx.data_objects[sub_tbl]
            else:
                sub_dbobj = fld.db_obj
            sub_fld = await sub_dbobj.getfld(sub_col)
            body = body[:pos1] + await sub_fld.getval() + body[pos2 + 1:]
    raise AibError(head=xml.get('head'), body=body)
示例#28
0
async def setup_inv_alloc(db_obj, conn, return_vals):
    # called as split_src func from sls_isls_subinv.upd_on_save()
    # return values - cost_whouse, cost_local
    tot_to_allocate = await db_obj.getval('qty')

    if 'fifo' not in db_obj.context.data_objects:
        db_obj.context.data_objects['fifo'] = await db.objects.get_db_object(
            db_obj.context, db_obj.company, 'in_wh_prod_fifo')
    fifo = db_obj.context.data_objects['fifo']

    cols_to_select = [
        'row_id', 'unalloc_qty', 'unalloc_whouse', 'unalloc_local'
    ]
    where = [
        ('WHERE', '', 'wh_prod_row_id', '=', await
         db_obj.getval('wh_prod_row_id'), ''),
        ('AND', '', 'unalloc_qty', '>', 0, ''),
    ]
    order = [('tran_date', False), ('row_id', False)]

    async for row_id, unalloc_qty, unalloc_wh, unalloc_loc in await conn.full_select(
            fifo, cols_to_select, where=where, order=order):
        if tot_to_allocate > unalloc_qty:
            qty_allocated = unalloc_qty
            cost_wh = unalloc_wh
            cost_loc = unalloc_loc
        else:
            qty_allocated = tot_to_allocate
            cost_wh = unalloc_wh / unalloc_qty * qty_allocated
            cost_loc = unalloc_loc / unalloc_qty * qty_allocated
        if qty_allocated:  # can it ever be zero ??
            yield (
                row_id,
                qty_allocated,
                cost_wh,
                cost_loc,
            )

            tot_to_allocate -= qty_allocated
            return_vals[0] += cost_wh
            return_vals[1] += cost_loc
        if not tot_to_allocate:
            break  # fully allocated

    if tot_to_allocate:  # should never get here
        raise AibError(head='Error', body='Insufficient stock')
示例#29
0
async def get_dflt_date(caller, obj, xml):
    # called as form_dflt from various 'tran_date' fields
    prev_date = await obj.fld.get_prev()
    if prev_date is not None:
        return prev_date
    db_obj = obj.fld.db_obj
    adm_periods = await db.cache.get_adm_periods(db_obj.company)
    ledger_periods = await db.cache.get_ledger_periods(
        caller.company, *caller.context.mod_ledg_id)
    if ledger_periods == {}:
        raise AibError(head=obj.fld.col_defn.short_descr,
                       body='Ledger periods not set up')
    curr_closing_date = adm_periods[ledger_periods.current_period].closing_date
    today = dt.today()
    if today < curr_closing_date:
        return today
    else:
        return curr_closing_date
示例#30
0
async def get_mod_ledg_id(company, module_id, ledger_id):
    search_key = (module_id, ledger_id)
    with await mod_ledg_lock:
        if company not in mod_ledg_ids:
            mod_ledg_ids[company] = {}
        if search_key not in mod_ledg_ids[company]:
            module_row_id = await get_mod_id(company, module_id)
            async with db_session.get_connection() as db_mem_conn:
                conn = db_mem_conn.db
                sql = (
                    f"SELECT row_id, ledger_id FROM {company}.{module_id}_ledger_params "
                    "WHERE deleted_id = 0")
                async for ledger_row_id, ledger_id in await conn.exec_sql(sql):
                    mod_ledg_ids[company][
                        module_id, ledger_id] = module_row_id, ledger_row_id
    try:
        return mod_ledg_ids[company][search_key]
    except KeyError:
        raise AibError(head='Module/ledger_id',
                       body='"{}.{}" not found'.format(*search_key))