[MERGE] merge with main branch
bzr revid: qdp-launchpad@tinyerp.com-20100706172422-bnkiuvwel9zdoj6j
This commit is contained in:
@@ -71,8 +71,8 @@ class account_invoice_line(osv.osv):
|
||||
_inherit = 'account.invoice.line'
|
||||
_description = 'Invoice Line'
|
||||
|
||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition=False, price_unit=False, address_invoice_id=False, currency_id=False, context=None):
|
||||
res_prod = super(account_invoice_line,self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition, price_unit, address_invoice_id, currency_id=currency_id, context=context)
|
||||
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fiscal_position=False, price_unit=False, address_invoice_id=False, currency_id=False, context=None):
|
||||
res_prod = super(account_invoice_line,self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fiscal_position, price_unit, address_invoice_id, currency_id=currency_id, context=context)
|
||||
rec = self.pool.get('account.analytic.default').account_get(cr, uid, product, partner_id, uid, time.strftime('%Y-%m-%d'), context)
|
||||
if rec:
|
||||
res_prod['value'].update({'account_analytic_id':rec.analytic_id.id})
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
|
||||
from datetime import datetime
|
||||
from osv import fields, osv, orm
|
||||
from osv.orm import except_orm
|
||||
from osv.osv import osv_pool
|
||||
from tools.translate import _
|
||||
import mx.DateTime
|
||||
import pooler
|
||||
@@ -42,17 +40,14 @@ class base_action_rule(osv.osv):
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
return self.state_get(cr, uid, context=context)
|
||||
|
||||
|
||||
def state_get(self, cr, uid, context={}):
|
||||
""" Get State
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
return [('', '')]
|
||||
|
||||
def priority_get(self, cr, uid, context={}):
|
||||
@@ -61,14 +56,13 @@ class base_action_rule(osv.osv):
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
return [('', '')]
|
||||
|
||||
_columns = {
|
||||
'name': fields.many2one('ir.model', 'Object', required=True),
|
||||
'max_level': fields.integer('Max Level', help='Specifies maximum level.'),
|
||||
'create_date': fields.datetime('Create Date', readonly=1),
|
||||
'active': fields.boolean('Active', help="If the active field is set to true,\
|
||||
'active': fields.boolean('Active', help="If the active field is set to False,\
|
||||
it will allow you to hide the rule without removing it."),
|
||||
'sequence': fields.integer('Sequence', help="Gives the sequence order \
|
||||
when displaying a list of rules."),
|
||||
@@ -85,10 +79,7 @@ specifies you can put a negative number. If you need a delay before the \
|
||||
trigger date, like sending a reminder 15 minutes before a meeting."),
|
||||
'trg_date_range_type': fields.selection([('minutes', 'Minutes'), ('hour', 'Hours'), \
|
||||
('day', 'Days'), ('month', 'Months')], 'Delay type'),
|
||||
|
||||
|
||||
'trg_user_id': fields.many2one('res.users', 'Responsible'),
|
||||
|
||||
'trg_partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'trg_partner_categ_id': fields.many2one('res.partner.category', 'Partner Category'),
|
||||
'trg_state_from': fields.selection(_state_get, 'State', size=16),
|
||||
@@ -171,10 +162,9 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
def _register_hook(self, cr, uid, ids, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
model_pool = self.pool.get('ir.model')
|
||||
for action_rule in self.browse(cr, uid, ids, context=context):
|
||||
model = action_rule.name.model
|
||||
obj_pool = self.pool.get(model)
|
||||
obj_pool = self.pool.get(model)
|
||||
obj_pool.__setattr__('create', self._create(obj_pool.create, model, context=context))
|
||||
obj_pool.__setattr__('write', self._write(obj_pool.write, model, context=context))
|
||||
return True
|
||||
@@ -194,7 +184,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
"""
|
||||
This Function is call by scheduler.
|
||||
"""
|
||||
rule_pool= self.pool.get('base.action.rule')
|
||||
rule_pool = self.pool.get('base.action.rule')
|
||||
rule_ids = rule_pool.search(cr, uid, [], context=context)
|
||||
return self._register_hook(cr, uid, rule_ids, context=context)
|
||||
|
||||
@@ -202,7 +192,6 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
def format_body(self, body):
|
||||
""" Foramat Action rule's body
|
||||
@param self: The object pointer """
|
||||
|
||||
return body and tools.ustr(body) or ''
|
||||
|
||||
def format_mail(self, obj, body):
|
||||
@@ -392,7 +381,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
|
||||
obj.date_action_next = dt
|
||||
model_obj.write(cr, uid, [obj.id], {'date_action_next': dt}, context)
|
||||
else:
|
||||
ok = action.trg_date_type=='none'
|
||||
ok = action.trg_date_type == 'none'
|
||||
|
||||
if ok:
|
||||
self.do_action(cr, uid, action, model_obj, obj, context)
|
||||
@@ -431,7 +420,7 @@ class ir_cron(osv.osv):
|
||||
|
||||
def _poolJobs(self, db_name, check=False):
|
||||
try:
|
||||
db, pool = pooler.get_db_and_pool(db_name)
|
||||
db = pooler.get_db(db_name)
|
||||
except:
|
||||
return False
|
||||
cr = db.cursor()
|
||||
@@ -439,8 +428,7 @@ class ir_cron(osv.osv):
|
||||
next = datetime.now().strftime('%Y-%m-%d %H:00:00')
|
||||
# Putting nextcall always less than current time in order to call it every time
|
||||
cr.execute('UPDATE ir_cron set nextcall = \'%s\' where numbercall<>0 and active and model=\'base.action.rule\' ' % (next))
|
||||
cr.commit()
|
||||
res = super(ir_cron, self)._poolJobs(db_name, check=check)
|
||||
super(ir_cron, self)._poolJobs(db_name, check=check)
|
||||
finally:
|
||||
cr.commit()
|
||||
cr.close()
|
||||
|
||||
@@ -57,22 +57,18 @@
|
||||
<field name="server_action_id"/>
|
||||
</page>
|
||||
<page string="Email Actions">
|
||||
<!-- <group col="4" colspan="2">-->
|
||||
<separator colspan="4" string="Email Reminders"/>
|
||||
<field name="act_remind_partner"/>
|
||||
<field name="act_remind_attach"/>
|
||||
<field name="act_remind_user"/>
|
||||
<group col="2" colspan="2" attrs="{'invisible': [('act_remind_user','=',False)]}">
|
||||
<field name="act_reply_to" attrs="{'required':[('act_remind_user','=',True)]}"/>
|
||||
</group>
|
||||
<separator colspan="4" string="Email Information"/>
|
||||
<field name="act_mail_to_watchers"/>
|
||||
<field name="act_mail_to_user"/>
|
||||
<field colspan="4" name="act_mail_to_email"/>
|
||||
<!-- </group>-->
|
||||
<!-- <group col="4" colspan="2">-->
|
||||
<separator colspan="4" string="Email Reminders"/>
|
||||
<field name="act_remind_partner"/>
|
||||
<field name="act_remind_attach"/>
|
||||
<field name="act_remind_user"/>
|
||||
<group col="2" colspan="2" attrs="{'invisible': [('act_remind_user','=',False)]}">
|
||||
<field name="act_reply_to" attrs="{'required':[('act_remind_user','=',True)]}"/>
|
||||
</group>
|
||||
<field name="act_mail_to_watchers"/>
|
||||
<field colspan="4" name="act_email_cc"/>
|
||||
<!-- </group>-->
|
||||
<separator colspan="4" string="Email Body"/>
|
||||
<field colspan="4" name="act_mail_body" height="250"
|
||||
nolabel="1" attrs="{'required':[('act_remind_user','=',True)]}" />
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_base_action_rule","base.action.rule","model_base_action_rule",,1,0,0,0
|
||||
"access_base_action_rule_config","base.action.rule config","model_base_action_rule",base.group_system,1,0,0,0
|
||||
"access_base_action_rule_config","base.action.rule config","model_base_action_rule",base.group_system,1,1,1,1
|
||||
|
+5
-5
@@ -22,7 +22,7 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
import base64
|
||||
import tools
|
||||
from osv import fields
|
||||
from osv import osv
|
||||
@@ -342,7 +342,6 @@ class crm_case(object):
|
||||
destination=False)
|
||||
|
||||
def remind_user(self, cr, uid, ids, context={}, attach=False,destination=True):
|
||||
|
||||
"""
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@@ -359,8 +358,9 @@ class crm_case(object):
|
||||
if case.section_id.reply_to and case.email_from:
|
||||
src = case.email_from
|
||||
dest = case.section_id.reply_to
|
||||
body = ""
|
||||
body = case.email_last or case.description
|
||||
body = case.description or ""
|
||||
if case.message_ids:
|
||||
body = case.message_ids[0].description or ""
|
||||
if not destination:
|
||||
src, dest = dest, src
|
||||
if body and case.user_id.signature:
|
||||
@@ -371,7 +371,7 @@ class crm_case(object):
|
||||
attach_to_send = None
|
||||
|
||||
if attach:
|
||||
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', 'mailgate.thread'), ('res_id', '=', case.id)])
|
||||
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
|
||||
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname','datas'])
|
||||
attach_to_send = map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send)
|
||||
|
||||
|
||||
@@ -115,26 +115,22 @@ this if you want the rule to send an email to the partner."),
|
||||
|
||||
|
||||
def state_get(self, cr, uid, context={}):
|
||||
|
||||
"""@param self: The object pointer
|
||||
"""Gets available states for crm
|
||||
@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
res = super(base_action_rule, self).state_get(cr, uid, context=context)
|
||||
return res + crm.AVAILABLE_STATES
|
||||
|
||||
def priority_get(self, cr, uid, context={}):
|
||||
|
||||
"""@param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param context: A standard dictionary for contextual values """
|
||||
|
||||
res = super(base_action_rule, self).priority_get(cr, uid, context=context)
|
||||
return res + crm.AVAILABLE_PRIORITIES
|
||||
|
||||
|
||||
base_action_rule()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_form"/>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="act_mail_to_watchers" position="before">
|
||||
<field name="act_mail_to_user" position="after">
|
||||
<field name="act_mail_to_partner"/>
|
||||
</field>
|
||||
</field>
|
||||
|
||||
@@ -57,6 +57,8 @@ class crm_meeting(osv.osv, crm_case):
|
||||
'id': fields.integer('ID'),
|
||||
'create_date': fields.datetime('Creation Date' , readonly=True),
|
||||
'write_date': fields.datetime('Write Date' , readonly=True),
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
# Meeting fields
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Meeting Type', \
|
||||
domain="[('object_id.model', '=', 'crm.meeting')]", \
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<field name="employee_id"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By...">
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="Employee" name="employee" icon="terp-personal" context="{'group_by':'employee_id'}"/>
|
||||
<filter string="Department" icon="terp-personal+" context="{'group_by':'department_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
|
||||
@@ -54,6 +54,12 @@
|
||||
'wizard/hr_payroll_employees_detail.xml',
|
||||
'wizard/hr_payroll_year_salary.xml',
|
||||
|
||||
],
|
||||
'test': [
|
||||
'test/payslip.yml',
|
||||
'test/payment_advice.yml',
|
||||
'test/payroll_register.yml',
|
||||
|
||||
],
|
||||
'demo_xml': [
|
||||
'hr_payroll_demo.xml'
|
||||
|
||||
@@ -194,10 +194,10 @@ class payroll_register(osv.osv):
|
||||
# 'advice_ids':fields.one2many('hr.payroll.advice', 'register_id', 'Bank Advice'),
|
||||
'company_id':fields.many2one('res.company', 'Company', required=False),
|
||||
'period_id': fields.many2one('account.period', 'Force Period', domain=[('state','<>','done')], help="Keep empty to use the period of the validation(Payslip) date."),
|
||||
'grows': fields.function(_calculate, method=True, store=True, multi='dc', string='Gross Salary', type='float', digits=(16, 4))),
|
||||
'net': fields.function(_calculate, method=True, store=True, multi='dc', string='Net Salary', digits=(16, 4)),
|
||||
'allounce': fields.function(_calculate, method=True, store=True, multi='dc', string='Allowance', digits=(16, 4)),
|
||||
'deduction': fields.function(_calculate, method=True, store=True, multi='dc', string='Deduction', digits=(16, 4)),
|
||||
'grows': fields.function(_calculate, method=True, store=True, multi='dc', string='Gross Salary', type='float', digits=(16, int(config['price_accuracy']))),
|
||||
'net': fields.function(_calculate, method=True, store=True, multi='dc', string='Net Salary', digits=(16, int(config['price_accuracy']))),
|
||||
'allounce': fields.function(_calculate, method=True, store=True, multi='dc', string='Allowance', digits=(16, int(config['price_accuracy']))),
|
||||
'deduction': fields.function(_calculate, method=True, store=True, multi='dc', string='Deduction', digits=(16, int(config['price_accuracy']))),
|
||||
'note': fields.text('Description'),
|
||||
}
|
||||
|
||||
@@ -366,8 +366,8 @@ class payroll_advice_line(osv.osv):
|
||||
'advice_id':fields.many2one('hr.payroll.advice', 'Bank Advice', required=False),
|
||||
'name':fields.char('Bank Account A/C', size=64, required=True, readonly=False),
|
||||
'employee_id':fields.many2one('hr.employee', 'Employee', required=True),
|
||||
'amount': fields.float('Amount', digits=(16, 4)),
|
||||
'bysal': fields.float('By Salary', digits=(16, 4)),
|
||||
'amount': fields.float('Amount', digits=(16, int(config['price_accuracy']))),
|
||||
'bysal': fields.float('By Salary', digits=(16, int(config['price_accuracy']))),
|
||||
'flag':fields.char('D/C', size=8, required=True, readonly=False),
|
||||
}
|
||||
_defaults = {
|
||||
@@ -434,10 +434,10 @@ class contrib_register(osv.osv):
|
||||
'analytic_account_id':fields.many2one('account.analytic.account', 'Analytic Account', required=False),
|
||||
'name':fields.char('Name', size=256, required=True, readonly=False),
|
||||
'register_line_ids':fields.one2many('hr.contibution.register.line', 'register_id', 'Register Line', readonly=True),
|
||||
'yearly_total_by_emp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Employee', digits=(16, 4)),
|
||||
'yearly_total_by_comp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Company', digits=(16, 4)),
|
||||
'monthly_total_by_emp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Employee', digits=(16, 4)),
|
||||
'monthly_total_by_comp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Company', digits=(16, 4)),
|
||||
'yearly_total_by_emp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Employee', digits=(16, int(config['price_accuracy']))),
|
||||
'yearly_total_by_comp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Company', digits=(16, int(config['price_accuracy']))),
|
||||
'monthly_total_by_emp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Employee', digits=(16, int(config['price_accuracy']))),
|
||||
'monthly_total_by_comp': fields.function(_total_contrib, method=True, multi='dc', store=True, string='Total By Company', digits=(16, int(config['price_accuracy']))),
|
||||
'note': fields.text('Description'),
|
||||
}
|
||||
_defaults = {
|
||||
@@ -466,9 +466,9 @@ class contrib_register_line(osv.osv):
|
||||
'code':fields.char('Code', size=64, required=False, readonly=False),
|
||||
'employee_id':fields.many2one('hr.employee', 'Employee', required=True),
|
||||
'period_id': fields.many2one('account.period', 'Period'),
|
||||
'emp_deduction': fields.float('Employee Deduction', digits=(16, 4)),
|
||||
'comp_deduction': fields.float('Company Deduction', digits=(16, 4)),
|
||||
'total': fields.function(_total, method=True, store=True, string='Total', digits=(16, 4)),
|
||||
'emp_deduction': fields.float('Employee Deduction', digits=(16, int(config['price_accuracy']))),
|
||||
'comp_deduction': fields.float('Company Deduction', digits=(16, int(config['price_accuracy']))),
|
||||
'total': fields.function(_total, method=True, store=True, string='Total', digits=(16, int(config['price_accuracy']))),
|
||||
}
|
||||
contrib_register_line()
|
||||
|
||||
@@ -539,7 +539,7 @@ class company_contribution(osv.osv):
|
||||
('fix','Fixed Amount'),
|
||||
('func','Function Calculation'),
|
||||
],'Amount Type', select=True),
|
||||
'contribute_per':fields.float('Contribution', digits=(16, 4), help='Define Company contribution ratio 1.00=100% contribution, If Employee Contribute 5% then company will and here 0.50 defined then company will contribute 50% on employee 5% contribution'),
|
||||
'contribute_per':fields.float('Contribution', digits=(16, int(config['price_accuracy'])), help='Define Company contribution ratio 1.00=100% contribution, If Employee Contribute 5% then company will and here 0.50 defined then company will contribute 50% on employee 5% contribution'),
|
||||
'account_id':fields.property(
|
||||
'account.account',
|
||||
type='many2one',
|
||||
@@ -596,13 +596,13 @@ class company_contribution_line(osv.osv):
|
||||
'contribution_id':fields.many2one('company.contribution', 'Contribution', required=False),
|
||||
'name':fields.char('Name', size=64, required=False, readonly=False),
|
||||
'umo_id':fields.many2one('product.uom', 'Unite', required=False),
|
||||
'from_val': fields.float('From', digits=(16, 4)),
|
||||
'to_val': fields.float('To', digits=(16, 4)),
|
||||
'from_val': fields.float('From', digits=(16, int(config['price_accuracy']))),
|
||||
'to_val': fields.float('To', digits=(16, int(config['price_accuracy']))),
|
||||
'amount_type':fields.selection([
|
||||
('fix','Fixed Amount'),
|
||||
],'Amount Type', select=True),
|
||||
'sequence':fields.integer('Sequence'),
|
||||
'value': fields.float('Value', digits=(16, 4)),
|
||||
'value': fields.float('Value', digits=(16, int(config['price_accuracy']))),
|
||||
}
|
||||
company_contribution_line()
|
||||
|
||||
@@ -1213,9 +1213,9 @@ class hr_payslip_line(osv.osv):
|
||||
'amount': fields.float('Amount / Percentage', digits=(16, 4)),
|
||||
'analytic_account_id':fields.many2one('account.analytic.account', 'Analytic Account', required=False),
|
||||
'account_id':fields.many2one('account.account', 'General Account', required=True),
|
||||
'total': fields.float('Sub Total', readonly=True, digits=(16, 4)),
|
||||
'total': fields.float('Sub Total', readonly=True, digits=(16, int(config['price_accuracy']))),
|
||||
#'total': fields.function(_calculate, method=True, type='float', string='Label', store=True),
|
||||
'company_contrib': fields.float('Company Contribution', readonly=True, digits=(16, 4)),
|
||||
'company_contrib': fields.float('Company Contribution', readonly=True, digits=(16, int(config['price_accuracy']))),
|
||||
'expanse_id': fields.many2one('hr.expense.expense', 'Expense'),
|
||||
'sequence': fields.integer('Sequence'),
|
||||
'note':fields.text('Description'),
|
||||
@@ -1251,13 +1251,13 @@ class hr_payslip_line_line(osv.osv):
|
||||
'slipline_id':fields.many2one('hr.payslip.line', 'Slip Line', required=False),
|
||||
'name':fields.char('Name', size=64, required=False, readonly=False),
|
||||
'umo_id':fields.many2one('product.uom', 'Unite', required=False),
|
||||
'from_val': fields.float('From', digits=(16, 4)),
|
||||
'to_val': fields.float('To', digits=(16, 4)),
|
||||
'from_val': fields.float('From', digits=(16, int(config['price_accuracy']))),
|
||||
'to_val': fields.float('To', digits=(16, int(config['price_accuracy']))),
|
||||
'amount_type':fields.selection([
|
||||
('fix','Fixed Amount'),
|
||||
],'Amount Type', select=True),
|
||||
'sequence':fields.integer('Sequence'),
|
||||
'value': fields.float('Value', digits=(16, 4)),
|
||||
'value': fields.float('Value', digits=(16, int(config['price_accuracy']))),
|
||||
}
|
||||
hr_payslip_line_line()
|
||||
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
<field name="manager" select="1"/>
|
||||
<field name="vehicle" select="1"/>
|
||||
<field name="vehicle_distance" select="1"/>
|
||||
<field name="medic_exam" select="1"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="2" string="ESI Information"/>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
-
|
||||
I test the 'Payment Advice' in order to check the hr_payroll in OpenERP
|
||||
-
|
||||
I create a new employee “Richie”
|
||||
-
|
||||
!record {model: hr.employee, id: hr_employee_richie0}:
|
||||
address_home_id: base.res_partner_address_1
|
||||
address_id: base.res_partner_address_9
|
||||
birthday: '1984-05-01'
|
||||
children: 0.0
|
||||
contract_ids:
|
||||
- advantages_gross: 0.0
|
||||
advantages_net: 0.0
|
||||
date_end: '2011-07-01'
|
||||
date_start: '2010-07-01'
|
||||
name: reference
|
||||
wage: 5000.0
|
||||
wage_type_id: hr_contract.hr_contract_monthly_gross
|
||||
country_id: base.in
|
||||
department_id: hr.dep_it
|
||||
employee_account: account.a_recv
|
||||
gender: male
|
||||
marital: hr.hr_employee_marital_status_single
|
||||
name: Richie
|
||||
pg_joining: '2009-12-01'
|
||||
property_bank_account: account.cash
|
||||
salary_account: account.a_recv
|
||||
vehicle_distance: 0.0
|
||||
-
|
||||
Then I create a new payment advice record
|
||||
-
|
||||
!record {model: hr.payroll.advice, id: hr_payroll_advice_advice0}:
|
||||
account_id: account.cash
|
||||
line_ids:
|
||||
- amount: 5500.0
|
||||
bysal: 5000.0
|
||||
employee_id: 'hr_employee_richie0'
|
||||
flag: C
|
||||
name: Axis Bank
|
||||
name: advice1
|
||||
-
|
||||
In order to confirm a sheet I click on "Confirm Sheet" button
|
||||
-
|
||||
!python {model: hr.payroll.advice}: |
|
||||
self.confirm_sheet(cr, uid, [ref("hr_payroll_advice_advice0")], {"lang": "en_US",
|
||||
"active_model": "ir.ui.menu", "active_ids": [ref("hr_payroll.hr_menu_payment_advice")],
|
||||
"tz": False, "active_id": ref("hr_payroll.hr_menu_payment_advice")})
|
||||
-
|
||||
I check that a state has transferred from draft to confirm
|
||||
-
|
||||
!python {model: hr.payroll.advice}: |
|
||||
from tools.translate import _
|
||||
advice_id=self.browse(cr, uid, ref("hr_payroll_advice_advice0"))
|
||||
assert(advice_id.state == 'confirm'), _('State not changed!')
|
||||
@@ -0,0 +1,63 @@
|
||||
-
|
||||
I test the 'Payroll Register' in order to check the hr_payroll in OpenERP
|
||||
-
|
||||
I create a new employee “Keith”
|
||||
-
|
||||
!record {model: hr.employee, id: hr_employee_keith0}:
|
||||
address_home_id: base.res_partner_address_3
|
||||
address_id: base.res_partner_address_9
|
||||
birthday: '1984-05-01'
|
||||
children: 0.0
|
||||
contract_ids:
|
||||
- advantages_gross: 0.0
|
||||
advantages_net: 0.0
|
||||
date_end: '2011-07-01'
|
||||
date_start: '2010-07-01'
|
||||
name: reference
|
||||
wage: 5000.0
|
||||
wage_type_id: hr_contract.hr_contract_monthly_gross
|
||||
country_id: base.in
|
||||
department_id: hr.dep_it
|
||||
employee_account: account.a_recv
|
||||
gender: male
|
||||
marital: hr.hr_employee_marital_status_single
|
||||
name: Keith
|
||||
pg_joining: '2009-12-01'
|
||||
property_bank_account: account.cash
|
||||
salary_account: account.a_recv
|
||||
vehicle_distance: 0.0
|
||||
-
|
||||
I create a payroll register record
|
||||
-
|
||||
!record {model: hr.payroll.register, id: hr_payroll_register_payroll0}:
|
||||
bank_journal_id: account.bank_journal
|
||||
date: '2010-07-02'
|
||||
journal_id: account.expenses_journal
|
||||
line_ids:
|
||||
- employee_id: hr_payroll.hr_employee_keith0
|
||||
bank_journal_id: account.bank_journal
|
||||
journal_id: account.expenses_journal
|
||||
name: payroll1
|
||||
-
|
||||
I click on Compute button
|
||||
-
|
||||
!python {model: hr.payroll.register}: |
|
||||
self.compute_sheet(cr, uid, [ref("hr_payroll_register_payroll0")], {"lang": "en_US",
|
||||
"tz": False, "active_model": "ir.ui.menu", "department_id": False, "active_ids":
|
||||
[ref("hr_payroll.hr_menu_payroll_register")], "section_id": False, "active_id":
|
||||
ref("hr_payroll.hr_menu_payroll_register"), })
|
||||
-
|
||||
Then I click on Verify Sheet button
|
||||
-
|
||||
!python {model: hr.payroll.register}: |
|
||||
self.verify_sheet(cr, uid, [ref("hr_payroll_register_payroll0")], {"lang": "en_US",
|
||||
"tz": False, "active_model": "ir.ui.menu", "department_id": False, "active_ids":
|
||||
[ref("hr_payroll.hr_menu_payroll_register")], "section_id": False, "active_id":
|
||||
ref("hr_payroll.hr_menu_payroll_register"), })
|
||||
-
|
||||
I check that a state has transferred from 'Wating for Verification' to 'Wating for HR Verification'state
|
||||
-
|
||||
!python {model: hr.payroll.register}: |
|
||||
from tools.translate import _
|
||||
reg_brw=self.browse(cr, uid, ref("hr_payroll_register_payroll0"))
|
||||
assert(reg_brw.state == 'hr_check'), _('State not changed!')
|
||||
@@ -0,0 +1,132 @@
|
||||
-
|
||||
I test the 'Payment Advice' in order to check the hr_payroll in OpenERP
|
||||
-
|
||||
I create a new employee “Richard”
|
||||
-
|
||||
!record {model: hr.employee, id: hr_employee_richard0}:
|
||||
address_home_id: base.res_partner_address_2
|
||||
address_id: base.res_partner_address_9
|
||||
birthday: '1984-05-01'
|
||||
children: 0.0
|
||||
contract_ids:
|
||||
- advantages_gross: 0.0
|
||||
advantages_net: 0.0
|
||||
date_end: '2011-07-01'
|
||||
date_start: '2010-07-01'
|
||||
name: reference
|
||||
wage: 5000.0
|
||||
wage_type_id: hr_contract.hr_contract_monthly_gross
|
||||
country_id: base.in
|
||||
department_id: hr.dep_it
|
||||
employee_account: account.a_recv
|
||||
gender: male
|
||||
marital: hr.hr_employee_marital_status_single
|
||||
name: Richard
|
||||
pg_joining: '2009-12-01'
|
||||
property_bank_account: account.cash
|
||||
salary_account: account.a_recv
|
||||
vehicle_distance: 0.0
|
||||
-
|
||||
I create a new payroll structure for software developer
|
||||
-
|
||||
!record {model: hr.payroll.structure, id: hr_payroll_structure_softwaredeveloper0}:
|
||||
code: SD
|
||||
line_ids:
|
||||
- account_id: account.a_expense
|
||||
amount: 0.40000000000000002
|
||||
amount_type: per
|
||||
category_id: hr_payroll.HRA
|
||||
code: HRA
|
||||
company_contrib: 0.0
|
||||
name: House Rant Allowance
|
||||
sequence: 5
|
||||
total: 0.0
|
||||
type: allowance
|
||||
- account_id: account.a_expense
|
||||
amount: 10000.0
|
||||
amount_type: fix
|
||||
category_id: hr_payroll.CA
|
||||
code: CA
|
||||
company_contrib: 0.0
|
||||
name: Convance Allowance
|
||||
sequence: 10
|
||||
total: 0.0
|
||||
type: allowance
|
||||
- account_id: account.a_pay
|
||||
amount: 10000.0
|
||||
amount_type: fix
|
||||
category_id: hr_payroll.PT
|
||||
code: PT
|
||||
company_contrib: 0.0
|
||||
name: Professional Tax
|
||||
sequence: 15
|
||||
total: 0.0
|
||||
type: deduction
|
||||
- account_id: account.a_pay
|
||||
amount: 0.125
|
||||
amount_type: per
|
||||
category_id: hr_payroll.PF
|
||||
code: PF
|
||||
company_contrib: 0.0
|
||||
name: Provident Fund
|
||||
sequence: 20
|
||||
total: 0.0
|
||||
type: deduction
|
||||
name: Software Developer
|
||||
-
|
||||
I create a employee payslip record
|
||||
-
|
||||
!record {model: hr.payslip, id: hr_payslip_0}:
|
||||
bank_journal_id: account.bank_journal
|
||||
employee_id: hr_payroll.hr_employee_richard0
|
||||
journal_id: account.expenses_journal
|
||||
-
|
||||
I click on 'Compute Sheet' button
|
||||
-
|
||||
!workflow {model: hr.payslip, action: compute_sheet, ref: hr_payslip_0}
|
||||
-
|
||||
!python {model: hr.payslip}: |
|
||||
self.compute_sheet(cr, uid, [ref("hr_payslip_0")], {"lang": "en_US", "tz": False,
|
||||
"active_model": "ir.ui.menu", "department_id": False, "active_ids": [ref("hr_payroll.menu_department_tree")],
|
||||
"section_id": False, "active_id": ref("hr_payroll.menu_department_tree"),
|
||||
})
|
||||
-
|
||||
I check that an order which was in the "New Slip" state has transit to "Wating for Verification" state
|
||||
-
|
||||
!python {model: hr.payslip}: |
|
||||
from tools.translate import _
|
||||
payslip_brw=self.browse(cr, uid, ref("hr_payslip_0"))
|
||||
assert(payslip_brw.state == 'draft'), _('State not changed!')
|
||||
-
|
||||
Then I click on Verify Sheet button
|
||||
-
|
||||
!workflow {model: hr.payslip, action: verify_sheet, ref: hr_payslip_0}
|
||||
-
|
||||
I check that an order which was in the "Wating for Verification" state has transit to "Wating for HR Verification" state
|
||||
-
|
||||
!python {model: hr.payslip}: |
|
||||
from tools.translate import _
|
||||
payslip_brw=self.browse(cr, uid, ref("hr_payslip_0"))
|
||||
assert(payslip_brw.state == 'hr_check'), _('State not changed!')
|
||||
-
|
||||
Then I click on Complete HR Checking button
|
||||
-
|
||||
!workflow {model: hr.payslip, action: final_verify_sheet, ref: hr_payslip_0}
|
||||
-
|
||||
I check that an order which was in the "'Wating for HR Verification'" state has transit to "Confirm Sheet" state
|
||||
-
|
||||
!python {model: hr.payslip}: |
|
||||
from tools.translate import _
|
||||
payslip_brw=self.browse(cr, uid, ref("hr_payslip_0"))
|
||||
assert(payslip_brw.state == 'confirm'), _('State not changed!')
|
||||
-
|
||||
Then I click on Pay Salary button
|
||||
-
|
||||
!workflow {model: hr.payslip, action: process_sheet, ref: hr_payslip_0}
|
||||
-
|
||||
I check that an order which was in the "Confirm Sheet" state has transit to "Paid Salary" state
|
||||
-
|
||||
!python {model: hr.payslip}: |
|
||||
from tools.translate import _
|
||||
payslip_brw=self.browse(cr, uid, ref("hr_payslip_0"))
|
||||
assert(payslip_brw.state == 'done'), _('State not changed!')
|
||||
@@ -45,7 +45,7 @@ class purchase_report(osv.osv):
|
||||
'product_id':fields.many2one('product.product', 'Product', readonly=True),
|
||||
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', readonly=True),
|
||||
'location_id': fields.many2one('stock.location', 'Destination', readonly=True),
|
||||
'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
|
||||
'partner_id':fields.many2one('res.partner', 'Supplier', readonly=True),
|
||||
'partner_address_id':fields.many2one('res.partner.address', 'Address Contact Name', readonly=True),
|
||||
'dest_address_id':fields.many2one('res.partner.address', 'Dest. Address Contact Name',readonly=True),
|
||||
'pricelist_id':fields.many2one('product.pricelist', 'Pricelist', readonly=True),
|
||||
|
||||
@@ -76,37 +76,39 @@
|
||||
<separator orientation="vertical"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="10" col="12">
|
||||
<group expand="1" string="Group By..." colspan="10" col="12">
|
||||
<filter string="Supplier" name="group_partner_id" icon="terp-personal" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Product" name="group_product_id" icon="terp-accessories-archiver" context="{'group_by':'product_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Responsible" name="Responsible" icon="terp-personal" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Validated by" icon="terp-personal" context="{'group_by':'validator'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Company" icon="terp-go-home" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Warehouse" icon="terp-go-home" context="{'group_by':'warehouse_id'}"/>
|
||||
<filter string="Destination" icon="terp-gtk-jump-to-ltr" context="{'group_by':'location_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="State" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Company" icon="terp-go-home" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Day" icon="terp-go-today" context="{'group_by':'day'}"/>
|
||||
<filter string="Month" icon="terp-go-month" context="{'group_by':'month'}"/>
|
||||
<filter string="Year" icon="terp-go-year" context="{'group_by':'name'}"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Extended filters..." colspan="10" col="12" groups="base.group_extended">
|
||||
<field name="user_id"/>
|
||||
<field name="validator"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="location_id"/>
|
||||
<field name="warehouse_id" widget="selection"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<newline/>
|
||||
<field name="date"/>
|
||||
<field name="date_approve"/>
|
||||
<field name="expected_date"/>
|
||||
<newline/>
|
||||
<field name="warehouse_id" widget="selection"/>
|
||||
<field name="validator" widget="selection"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="location_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<field name="nbr" sum="# of Lines"/>
|
||||
<field name="product_uom_qty" sum="# of Qty"/>
|
||||
<field name="shipped_qty_1"/>
|
||||
<field name="uom_name" invisible="not context.get('set_visible',False)"/>
|
||||
<field name="uom_name" invisible="context.get('set_visible',False)"/>
|
||||
<field name="price_average" avg="Average Price"/>
|
||||
<field name="price_total" sum="Total Price"/>
|
||||
<field name="delay" avg="Commitment Delay"/>
|
||||
|
||||
@@ -64,7 +64,7 @@ class sale_advance_payment_inv(osv.osv_memory):
|
||||
_("You cannot make an advance on a sale order \
|
||||
that is defined as 'Automatic Invoice after delivery'."))
|
||||
val = obj_lines.product_id_change(cr, uid, [], sale_adv_obj.product_id.id,
|
||||
uom = False, partner_id = sale.partner_id.id, fposition_id=sale.fiscal_position.id)
|
||||
uom = False, partner_id = sale.partner_id.id, fiscal_position = sale.fiscal_position.id)
|
||||
line_id =obj_lines.create(cr, uid, {
|
||||
'name': val['value']['name'],
|
||||
'account_id': val['value']['account_id'],
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<field name="res_model">account.invoice.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,tree</field>
|
||||
<field name="view_id" ref="view_turnover_by_month_tree"/>
|
||||
<field name="view_id" ref="view_turnover_by_month_graph"/>
|
||||
<field name="domain">[('year','ilike',time.strftime('%Y')),('user_id','=',uid)]</field>
|
||||
<field name="context">{'group_by_no_leaf':1,'group_by':['month']}</field>
|
||||
<field name="search_view_id" ref="account.view_account_invoice_report_search"/>
|
||||
|
||||
@@ -58,12 +58,6 @@ class sale_order_dates(osv.osv):
|
||||
'effective_date': fields.function(_get_effective_date, method=True, type='date', store=True,string='Effective Date'),
|
||||
}
|
||||
sale_order_dates()
|
||||
"""
|
||||
- date_commitment: min(fields.function using delay on SO lines +
|
||||
date_order)
|
||||
- date_requested: fields.date
|
||||
- Effective date: fields.function the first picking done.
|
||||
"""
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<field name="partner_id" context="{'contact_display':'partner'}"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By...">
|
||||
<group expand="1" string="Group By...">
|
||||
<filter name="group_partner" string="Partner" icon="terp-personal" context="{'group_by':'partner_id'}"/>
|
||||
<filter name="group_product" string="Product" icon="terp-accessories-archiver" context="{'group_by':'product_id'}"/>
|
||||
<filter name="group_picking" string="Packing" icon="terp-accessories-archiver" context="{'group_by':'picking_id'}"/>
|
||||
|
||||
@@ -37,6 +37,7 @@ class report_stock_picking(osv.osv):
|
||||
'product_uos_qty': fields.float('# of Products', readonly=True),
|
||||
'product_id': fields.many2one('product.product', 'Product', readonly=True),
|
||||
'date': fields.date('Date', readonly=True),
|
||||
'avg_days_late': fields.float('Avg Due Days', digits=(16,2), readonly=True, group_operator="avg"),
|
||||
'avg_days_to_deliver': fields.float('Avg Days to Deliver', digits=(16,2), readonly=True, group_operator="avg",
|
||||
help="Number of Avg Days to deliver"),
|
||||
'state': fields.selection([('draft', 'Draft'),('auto', 'Waiting'),('confirmed', 'Confirmed'),('assigned', 'Available'),('done', 'Done'),('cancel', 'Cancelled')], 'State'),
|
||||
@@ -71,8 +72,7 @@ class report_stock_picking(osv.osv):
|
||||
sp.address_id as partner_id,
|
||||
to_date(to_char(sp.create_date, 'MM-dd-YYYY'),'MM-dd-YYYY') as date,
|
||||
count(sm.id) as nbr,
|
||||
count(distinct sp.id) as nbp,
|
||||
sum(sm.product_qty) as product_qty,
|
||||
sum(sm.product_qty*u.factor) as product_qty,
|
||||
sum(sm.product_uos_qty) as product_uos_qty,
|
||||
sm.product_id as product_id,
|
||||
sm.location_dest_id as location_dest_id,
|
||||
@@ -83,9 +83,11 @@ class report_stock_picking(osv.osv):
|
||||
sp.invoice_state,
|
||||
sp.company_id as company_id,
|
||||
avg(extract('epoch' from (sp.date_done-sp.create_date)))/(3600*24) as avg_days_to_deliver,
|
||||
avg(extract('epoch' from (sp.date_done-sp.min_date)))/(3600*24) as avg_days_late,
|
||||
sp.state
|
||||
from stock_move as sm
|
||||
left join stock_picking as sp ON (sm.picking_id=sp.id)
|
||||
from stock_picking as sp
|
||||
Inner join stock_move as sm ON (sm.picking_id=sp.id)
|
||||
Inner join product_uom u on (u.id=sm.product_uom)
|
||||
group by sp.type,
|
||||
sp.create_date,
|
||||
sp.address_id,
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="invoice_state" invisible="1"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="product_qty" sum="# of Products" />
|
||||
<field name="nbp" sum="# of Pickings" />
|
||||
<field name="nbr" sum="# of Lines" />
|
||||
<field name="avg_days_to_deliver" avg='Avg Days to Deliver'/>
|
||||
<field name="product_qty" sum="# of Products" />
|
||||
<field name="avg_days_to_deliver" avg='Avg Days to Deliver'/>
|
||||
<field name="avg_days_late" avg='Avg Due Days'/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
@@ -69,37 +69,39 @@
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Todo" icon="terp-gtk-go-back-rtl" domain="[('state','in',('draft','auto','confirmed','assigned'))]"/>
|
||||
<filter string="Done" icon="terp-dialog-close" domain="[('state','=','done')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="partner_id"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By...">
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="Partner" name="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<filter string="Shipping Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Shipping Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
<filter string="Invoice Status" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'invoice_state'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Day" icon="terp-go-today" domain="[]" context="{'group_by':'day'}"/>
|
||||
<filter string="Month" icon="terp-go-month" domain="[]" context="{'group_by':'month'}"/>
|
||||
<filter string="Year" icon="terp-go-year" domain="[]" context="{'group_by':'year'}"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="0" string="Extended options..." groups="base.group_extended">
|
||||
<field name="type"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="min_date"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="max_date"/>
|
||||
<newline/>
|
||||
<field name="product_id"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="type"/>
|
||||
<field name="invoice_state"/>
|
||||
<separator orientation="vertical"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
|
||||
<newline/>
|
||||
<field name="order_date"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="date_done"/>
|
||||
<field name="min_date"/>
|
||||
<field name="max_date"/>
|
||||
</group>
|
||||
|
||||
</search>
|
||||
|
||||
@@ -20,15 +20,13 @@
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import time
|
||||
|
||||
from osv import fields, osv
|
||||
from tools import config
|
||||
from tools.translate import _
|
||||
import math
|
||||
import netsvc
|
||||
import time
|
||||
import tools
|
||||
|
||||
import decimal_precision as dp
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user