merge
bzr revid: christophe@tinyerp.com-20080819131400-s14sq8un0rzlucg0
This commit is contained in:
commit
64f20c2234
|
@ -327,6 +327,9 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
|
|||
if force_demo:
|
||||
force.append('demo')
|
||||
if update_module:
|
||||
for module in tools.config['init']:
|
||||
cr.execute('update ir_module_module set state=%s where state=%s and name=%s', ('to install', 'uninstalled', module))
|
||||
cr.commit()
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to install', 'to upgrade','to remove')")
|
||||
else:
|
||||
cr.execute("select name from ir_module_module where state in ('installed', 'to upgrade', 'to remove')")
|
||||
|
|
|
@ -1369,6 +1369,7 @@
|
|||
<field name="code">COP</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="CZK" model="res.currency">
|
||||
|
@ -1376,6 +1377,7 @@
|
|||
<field name="code">CZK</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="DKK" model="res.currency">
|
||||
|
@ -1396,6 +1398,7 @@
|
|||
<field name="code">HUF</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="IDR" model="res.currency">
|
||||
|
@ -1403,6 +1406,7 @@
|
|||
<field name="code">IDR</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="LVL" model="res.currency">
|
||||
|
@ -1449,6 +1453,7 @@
|
|||
<field name="code">PLN</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="SEK" model="res.currency">
|
||||
|
@ -1456,6 +1461,7 @@
|
|||
<field name="code">SEK</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="GBP" model="res.currency">
|
||||
|
@ -1475,6 +1481,7 @@
|
|||
<field name="code">ARS</field>
|
||||
<field name="rounding">0.01</field>
|
||||
<field name="accuracy">4</field>
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
|
||||
|
|
|
@ -1039,23 +1039,34 @@
|
|||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Server Action">
|
||||
<field name="name" select="1"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="state" select="1"/>
|
||||
<field name="model_id" select="1"/>
|
||||
<field name="sequence" select="2"/>
|
||||
<separator colspan="4" string="Python code"/>
|
||||
<field name="code" colspan="4" attrs="{'readonly':[('state','!=','python')]}"/>
|
||||
|
||||
<separator colspan="4" string="Trigger Configuration"/>
|
||||
<field name="trigger_obj_id" select="2" colspan="4" attrs="{'readonly':[('state','!=','trigger')]}"/>
|
||||
<field name="trigger_name" select="2" attrs="{'readonly':[('state','!=','trigger')]}"/>
|
||||
<!-- <field name="trigger_object_id" attrs="{'readonly':[('state','!=','trigger')]}"/>-->
|
||||
<separator colspan="4" string="Email Configuration"/>
|
||||
<field name="address" select="2" attrs="{'readonly':[('state','=','python'),('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','client_action'), ('state','=','other')]}"/>
|
||||
<field name="message" select="2" colspan="4" attrs="{'readonly':[('state','=','python'),('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','client_action'), ('state','=','other')]}"/>
|
||||
|
||||
<separator colspan="4" string="Other Actions Configuration"/>
|
||||
<field name="child_ids" colspan="4" attrs="{'readonly':[('state','!=','other')]}"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Python Code" attrs="{'invisible':[('state','!=','python')]}">
|
||||
<separator colspan="4" string="Python code"/>
|
||||
<field name="code" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
|
||||
<page string="Trigger" attrs="{'invisible':[('state','!=','trigger')]}">
|
||||
<separator colspan="4" string="Trigger Configuration"/>
|
||||
<field name="trigger_obj_id" select="2" colspan="4"/>
|
||||
<field name="trigger_name" select="2"/>
|
||||
</page>
|
||||
|
||||
<page string="Email" attrs="{'invisible':[('state','=','python'),('state','=','dummy'),('state','=','trigger'), ('state','=','object_create'), ('state','=','object_write'), ('state','=','client_action'), ('state','=','other')]}">
|
||||
<separator colspan="4" string="Email Configuration"/>
|
||||
<field name="address" domain="[('model_id','=',model_id)]"/>
|
||||
<field name="message" select="2" colspan="4"/>
|
||||
</page>
|
||||
|
||||
<page string="Other Actions" attrs="{'invisible':[('state','!=','other')]}">
|
||||
<separator colspan="4" string="Other Actions Configuration"/>
|
||||
<field name="child_ids" nolabel="1" colspan="4" />
|
||||
</page>
|
||||
|
||||
</notebook>
|
||||
<field name="usage"/>
|
||||
<field name="type"/>
|
||||
</form>
|
||||
|
@ -1080,8 +1091,22 @@
|
|||
<field name="res_model">ir.actions.server</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_server_action_tree"/>
|
||||
<field name="context">{'key':'myval'}</field>
|
||||
</record>
|
||||
<menuitem action="action_server_action" id="menu_server_action" parent="base.next_id_6"/>
|
||||
|
||||
|
||||
<record id="view_model_fields_tree" model="ir.ui.view">
|
||||
<field name="name">ir.model.fields.tree</field>
|
||||
<field name="model">ir.model.fields</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Fields">
|
||||
<field name="complete_name"/>
|
||||
<field name="model_id"/>
|
||||
<field name="name"/>
|
||||
<field name="field_description"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</terp>
|
||||
|
|
|
@ -255,10 +255,6 @@ class act_url(osv.osv):
|
|||
}
|
||||
act_url()
|
||||
|
||||
def _get_fields(self, cr, uid, context={}):
|
||||
|
||||
return [('key','Email Value')]
|
||||
|
||||
def model_get(self, cr, uid, context={}):
|
||||
wkf_pool = self.pool.get('workflow')
|
||||
ids = wkf_pool.search(cr, uid, [])
|
||||
|
@ -273,8 +269,60 @@ def model_get(self, cr, uid, context={}):
|
|||
res.append((model, name))
|
||||
|
||||
return res
|
||||
|
||||
|
||||
#class ir_model_fields(osv.osv):
|
||||
# _inherit = 'ir.model.fields'
|
||||
# _rec_name = 'complete_name'
|
||||
# _columns = {
|
||||
# 'complete_name': fields.char('Complete Name', required=True, size=64, select=1),
|
||||
# }
|
||||
#
|
||||
# def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=80):
|
||||
# def get_fields(cr, uid, field, rel):
|
||||
# result = []
|
||||
# mobj = self.pool.get('ir.model')
|
||||
# id = mobj.search(cr, uid, [('model','=',rel)])
|
||||
#
|
||||
# obj = self.pool.get('ir.model.fields')
|
||||
# ids = obj.search(cr, uid, [('model_id','in',id)])
|
||||
# records = obj.read(cr, uid, ids)
|
||||
# for record in records:
|
||||
# id = record['id']
|
||||
# fld = field + '/' + record['name']
|
||||
#
|
||||
# result.append((id, fld))
|
||||
# return result
|
||||
#
|
||||
# if not args:
|
||||
# args=[]
|
||||
# if not context:
|
||||
# context={}
|
||||
# return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
|
||||
#
|
||||
# result = []
|
||||
# obj = self.pool.get('ir.model.fields')
|
||||
# ids = obj.search(cr, uid, args)
|
||||
# records = obj.read(cr, uid, ids)
|
||||
# for record in records:
|
||||
# id = record['id']
|
||||
# field = record['name']
|
||||
#
|
||||
# if record['ttype'] == 'many2one':
|
||||
# rel = record['relation']
|
||||
# res = get_fields(cr, uid, field, record['relation'])
|
||||
# for rs in res:
|
||||
# result.append(rs)
|
||||
#
|
||||
# result.append((id, field))
|
||||
#
|
||||
# for rs in result:
|
||||
# obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]})
|
||||
#
|
||||
# #result = super(ir_model_fields, self).name_search(cr, uid, name, [['complete_name','ilike',name]], operator, context, limit)
|
||||
# return result
|
||||
#
|
||||
#ir_model_fields()
|
||||
##
|
||||
# Actions that are run on the server side
|
||||
#
|
||||
class actions_server(osv.osv):
|
||||
|
@ -302,7 +350,8 @@ class actions_server(osv.osv):
|
|||
#'trigger_object': fields.char('Trigger Object', size=128),
|
||||
#'trigger_object_id': fields.char('Trigger Object ID', size=128),
|
||||
'message': fields.text('Message', translate=True),
|
||||
'address': fields.selection(_get_fields ,'Email / SMS', size=128),
|
||||
'address': fields.many2one('ir.model.fields', 'Email From / SMS'),
|
||||
#selection(_get_fields ,'Email / SMS', size=128),
|
||||
'child_ids': fields.one2many('ir.actions.actions', 'parent_id', 'Others Actions'),
|
||||
'usage': fields.char('Action Usage', size=32),
|
||||
'type': fields.char('Report Type', size=32, required=True),
|
||||
|
@ -322,6 +371,11 @@ class actions_server(osv.osv):
|
|||
"""
|
||||
}
|
||||
|
||||
# def on_change_model(self, cr, uid, ids, model_id):
|
||||
# print '**************** : method called'
|
||||
# res = {'value' : {'address': [('key1','Email Value One')]} }
|
||||
# return res
|
||||
|
||||
#
|
||||
# Context should contains:
|
||||
# ids : original ids
|
||||
|
@ -344,9 +398,14 @@ class actions_server(osv.osv):
|
|||
exec action.code in localdict
|
||||
if 'action' in localdict:
|
||||
return localdict['action']
|
||||
|
||||
if action.state == 'email':
|
||||
user = config['email_from']
|
||||
subject = action.name
|
||||
|
||||
#TODO : Apply Mail merge in to the Content of the Email
|
||||
print '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ',context
|
||||
|
||||
body = action.message
|
||||
if tools.email_send_attach(user, action.address, subject, body, debug=False) == True:
|
||||
logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (action.address))
|
||||
|
@ -361,10 +420,12 @@ class actions_server(osv.osv):
|
|||
wf_service.trg_validate(uid, model, int(id), action.trigger_name, cr)
|
||||
|
||||
if action.state == 'sms':
|
||||
#TODO: Apply mearge with the field
|
||||
if tools.sms_send(user, password, api_id, text, to) == True:
|
||||
logger.notifyChannel('sms', netsvc.LOG_INFO, 'SMS successfully send to : %s' % (action.address))
|
||||
else:
|
||||
logger.notifyChannel('sms', netsvc.LOG_ERROR, 'Failed to send SMS to : %s' % (action.address))
|
||||
|
||||
if action.state == 'other':
|
||||
localdict = {
|
||||
'self': self.pool.get(action.model_id.model),
|
||||
|
@ -376,15 +437,10 @@ class actions_server(osv.osv):
|
|||
}
|
||||
|
||||
for act in action.child_ids:
|
||||
code = """
|
||||
action = {
|
||||
'res_model': %s,
|
||||
'type': %s,
|
||||
'name': %s,
|
||||
'usage': %s,
|
||||
}
|
||||
""" % (action.model_id.model, act.type, act.name, act.usage)
|
||||
exec action.code in localdict
|
||||
code = """action = {'model':'%s','type':'%s', %s}""" % (action.model_id.model, act.type, act.usage)
|
||||
exec code in localdict
|
||||
if 'action' in localdict:
|
||||
return localdict['action']
|
||||
|
||||
return False
|
||||
actions_server()
|
||||
|
|
|
@ -122,6 +122,7 @@ class ir_model_fields(osv.osv):
|
|||
'groups': fields.many2many('res.groups', 'ir_model_fields_group_rel', 'field_id', 'group_id', 'Groups'),
|
||||
'group_name': fields.char('Group Name', size=128),
|
||||
'view_load': fields.boolean('View Auto-Load'),
|
||||
'complete_name': fields.char('Complete Name', required=True, size=64, select=1),
|
||||
}
|
||||
_defaults = {
|
||||
'relate': lambda *a: 0,
|
||||
|
|
|
@ -89,6 +89,15 @@ class wizard_info_get(wizard.interface):
|
|||
mod_obj = pool.get('ir.module.module')
|
||||
ids = mod_obj.search(cr, uid, [
|
||||
('state', 'in', ['to upgrade', 'to remove', 'to install'])])
|
||||
unmet_packages=[]
|
||||
mod_dep_obj = pool.get('ir.module.module.dependency')
|
||||
for mod in mod_obj.browse(cr,uid,ids):
|
||||
depends_mod_ids=mod_dep_obj.search(cr,uid,[('module_id','=',mod.id)])
|
||||
for dep_mod in mod_dep_obj.browse(cr,uid,depends_mod_ids):
|
||||
if dep_mod.state in ('unknown','uninstalled'):
|
||||
unmet_packages.append(dep_mod.name)
|
||||
if len(unmet_packages):
|
||||
raise wizard.except_wizard('Unmet dependency !','Following modules are uninstalled or unknown. \n\n'+'\n'.join(unmet_packages))
|
||||
mod_obj.download(cr, uid, ids, context=context)
|
||||
cr.commit()
|
||||
db, pool = pooler.restart_pool(cr.dbname, update_module=True)
|
||||
|
|
|
@ -142,6 +142,7 @@ class res_partner(osv.osv):
|
|||
'user_id': fields.many2one('res.users', 'Dedicated Salesman', help='The internal user that is in charge of communicating with this partner if any.'),
|
||||
'responsible': fields.many2one('res.users', 'Users'),
|
||||
'vat': fields.char('VAT',size=32 ,help="Value Added Tax number"),
|
||||
'vat_subject': fields.boolean('Subjected to the VAT'),
|
||||
'bank_ids': fields.one2many('res.partner.bank', 'partner_id', 'Banks'),
|
||||
'website': fields.char('Website',size=64),
|
||||
'comment': fields.text('Notes'),
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<rng:optional><rng:attribute name="col"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="editable"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="type"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="notebook"/>
|
||||
|
@ -16,6 +17,7 @@
|
|||
<rng:ref name="label" />
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="image"/>
|
||||
<rng:ref name="form"/>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
<rng:element name="properties"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
|
@ -30,10 +32,13 @@
|
|||
<rng:optional><rng:attribute name="color"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="editable"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="toolbar"/></rng:optional>
|
||||
<rng:optional><rng:attribute name="position"/></rng:optional>
|
||||
<rng:zeroOrMore>
|
||||
<rng:choice>
|
||||
<rng:ref name="field"/>
|
||||
<rng:ref name="separator"/>
|
||||
<rng:ref name="tree"/>
|
||||
<rng:ref name="group"/>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
|
@ -186,6 +191,7 @@
|
|||
<rng:ref name="separator"/>
|
||||
<rng:ref name="xpath"/>
|
||||
<rng:ref name="button"/>
|
||||
<rng:ref name="group"/>
|
||||
<rng:element name="newline"><rng:empty/></rng:element>
|
||||
</rng:choice>
|
||||
</rng:zeroOrMore>
|
||||
|
|
|
@ -593,28 +593,28 @@ class orm_template(object):
|
|||
|
||||
while len(datas):
|
||||
res = {}
|
||||
try:
|
||||
(res, other, warning, translate, data_id) = \
|
||||
process_liness(self, datas, [], fields_def)
|
||||
if warning:
|
||||
cr.rollback()
|
||||
return (-1, res, warning, '')
|
||||
id = self.pool.get('ir.model.data')._update(cr, uid, self._name,
|
||||
current_module, res, xml_id=data_id, mode=mode,
|
||||
noupdate=noupdate)
|
||||
for lang in translate:
|
||||
context2 = context.copy()
|
||||
context2['lang'] = lang
|
||||
self.write(cr, uid, [id], translate[lang], context2)
|
||||
if config.get('commit_mode', False):
|
||||
cr.commit()
|
||||
except Exception, e:
|
||||
logger.notifyChannel("import", netsvc.LOG_ERROR, e)
|
||||
#try:
|
||||
(res, other, warning, translate, data_id) = \
|
||||
process_liness(self, datas, [], fields_def)
|
||||
if warning:
|
||||
cr.rollback()
|
||||
try:
|
||||
return (-1, res, e[0], warning)
|
||||
except:
|
||||
return (-1, res, e[0], '')
|
||||
return (-1, res, warning, '')
|
||||
id = self.pool.get('ir.model.data')._update(cr, uid, self._name,
|
||||
current_module, res, xml_id=data_id, mode=mode,
|
||||
noupdate=noupdate)
|
||||
for lang in translate:
|
||||
context2 = context.copy()
|
||||
context2['lang'] = lang
|
||||
self.write(cr, uid, [id], translate[lang], context2)
|
||||
if config.get('import_partial', False):
|
||||
cr.commit()
|
||||
#except Exception, e:
|
||||
# logger.notifyChannel("import", netsvc.LOG_ERROR, e)
|
||||
# cr.rollback()
|
||||
# try:
|
||||
# return (-1, res, e[0], warning)
|
||||
# except:
|
||||
# return (-1, res, e[0], '')
|
||||
done += 1
|
||||
#
|
||||
# TODO: Send a request with the result and multi-thread !
|
||||
|
|
|
@ -236,7 +236,10 @@ class osv(orm.orm):
|
|||
parent_name = hasattr(cls, '_inherit') and cls._inherit
|
||||
if parent_name:
|
||||
parent_class = pool.get(parent_name).__class__
|
||||
assert parent_class, "parent class %s does not exist !" % parent_name
|
||||
|
||||
print cls
|
||||
print cls._name
|
||||
assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
|
||||
nattr = {}
|
||||
for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints'):
|
||||
new = copy.copy(getattr(pool.get(parent_name), s))
|
||||
|
|
|
@ -58,7 +58,7 @@ class configmanager(object):
|
|||
'addons_path': None,
|
||||
'root_path': None,
|
||||
'debug_mode': False,
|
||||
'commit_mode': False,
|
||||
'import_partial': "",
|
||||
'pidfile': None,
|
||||
'logfile': None,
|
||||
'secure': False,
|
||||
|
@ -114,7 +114,7 @@ class configmanager(object):
|
|||
group.add_option("--db_host", dest="db_host", help="specify the database host")
|
||||
group.add_option("--db_port", dest="db_port", help="specify the database port")
|
||||
group.add_option("--db_maxconn", dest="db_maxconn", default='64', help="specify the the maximum number of physical connections to posgresql")
|
||||
group.add_option("-C", "--commit-mode", dest="commit_mode", action="store_true", help="Several commit during one file importation. Use this for big data importation.", default=False)
|
||||
group.add_option("-C", "--commit-mode", dest="import_partial", help="Several commit during one file importation. Use this for big data importation. Provide a filename to store intermediate state.", default=False)
|
||||
parser.add_option_group(group)
|
||||
|
||||
group = optparse.OptionGroup(parser, "Internationalisation options",
|
||||
|
@ -156,7 +156,7 @@ class configmanager(object):
|
|||
self.options['pidfile'] = False
|
||||
|
||||
for arg in ('interface', 'port', 'db_name', 'db_user', 'db_password', 'db_host',
|
||||
'db_port', 'logfile', 'pidfile', 'secure', 'smtp_ssl', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'netinterface', 'netport', 'db_maxconn', 'commit_mode', 'addons_path'):
|
||||
'db_port', 'logfile', 'pidfile', 'secure', 'smtp_ssl', 'email_from', 'smtp_server', 'smtp_user', 'smtp_password', 'price_accuracy', 'netinterface', 'netport', 'db_maxconn', 'import_partial', 'addons_path'):
|
||||
if getattr(opt, arg):
|
||||
self.options[arg] = getattr(opt, arg)
|
||||
|
||||
|
|
|
@ -657,7 +657,7 @@ form: module.record_id""" % (xml_id,)
|
|||
id = self.pool.get('ir.model.data')._update(cr, self.uid, rec_model, self.module, res, rec_id or False, not self.isnoupdate(data_node), noupdate=self.isnoupdate(data_node), mode=self.mode )
|
||||
if rec_id:
|
||||
self.idref[rec_id] = int(id)
|
||||
if config.get('commit_mode', False):
|
||||
if config.get('import_partial', False):
|
||||
cr.commit()
|
||||
return rec_model, id
|
||||
|
||||
|
@ -724,6 +724,15 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
|||
|
||||
pool = pooler.get_pool(cr.dbname)
|
||||
|
||||
import pickle
|
||||
if config.get('import_partial'):
|
||||
if not os.path.isfile(config.get('import_partial')):
|
||||
pickle.dump({}, file(config.get('import_partial'),'w+'))
|
||||
data = pickle.load(file(config.get('import_partial')))
|
||||
if fname in data:
|
||||
if not data[fname]:
|
||||
return
|
||||
|
||||
input = StringIO.StringIO(csvcontent)
|
||||
reader = csv.reader(input, quotechar='"', delimiter=',')
|
||||
fields = reader.next()
|
||||
|
@ -738,6 +747,10 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
|||
continue
|
||||
datas.append( map(lambda x:x.decode('utf8').encode('utf8'), line))
|
||||
pool.get(model).import_data(cr, uid, fields, datas,mode, module,noupdate)
|
||||
if config.get('import_partial'):
|
||||
data = pickle.load(file(config.get('import_partial')))
|
||||
data[fname] = 0
|
||||
pickle.dump(data, file(config.get('import_partial'),'wb'))
|
||||
|
||||
#
|
||||
# xml import/export
|
||||
|
|
Loading…
Reference in New Issue