[MERGE] merge from dev3
bzr revid: ara@tinyerp.com-20110117124103-zmjdbyc4x05w8fw1
This commit is contained in:
commit
d639116333
|
@ -1130,7 +1130,7 @@ class account_move(osv.osv):
|
|||
'to_check': fields.boolean('To Review', help='Check this box if you are unsure of that journal entry and if you want to note it as \'to be reviewed\' by an accounting expert.'),
|
||||
'partner_id': fields.related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store=True),
|
||||
'amount': fields.function(_amount_compute, method=True, string='Amount', digits_compute=dp.get_precision('Account'), type='float', fnct_search=_search_amount),
|
||||
'date': fields.date('Date', required=True, states={'posted':[('readonly',True)]}),
|
||||
'date': fields.date('Date', required=True, states={'posted':[('readonly',True)]}, select=True),
|
||||
'narration':fields.text('Narration'),
|
||||
'company_id': fields.related('journal_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True),
|
||||
}
|
||||
|
|
|
@ -494,12 +494,12 @@ class account_move_line(osv.osv):
|
|||
'journal_id': fields.many2one('account.journal', 'Journal', required=True, select=1),
|
||||
'blocked': fields.boolean('Litigation', help="You can check this box to mark this journal item as a litigation with the associated partner"),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', select=1, ondelete='restrict'),
|
||||
'date_maturity': fields.date('Due date', help="This field is used for payable and receivable journal entries. You can put the limit date for the payment of this line."),
|
||||
'date': fields.related('move_id','date', string='Effective date', type='date', required=True,
|
||||
'date_maturity': fields.date('Due date', select=True ,help="This field is used for payable and receivable journal entries. You can put the limit date for the payment of this line."),
|
||||
'date': fields.related('move_id','date', string='Effective date', type='date', required=True, select=True,
|
||||
store = {
|
||||
'account.move': (_get_move_lines, ['date'], 20)
|
||||
}),
|
||||
'date_created': fields.date('Creation date'),
|
||||
'date_created': fields.date('Creation date', select=True),
|
||||
'analytic_lines': fields.one2many('account.analytic.line', 'move_id', 'Analytic lines'),
|
||||
'centralisation': fields.selection([('normal','Normal'),('credit','Credit Centralisation'),('debit','Debit Centralisation')], 'Centralisation', size=6),
|
||||
'balance': fields.function(_balance, fnct_search=_balance_search, method=True, string='Balance'),
|
||||
|
|
|
@ -211,8 +211,8 @@ class account_invoice(osv.osv):
|
|||
\n* The \'Open\' state is used when user create invoice,a invoice number is generated.Its in open state till user does not pay invoice. \
|
||||
\n* The \'Paid\' state is set automatically when invoice is paid.\
|
||||
\n* The \'Cancelled\' state is used when user cancel invoice.'),
|
||||
'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, help="Keep empty to use the current date"),
|
||||
'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]},
|
||||
'date_invoice': fields.date('Invoice Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True, help="Keep empty to use the current date"),
|
||||
'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, select=True,
|
||||
help="If you use payment terms, the due date will be computed automatically at the generation "\
|
||||
"of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}),
|
||||
|
|
|
@ -628,7 +628,7 @@ class account_analytic_account_summary_month(osv.osv):
|
|||
tools.sql.drop_view_if_exists(cr, 'account_analytic_analysis_summary_month')
|
||||
cr.execute('CREATE VIEW account_analytic_analysis_summary_month AS (' \
|
||||
'SELECT ' \
|
||||
'(TO_NUMBER(TO_CHAR(d.month, \'YYYYMM\'), \'999999\') + (d.account_id * 1000000))::integer AS id, ' \
|
||||
'(TO_NUMBER(TO_CHAR(d.month, \'YYYYMM\'), \'999999\') + (d.account_id * 1000000::bigint))::bigint AS id, ' \
|
||||
'd.account_id AS account_id, ' \
|
||||
'TO_CHAR(d.month, \'Mon YYYY\') AS month, ' \
|
||||
'TO_NUMBER(TO_CHAR(d.month, \'YYYYMM\'), \'999999\') AS month_id, ' \
|
||||
|
|
|
@ -54,7 +54,7 @@ class account_move_line(osv.osv):
|
|||
_inherit = 'account.move.line'
|
||||
_columns = {
|
||||
'followup_line_id': fields.many2one('account_followup.followup.line', 'Follow-up Level'),
|
||||
'followup_date': fields.date('Latest Follow-up'),
|
||||
'followup_date': fields.date('Latest Follow-up', select=True),
|
||||
}
|
||||
|
||||
account_move_line()
|
||||
|
|
|
@ -181,7 +181,7 @@ class account_voucher(osv.osv):
|
|||
('receipt','Receipt'),
|
||||
],'Default Type', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'name':fields.char('Memo', size=256, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'date':fields.date('Date', readonly=True, states={'draft':[('readonly',False)]}, help="Effective date for accounting entries"),
|
||||
'date':fields.date('Date', readonly=True, select=True, states={'draft':[('readonly',False)]}, help="Effective date for accounting entries"),
|
||||
'journal_id':fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'account_id':fields.many2one('account.account', 'Account', required=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'line_ids':fields.one2many('account.voucher.line','voucher_id','Voucher Lines', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
|
@ -218,7 +218,7 @@ class account_voucher(osv.osv):
|
|||
],'Payment', select=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'tax_id':fields.many2one('account.tax', 'Tax', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'pre_line':fields.boolean('Previous Payments ?', required=False),
|
||||
'date_due': fields.date('Due Date', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'date_due': fields.date('Due Date', readonly=True, select=True, states={'draft':[('readonly',False)]}),
|
||||
'payment_option':fields.selection([
|
||||
('without_writeoff', 'Keep Open'),
|
||||
('with_writeoff', 'Reconcile with Write-Off'),
|
||||
|
|
|
@ -60,7 +60,7 @@ class account_analytic_account(osv.osv):
|
|||
return res
|
||||
|
||||
where_date = ''
|
||||
where_clause_args = [tuple(child_ids)]
|
||||
where_clause_args = [tuple(child_ids)]
|
||||
if context.get('from_date', False):
|
||||
where_date += " AND l.date >= %s"
|
||||
where_clause_args += [context['from_date']]
|
||||
|
@ -71,20 +71,20 @@ class account_analytic_account(osv.osv):
|
|||
SELECT a.id,
|
||||
sum(
|
||||
CASE WHEN l.amount > 0
|
||||
THEN l.amount
|
||||
THEN l.amount
|
||||
ELSE 0.0
|
||||
END
|
||||
) as debit,
|
||||
sum(
|
||||
CASE WHEN l.amount < 0
|
||||
THEN -l.amount
|
||||
ELSE 0.0
|
||||
ELSE 0.0
|
||||
END
|
||||
) as credit,
|
||||
COALESCE(SUM(l.amount),0) AS balance,
|
||||
COALESCE(SUM(l.unit_amount),0) AS quantity
|
||||
FROM account_analytic_account a
|
||||
LEFT JOIN account_analytic_line l ON (a.id = l.account_id)
|
||||
FROM account_analytic_account a
|
||||
LEFT JOIN account_analytic_line l ON (a.id = l.account_id)
|
||||
WHERE a.id IN %s
|
||||
""" + where_date + """
|
||||
GROUP BY a.id""", where_clause_args)
|
||||
|
@ -128,7 +128,7 @@ class account_analytic_account(osv.osv):
|
|||
'contact_id': fields.many2one('res.partner.address', 'Contact'),
|
||||
'user_id': fields.many2one('res.users', 'Account Manager'),
|
||||
'date_start': fields.date('Date Start'),
|
||||
'date': fields.date('Date End'),
|
||||
'date': fields.date('Date End', select=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts.
|
||||
'state': fields.selection([('draft','Draft'),('open','Open'), ('pending','Pending'),('cancelled', 'Cancelled'),('close','Closed'),('template', 'Template')], 'State', required=True,
|
||||
help='* When an account is created its in \'Draft\' state.\
|
||||
|
@ -230,7 +230,7 @@ class account_analytic_line(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'name': fields.char('Description', size=256, required=True),
|
||||
'date': fields.date('Date', required=True, select=1),
|
||||
'date': fields.date('Date', required=True, select=True),
|
||||
'amount': fields.float('Amount', required=True, help='Calculated by multiplying the quantity and the price given in the Product\'s cost price. Always expressed in the company main currency.', digits_compute=dp.get_precision('Account')),
|
||||
'unit_amount': fields.float('Quantity', help='Specifies the amount of quantity to count.'),
|
||||
'account_id': fields.many2one('account.analytic.account', 'Analytic Account', required=True, ondelete='cascade', select=True, domain=[('type','<>','view')]),
|
||||
|
|
|
@ -96,6 +96,8 @@ def _record_objects(self, cr, uid, data, context):
|
|||
if '_auto' in dir(obj_pool):
|
||||
if not obj_pool._auto:
|
||||
continue
|
||||
elif '_log_access' not in dir(obj_pool):
|
||||
search_condition = []
|
||||
search_ids=obj_pool.search(cr,uid,search_condition)
|
||||
for s_id in search_ids:
|
||||
args=(cr.dbname,uid,obj_name,'copy',s_id,{},context)
|
||||
|
|
|
@ -23,33 +23,15 @@ from osv import fields, osv
|
|||
from tools.translate import _
|
||||
from tools import ustr
|
||||
|
||||
class report_creator(osv.osv):
|
||||
class report_result(osv.osv):
|
||||
"""
|
||||
Report Creator
|
||||
"""
|
||||
_name = "base_report_creator.report"
|
||||
_name = "base_report_creator_report.result"
|
||||
_description = "Report"
|
||||
model_set_id = False
|
||||
#
|
||||
# Should request only used fields
|
||||
#
|
||||
def export_data(self, cr, uid, ids, fields_to_export, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
data_l = self.read(cr, uid, ids, ['sql_query'], context=context)
|
||||
final_datas = []
|
||||
#start Loop
|
||||
for record in data_l:
|
||||
datas = []
|
||||
for key in fields_to_export:
|
||||
value = record.get(key,'')
|
||||
if isinstance(value, tuple):
|
||||
datas.append(ustr(value[1]))
|
||||
else:
|
||||
datas.append(ustr(value))
|
||||
final_datas += [datas]
|
||||
#End Loop
|
||||
return {'datas': final_datas}
|
||||
|
||||
def fields_get(self, cr, user, fields=None, context=None):
|
||||
"""
|
||||
|
@ -64,9 +46,9 @@ class report_creator(osv.osv):
|
|||
|
||||
data = context and context.get('report_id', False) or False
|
||||
if (not context) or 'report_id' not in context:
|
||||
return super(report_creator, self).fields_get(cr, user, fields, context)
|
||||
return super(report_result, self).fields_get(cr, user, fields, context)
|
||||
if data:
|
||||
report = self.browse(cr, user, data)
|
||||
report = self.pool.get('base_report_creator.report').browse(cr, user, data,context=context)
|
||||
models = {}
|
||||
#Start Loop
|
||||
for model in report.model_ids:
|
||||
|
@ -80,12 +62,8 @@ class report_creator(osv.osv):
|
|||
i += 1
|
||||
else:
|
||||
fields['column_count'] = {'readonly': True, 'type': 'integer', 'string': 'Count', 'size': 64, 'name': 'column_count'}
|
||||
|
||||
return fields
|
||||
|
||||
#
|
||||
# Should Call self.fields_get !
|
||||
#
|
||||
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
"""
|
||||
Overrides orm field_view_get.
|
||||
|
@ -98,8 +76,8 @@ class report_creator(osv.osv):
|
|||
|
||||
data = context and context.get('report_id', False) or False
|
||||
if (not context) or 'report_id' not in context:
|
||||
return super(report_creator, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
|
||||
report = self.browse(cr, user, data)
|
||||
return super(report_result, self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
|
||||
report = self.pool.get('base_report_creator.report').browse(cr, user, context.get('report_id'), context=context)
|
||||
models = {}
|
||||
for model in report.model_ids:
|
||||
models[model.model] = self.pool.get(model.model).fields_get(cr, user, context=context)
|
||||
|
@ -192,31 +170,11 @@ class report_creator(osv.osv):
|
|||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
data = context.get('report_id', False)
|
||||
res = super(report_creator, self).read(cr, user, ids, fields, context, load)
|
||||
if (not context) or 'report_id' not in context:
|
||||
return res
|
||||
wp = ''
|
||||
for data in res:
|
||||
if not data.get('sql_query'):
|
||||
return res
|
||||
if self.model_set_id:
|
||||
wp = [self._id_get(cr, user, data, context) + (' in (%s)' % (','.join(map(lambda x: "'" + str(x) + "'", ids))))]
|
||||
cr.execute(data['sql_query'])
|
||||
res = cr.dictfetchall()
|
||||
fields_get = self.fields_get(cr, user, None, context)
|
||||
for r in res:
|
||||
for k in r:
|
||||
r[k] = r[k] or False
|
||||
field_dict = fields_get.get(k)
|
||||
field_type = field_dict and field_dict.get('type', False) or False
|
||||
if field_type and field_type == 'many2one':
|
||||
if r[k] == False:
|
||||
continue
|
||||
related_name = self.pool.get(field_dict.get('relation')).name_get(cr, user, [r[k]], context)[0]
|
||||
r[k] = related_name
|
||||
|
||||
return res
|
||||
report_id = context.get('active_id', False)
|
||||
report = self.pool.get('base_report_creator.report').browse(cr, user, context.get('report_id'), context=context)
|
||||
cr.execute(report.sql_query)
|
||||
result = cr.dictfetchall()
|
||||
return result
|
||||
|
||||
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
"""
|
||||
|
@ -231,9 +189,9 @@ class report_creator(osv.osv):
|
|||
context_id = context.get('report_id', False)
|
||||
|
||||
if (not context) or 'report_id' not in context:
|
||||
return super(report_creator, self).search(cr, user, args, offset, limit, order, context, count)
|
||||
return {}
|
||||
if context_id:
|
||||
report = self.browse(cr, user, context_id)
|
||||
report = self.pool.get('base_report_creator.report').browse(cr, user, context_id, context=context)
|
||||
i = 0
|
||||
fields = {}
|
||||
for f in report.field_ids:
|
||||
|
@ -254,10 +212,42 @@ class report_creator(osv.osv):
|
|||
ctx = context or {}
|
||||
ctx['getid'] = True
|
||||
sql_query = report.sql_query
|
||||
cr.execute(sql_query, newargs2)
|
||||
cr.execute(sql_query) # TODO: FILTER
|
||||
result = cr.fetchall()
|
||||
return map(lambda x: x[0], result)
|
||||
|
||||
report_result()
|
||||
|
||||
|
||||
class report_creator(osv.osv):
|
||||
"""
|
||||
Report Creator
|
||||
"""
|
||||
_name = "base_report_creator.report"
|
||||
_description = "Report"
|
||||
model_set_id = False
|
||||
#
|
||||
# Should request only used fields
|
||||
#
|
||||
def export_data(self, cr, uid, ids, fields_to_export, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
data_l = self.read(cr, uid, ids, ['sql_query'], context=context)
|
||||
final_datas = []
|
||||
#start Loop
|
||||
for record in data_l:
|
||||
datas = []
|
||||
for key in fields_to_export:
|
||||
value = record.get(key,'')
|
||||
if isinstance(value, tuple):
|
||||
datas.append(ustr(value[1]))
|
||||
else:
|
||||
datas.append(ustr(value))
|
||||
final_datas += [datas]
|
||||
#End Loop
|
||||
return {'datas': final_datas}
|
||||
|
||||
|
||||
def _path_get(self, cr, uid, models, filter_ids=[]):
|
||||
"""
|
||||
@param cr: the current row, from the database cursor,
|
||||
|
@ -465,7 +455,7 @@ class report_creator(osv.osv):
|
|||
'name': rep.name,
|
||||
'view_type': 'form',
|
||||
'view_mode': view_mode,
|
||||
'res_model': 'base_report_creator.report',
|
||||
'res_model': 'base_report_creator_report.result',
|
||||
'type': 'ir.actions.act_window',
|
||||
'context': "{'report_id':%d}" % (rep.id,),
|
||||
'nodestroy': True,
|
||||
|
@ -596,3 +586,4 @@ class report_creator_filter(osv.osv):
|
|||
}
|
||||
report_creator_filter()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ appropriate staff, and make sure all future correspondence gets to the right
|
|||
place.
|
||||
|
||||
The CRM module has a email gateway for the synchronisation interface
|
||||
between mails and OpenERP.
|
||||
between mails and OpenERP.
|
||||
Create dashboard for CRM that includes:
|
||||
* My Leads (list)
|
||||
* Leads by Stage (graph)
|
||||
|
@ -95,6 +95,7 @@ Create dashboard for CRM that includes:
|
|||
|
||||
'crm_meeting_view.xml',
|
||||
'crm_meeting_menu.xml',
|
||||
'crm_meeting_shortcut_data.xml',
|
||||
|
||||
'crm_phonecall_view.xml',
|
||||
'crm_phonecall_menu.xml',
|
||||
|
@ -106,12 +107,12 @@ Create dashboard for CRM that includes:
|
|||
'report/crm_phonecall_report_view.xml',
|
||||
|
||||
'process/crm_configuration_process.xml',
|
||||
'crm_installer_view.xml',
|
||||
|
||||
'crm_installer_view.xml',
|
||||
|
||||
'res_partner_view.xml',
|
||||
'board_crm_view.xml',
|
||||
'board_crm_statistical_view.xml',
|
||||
|
||||
|
||||
],
|
||||
'demo_xml': [
|
||||
'crm_demo.xml',
|
||||
|
|
|
@ -92,12 +92,6 @@
|
|||
action="crm_case_categ_meet" parent="menu_meeting_sale"
|
||||
sequence="1" />
|
||||
|
||||
<record id="ir_ui_view_sc_calendar0" model="ir.ui.view_sc">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="res_id" ref="crm.menu_crm_case_categ_meet"/>
|
||||
</record>
|
||||
<record id="action_view_attendee_form" model="ir.actions.act_window">
|
||||
<field name="name">Meeting Invitations</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="ir_ui_view_sc_calendar0" model="ir.ui.view_sc">
|
||||
<field name="name">Meetings</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="res_id" ref="crm.menu_crm_case_categ_meet"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -146,7 +146,7 @@ class hr_employee(osv.osv):
|
|||
'marital': fields.many2one('hr.employee.marital.status', 'Marital Status'),
|
||||
'department_id':fields.many2one('hr.department', 'Department'),
|
||||
'address_id': fields.many2one('res.partner.address', 'Working Address'),
|
||||
'address_home_id': fields.many2one('res.partner.address', 'Home Address'),
|
||||
'address_home_id': fields.many2one('res.partner.address', 'Home Address', domain="[('partner_id', '!=', False)]"),
|
||||
'partner_id': fields.related('address_home_id', 'partner_id', type='many2one', relation='res.partner', readonly=True, help="Partner that is related to the current employee. Accounting transaction will be written on this partner belongs to employee."),
|
||||
'bank_account_id':fields.many2one('res.partner.bank', 'Bank Account', domain="[('partner_id','=',partner_id)]", help="Employee bank salary account"),
|
||||
'work_phone': fields.char('Work Phone', size=32, readonly=False),
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(4,ref('base.group_hr_manager'))]"/>
|
||||
</record>
|
||||
<record id="property_rule_attendace_employee" model="ir.rule">
|
||||
<field name="name">Employee Attendance</field>
|
||||
<field model="ir.model" name="model_id" ref="model_hr_attendance"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
|
|
|
@ -143,7 +143,7 @@ class hr_evaluation(osv.osv):
|
|||
_description = "Employee Evaluation"
|
||||
_rec_name = 'employee_id'
|
||||
_columns = {
|
||||
'date': fields.date("Evaluation Deadline", required=True),
|
||||
'date': fields.date("Evaluation Deadline", required=True, select=True),
|
||||
'employee_id': fields.many2one('hr.employee', "Employee", required=True),
|
||||
'note_summary': fields.text('Evaluation Summary'),
|
||||
'note_action': fields.text('Action Plan',
|
||||
|
@ -165,7 +165,7 @@ class hr_evaluation(osv.osv):
|
|||
('done','Done'),
|
||||
('cancel','Cancelled'),
|
||||
], 'State', required=True, readonly=True),
|
||||
'date_close': fields.date('Ending Date'),
|
||||
'date_close': fields.date('Ending Date', select=True),
|
||||
'progress': fields.float("Progress"),
|
||||
}
|
||||
_defaults = {
|
||||
|
|
|
@ -60,12 +60,12 @@ class hr_expense_expense(osv.osv):
|
|||
'name': fields.char('Description', size=128, required=True),
|
||||
'id': fields.integer('Sheet ID', readonly=True),
|
||||
'ref': fields.char('Reference', size=32),
|
||||
'date': fields.date('Date'),
|
||||
'date': fields.date('Date', select=True),
|
||||
'journal_id': fields.many2one('account.journal', 'Force Journal', help = "The journal used when the expense is invoiced"),
|
||||
'employee_id': fields.many2one('hr.employee', "Employee", required=True),
|
||||
'user_id': fields.many2one('res.users', 'User', required=True),
|
||||
'date_confirm': fields.date('Confirmation Date', help = "Date of the confirmation of the sheet expense. It's filled when the button Confirm is pressed."),
|
||||
'date_valid': fields.date('Validation Date', help = "Date of the acceptation of the sheet expense. It's filled when the button Accept is pressed."),
|
||||
'date_confirm': fields.date('Confirmation Date', select=True, help = "Date of the confirmation of the sheet expense. It's filled when the button Confirm is pressed."),
|
||||
'date_valid': fields.date('Validation Date', select=True, help = "Date of the acceptation of the sheet expense. It's filled when the button Accept is pressed."),
|
||||
'user_valid': fields.many2one('res.users', 'Validation User'),
|
||||
'account_move_id': fields.many2one('account.move', 'Ledger Posting'),
|
||||
'line_ids': fields.one2many('hr.expense.line', 'expense_id', 'Expense Lines', readonly=True, states={'draft':[('readonly',False)]} ),
|
||||
|
@ -251,13 +251,17 @@ class hr_expense_line(osv.osv):
|
|||
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
res['name'] = product.name
|
||||
# Compute based on pricetype of employee company
|
||||
ctx['currency_id'] = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.currency_id.id
|
||||
amount_unit = product.price_get('standard_price', ctx)[product.id]
|
||||
res['unit_amount'] = amount_unit
|
||||
employee = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context)
|
||||
if employee.user_id:
|
||||
ctx['currency_id'] = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.currency_id.id
|
||||
amount_unit = product.price_get('standard_price', ctx)[product.id]
|
||||
res['unit_amount'] = amount_unit
|
||||
else:
|
||||
res['unit_amount'] = product.standard_price
|
||||
if not uom_id:
|
||||
res['uom_id'] = product.uom_id.id
|
||||
return {'value': res}
|
||||
|
||||
hr_expense_line()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -14,6 +14,12 @@
|
|||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(4,ref('base.group_hr_manager'))]"/>
|
||||
</record>
|
||||
<record id="property_rule_expense_employee" model="ir.rule">
|
||||
<field name="name">Employee Expense</field>
|
||||
<field model="ir.model" name="model_id" ref="model_hr_expense_expense"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(6,0,[ref('base.group_hr_manager')])]"/>
|
||||
</record>
|
||||
<record id="property_rule_holidays_employee" model="ir.rule">
|
||||
<field name="name">Employee Holidays</field>
|
||||
<field model="ir.model" name="model_id" ref="model_hr_holidays"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -126,7 +126,7 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
'partner_id': fields.many2one('res.partner', 'Partner'),
|
||||
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
|
||||
domain="[('partner_id','=',partner_id)]"),
|
||||
'create_date': fields.datetime('Creation Date', readonly=True),
|
||||
'create_date': fields.datetime('Creation Date', readonly=True, select=True),
|
||||
'write_date': fields.datetime('Update Date', readonly=True),
|
||||
'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage'),
|
||||
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True,
|
||||
|
@ -137,8 +137,8 @@ class hr_applicant(crm.crm_case, osv.osv):
|
|||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'user_id': fields.many2one('res.users', 'Responsible'),
|
||||
# Applicant Columns
|
||||
'date_closed': fields.datetime('Closed', readonly=True),
|
||||
'date_open': fields.datetime('Opened', readonly=True),
|
||||
'date_closed': fields.datetime('Closed', readonly=True, select=True),
|
||||
'date_open': fields.datetime('Opened', readonly=True, select=True),
|
||||
'date': fields.datetime('Date'),
|
||||
'date_action': fields.date('Next Action Date'),
|
||||
'title_action': fields.char('Next Action', size=64),
|
||||
|
|
|
@ -50,7 +50,7 @@ class report_custom(report_rml):
|
|||
emp_obj = pooler.get_pool(cr.dbname).get('hr.employee')
|
||||
user_id = emp_obj.browse(cr, uid, emp_id).user_id.id
|
||||
empl_name = emp_obj.browse(cr, uid, emp_id).name
|
||||
|
||||
|
||||
# Computing the dates (start of month: som, and end of month: eom)
|
||||
som = datetime.date(data['form']['year'], data['form']['month'], 1)
|
||||
eom = som + datetime.timedelta(lengthmonth(som.year, som.month))
|
||||
|
|
|
@ -262,7 +262,7 @@ class hr_timesheet_sheet(osv.osv):
|
|||
'user_id': fields.related('employee_id', 'user_id', type="many2one", relation="res.users", store=True, string="User", required=False, readonly=True),#fields.many2one('res.users', 'User', required=True, select=1, states={'confirm':[('readonly', True)], 'done':[('readonly', True)]}),
|
||||
'date_from': fields.date('Date from', required=True, select=1, readonly=True, states={'new':[('readonly', False)]}),
|
||||
'date_to': fields.date('Date to', required=True, select=1, readonly=True, states={'new':[('readonly', False)]}),
|
||||
'date_current': fields.date('Current date', required=True),
|
||||
'date_current': fields.date('Current date', required=True, select=1),
|
||||
'timesheet_ids' : one2many_mod('hr.analytic.timesheet', 'sheet_id',
|
||||
'Timesheet lines', domain=[('date', '=', time.strftime('%Y-%m-%d'))],
|
||||
readonly=True, states={
|
||||
|
|
|
@ -342,7 +342,7 @@ class mrp_bom(osv.osv):
|
|||
if context is None:
|
||||
context = {}
|
||||
bom_data = self.read(cr, uid, id, [], context=context)
|
||||
default.update({'name': bom_data['name'] + ' ' + _('Copy')})
|
||||
default.update({'name': bom_data['name'] + ' ' + _('Copy'), 'bom_id':False})
|
||||
return super(mrp_bom, self).copy_data(cr, uid, id, default, context=context)
|
||||
|
||||
mrp_bom()
|
||||
|
@ -444,7 +444,7 @@ class mrp_production(osv.osv):
|
|||
'bom_id': fields.many2one('mrp.bom', 'Bill of Material', domain=[('bom_id','=',False)]),
|
||||
'routing_id': fields.many2one('mrp.routing', string='Routing', on_delete='set null', help="The list of operations (list of work centers) to produce the finished product. The routing is mainly used to compute work center costs during operations and to plan future loads on work centers based on production plannification."),
|
||||
|
||||
'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True,
|
||||
'picking_id': fields.many2one('stock.picking', 'Picking list', readonly=True, ondelete="restrict",
|
||||
help="This is the internal picking list that brings the finished product to the production plan"),
|
||||
'move_prod_id': fields.many2one('stock.move', 'Move product', readonly=True),
|
||||
'move_lines': fields.many2many('stock.move', 'mrp_production_move_ids', 'production_id', 'move_id', 'Products to Consume', domain=[('state','not in', ('done', 'cancel'))], states={'done':[('readonly',True)]}),
|
||||
|
@ -602,12 +602,18 @@ class mrp_production(osv.osv):
|
|||
workcenter_line_obj.create(cr, uid, line)
|
||||
return len(results)
|
||||
|
||||
def action_cancel(self, cr, uid, ids):
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
""" Cancels the production order and related stock moves.
|
||||
@return: True
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
move_obj = self.pool.get('stock.move')
|
||||
for production in self.browse(cr, uid, ids):
|
||||
for production in self.browse(cr, uid, ids, context=context):
|
||||
if production.state == 'confirmed' and production.picking_id.state not in ('draft', 'cancel'):
|
||||
raise osv.except_osv(
|
||||
_('Could not cancel manufacturing order !'),
|
||||
_('You must first cancel related internal picking attached to this manufacturing order.'))
|
||||
if production.move_created_ids:
|
||||
move_obj.action_cancel(cr, uid, [x.id for x in production.move_created_ids])
|
||||
move_obj.action_cancel(cr, uid, [x.id for x in production.move_lines])
|
||||
|
@ -664,7 +670,7 @@ class mrp_production(osv.osv):
|
|||
"""
|
||||
stock_mov_obj = self.pool.get('stock.move')
|
||||
production = self.browse(cr, uid, production_id, context=context)
|
||||
|
||||
|
||||
final_product_todo = []
|
||||
|
||||
produced_qty = 0
|
||||
|
@ -708,9 +714,9 @@ class mrp_production(osv.osv):
|
|||
if production_mode == 'consume_produce':
|
||||
# To produce remaining qty of final product
|
||||
vals = {'state':'confirmed'}
|
||||
final_product_todo = [x.id for x in production.move_created_ids]
|
||||
#final_product_todo = [x.id for x in production.move_created_ids]
|
||||
#stock_mov_obj.write(cr, uid, final_product_todo, vals)
|
||||
stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
|
||||
#stock_mov_obj.action_confirm(cr, uid, final_product_todo, context)
|
||||
produced_products = {}
|
||||
for produced_product in production.move_created_ids2:
|
||||
if produced_product.scrapped:
|
||||
|
|
|
@ -343,6 +343,54 @@
|
|||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
</tree>
|
||||
<form string="Bill of Material">
|
||||
<group colspan="4" col="6">
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, name)" select="1"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="code" select="1" string="Reference" groups="base.group_extended"/>
|
||||
<newline/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom"/>
|
||||
<field name="routing_id" groups="base.group_extended"/>
|
||||
<newline/>
|
||||
<field name="product_uos_qty" groups="product.group_uos" />
|
||||
<field name="product_uos" groups="product.group_uos"/>
|
||||
<newline/>
|
||||
<field name="type" groups="base.group_extended"/>
|
||||
<field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/>
|
||||
</group>
|
||||
<group groups="base.group_extended">
|
||||
<notebook colspan="4">
|
||||
<page string="Components">
|
||||
<field colspan="4" name="bom_lines" nolabel="1" widget="one2many_list">
|
||||
<tree string="Components" editable="bottom">
|
||||
<field name="product_id" on_change="onchange_product_id(product_id, name)" select="1"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom"/>
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Revisions" groups="base.group_extended" attrs="{'invisible': [('bom_id','!=',False)]}">
|
||||
<field colspan="4" name="revision_ids" nolabel="1" widget="one2many_list"/>
|
||||
</page>
|
||||
<page string="Properties" groups="base.group_extended">
|
||||
<field name="position"/>
|
||||
<field name="active"/>
|
||||
<field name="sequence"/>
|
||||
<field name="bom_id"/>
|
||||
|
||||
<field name="date_start"/>
|
||||
<field name="date_stop"/>
|
||||
<field name="product_rounding"/>
|
||||
<field name="product_efficiency" groups="base.group_extended"/>
|
||||
<field colspan="4" name="property_ids" nolabel="2" groups="base.group_extended"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Revisions" groups="base.group_extended" attrs="{'invisible': [('bom_id','!=',False)]}">
|
||||
|
@ -412,6 +460,28 @@
|
|||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="mrp_bom_component_tree_view" model="ir.ui.view">
|
||||
<field name="name">mrp.bom.component.tree</field>
|
||||
<field name="model">mrp.bom</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="field_parent">child_complete_ids</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="BoM Structure" colors="blue:method">
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="name" string="Component Name"/>
|
||||
<field name="code"/>
|
||||
<field name="product_id" string="Component Product"/>
|
||||
<field name="bom_id"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="product_uom"/>
|
||||
<field name="type"/>
|
||||
<field name="method" groups="base.group_extended"/>
|
||||
<field name="routing_id" groups="base.group_extended"/>
|
||||
<field name="date_start" groups="base.group_extended"/>
|
||||
<field name="date_stop" groups="base.group_extended"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="mrp_bom_form_action" model="ir.actions.act_window">
|
||||
<field name="name">Bill of Materials</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
|
@ -426,6 +496,7 @@
|
|||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">mrp.bom</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="mrp_bom_component_tree_view"/>
|
||||
<field name="domain">[('bom_id','!=',False)]</field>
|
||||
<field name="help">Bills of materials components are components and sub-products used to create master bills of materials. Use this menu to search in which BoM a specific component is used.</field>
|
||||
</record>
|
||||
|
@ -616,7 +687,6 @@
|
|||
<field name="product_id" readonly="1"/>
|
||||
<field name="product_qty" readonly="1" string="Qty"/>
|
||||
<field name="product_uom" readonly="1" string="UOM"/>
|
||||
<field name="location_dest_id" readonly="1" string="Destination Loc."/>
|
||||
<field name="prodlot_id" context="{'product_id': product_id}"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="scrapped" invisible="1"/>
|
||||
|
@ -630,7 +700,8 @@
|
|||
<separator colspan="4"/>
|
||||
<group col="9" colspan="4">
|
||||
<field name="state"/>
|
||||
<button name="button_cancel" states="draft,ready,confirmed,in_production,picking_except" string="Cancel" icon="gtk-stop"/>
|
||||
<button name="button_cancel" states="draft,ready,in_production,picking_except" string="Cancel" icon="gtk-stop"/>
|
||||
<button name="action_cancel" type="object" states="confirmed" string="Cancel" icon="gtk-stop"/>
|
||||
<button name="button_confirm" states="draft" string="Confirm Production" icon="gtk-apply"/>
|
||||
<button name="button_produce" states="ready" string="Start Production" icon="terp-gtk-jump-to-ltr"/>
|
||||
<button name="%(act_mrp_product_produce)d" states="in_production" string="Produce" icon="gtk-ok" type="action"/>
|
||||
|
@ -645,7 +716,6 @@
|
|||
<field name="product_id" />
|
||||
<field name="product_qty" string="Qty"/>
|
||||
<field name="product_uom" string="UOM"/>
|
||||
<field name="location_id" string="Source Loc." />
|
||||
<field name="state" invisible="1"/>
|
||||
<button name="%(stock.action_partial_move_server)d"
|
||||
string="Partial"
|
||||
|
@ -680,7 +750,7 @@
|
|||
<button name="action_compute" states="draft"
|
||||
string="Compute Data" type="object"
|
||||
icon="terp-stock_format-scientific"
|
||||
colspan="4" />
|
||||
colspan="2" />
|
||||
<field colspan="4" name="workcenter_lines" nolabel="1">
|
||||
<form string="Production Work Centers">
|
||||
<field colspan="4" name="name"/>
|
||||
|
@ -702,7 +772,7 @@
|
|||
<button name="action_compute" states="draft"
|
||||
string="Compute Data" type="object"
|
||||
icon="terp-stock_format-scientific"
|
||||
colspan="4" />
|
||||
colspan="2" />
|
||||
<field colspan="4" name="product_lines" nolabel="1" widget="one2many_list"/>
|
||||
</page>
|
||||
<page string="Extra Information">
|
||||
|
|
|
@ -30,6 +30,11 @@ class StockMove(osv.osv):
|
|||
_columns = {
|
||||
'production_id': fields.many2one('mrp.production', 'Production', select=True),
|
||||
}
|
||||
|
||||
def create_chained_picking(self, cr, uid, moves, context=None):
|
||||
new_moves = super(StockMove, self).create_chained_picking(cr, uid, moves, context=context)
|
||||
self.write(cr, uid, [x.id for x in new_moves], {'production_id': False}, context=context)
|
||||
return new_moves
|
||||
|
||||
def _action_explode(self, cr, uid, move, context=None):
|
||||
""" Explodes pickings.
|
||||
|
|
|
@ -327,6 +327,9 @@ class mrp_repair(osv.osv):
|
|||
self.write(cr, uid, [o.id], {'state': '2binvoiced'})
|
||||
else:
|
||||
self.write(cr, uid, [o.id], {'state': 'confirmed'})
|
||||
for line in o.operations:
|
||||
if line.product_id.track_production and not line.prodlot_id:
|
||||
raise osv.except_osv(_('Warning'), _("Production lot is required for opration line with product '%s'") % (line.product_id.name))
|
||||
mrp_line_obj.write(cr, uid, [l.id for l in o.operations], {'state': 'confirmed'})
|
||||
return True
|
||||
|
||||
|
@ -535,6 +538,7 @@ class mrp_repair(osv.osv):
|
|||
'location_id': move.location_id.id,
|
||||
'location_dest_id': move.location_dest_id.id,
|
||||
'tracking_id': False,
|
||||
'prodlot_id': move.prodlot_id and move.prodlot_id.id or False,
|
||||
'state': 'done',
|
||||
})
|
||||
repair_line_obj.write(cr, uid, [move.id], {'move_id': move_id, 'state': 'done'}, context=context)
|
||||
|
@ -661,6 +665,7 @@ class mrp_repair_line(osv.osv, ProductChangeMixin):
|
|||
'tax_id': fields.many2many('account.tax', 'repair_operation_line_tax', 'repair_operation_line_id', 'tax_id', 'Taxes'),
|
||||
'product_uom_qty': fields.float('Quantity (UoM)', digits=(16,2), required=True),
|
||||
'product_uom': fields.many2one('product.uom', 'Product UoM', required=True),
|
||||
'prodlot_id': fields.many2one('stock.production.lot', 'Lot Number',domain="[('product_id','=',product_id)]"),
|
||||
'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', readonly=True),
|
||||
'location_id': fields.many2one('stock.location', 'Source Location', required=True, select=True),
|
||||
'location_dest_id': fields.many2one('stock.location', 'Dest. Location', required=True, select=True),
|
||||
|
|
|
@ -49,7 +49,8 @@
|
|||
<notebook>
|
||||
<page string="Repair Line">
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="product_id" on_change="product_id_change(parent.pricelist_id,product_id,product_uom,product_uom_qty, parent.partner_id)" colspan="4"/>
|
||||
<field name="product_id" on_change="product_id_change(parent.pricelist_id,product_id,product_uom,product_uom_qty, parent.partner_id)"/>
|
||||
<field name='prodlot_id'/>
|
||||
<field name="product_uom_qty" string="Qty" />
|
||||
<field name="product_uom" string="UoM"/>
|
||||
<field name="price_unit"/>
|
||||
|
@ -178,7 +179,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<search string="Search Reair Orders">
|
||||
<group col='4' colspan='4'>
|
||||
<filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-check" string="Confirmed" domain="[('state','=','confirmed')]" name="current" />
|
||||
<filter icon="terp-emblem-important" string="Ready To Repair" domain="[('state','=','ready')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
|
@ -202,7 +203,7 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
|
||||
<record id="action_repair_order_tree" model="ir.actions.act_window">
|
||||
<field name="name">Repair Orders</field>
|
||||
|
@ -212,7 +213,7 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_repair_order_form_filter"/>
|
||||
<field name="help">Repair orders allow you to organize your product repairs. In a repair order, you can detail the components you remove, add or replace and record the time you spent on the different operations. The repair order uses the warranty date on the production lot in order to know if whether the repair should be invoiced to the customer or not.</field>
|
||||
</record>
|
||||
</record>
|
||||
|
||||
<menuitem action="action_repair_order_tree" id="menu_repair_order" parent="mrp.menu_mrp_manufacturing" groups="mrp.group_mrp_user" name="Repair Orders" sequence="50"/>
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class pos_config_journal(osv.osv):
|
|||
""" Point of Sale journal configuration"""
|
||||
_name = 'pos.config.journal'
|
||||
_description = "Journal Configuration"
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Description', size=64),
|
||||
'code': fields.char('Code', size=64),
|
||||
|
@ -46,7 +46,7 @@ pos_config_journal()
|
|||
class pos_company_discount(osv.osv):
|
||||
""" Company Discount and Cashboxes """
|
||||
_inherit = 'res.company'
|
||||
|
||||
|
||||
_columns = {
|
||||
'company_discount': fields.float('Max Discount(%)', digits_compute=dp.get_precision('Point Of Sale')),
|
||||
'max_diff': fields.float('Max Difference for Cashboxes', digits_compute=dp.get_precision('Point Of Sale Discount')),
|
||||
|
@ -247,14 +247,14 @@ class pos_order(osv.osv):
|
|||
'num_sale': fields.char('Internal Note', size=64),
|
||||
'shop_id': fields.many2one('sale.shop', 'Shop', required=True,
|
||||
states={'draft': [('readonly', False)]}, readonly=True),
|
||||
'date_order': fields.datetime('Date Ordered', readonly=True),
|
||||
'date_order': fields.datetime('Date Ordered', readonly=True, select=True),
|
||||
'date_validation': fields.function(_get_date_payment,
|
||||
method=True,
|
||||
string='Validation Date',
|
||||
type='date', store=True),
|
||||
type='date', select=True, store=True),
|
||||
'date_payment': fields.function(_get_date_payment2, method=True,
|
||||
string='Payment Date',
|
||||
type='date', store=True),
|
||||
type='date', select=True, store=True),
|
||||
'date_validity': fields.date('Validity Date', required=True),
|
||||
'user_id': fields.many2one('res.users', 'Connected Salesman', help="Person who uses the the cash register. It could be a reliever, a student or an interim employee."),
|
||||
'user_salesman_id': fields.many2one('res.users', 'Cashier', required=True, help="User who is logged into the system."),
|
||||
|
@ -332,7 +332,7 @@ class pos_order(osv.osv):
|
|||
|
||||
|
||||
def test_order_lines(self, cr, uid, order, context=None):
|
||||
""" Test order line is created or not for the order
|
||||
""" Test order line is created or not for the order
|
||||
@param name: Names of fields.
|
||||
@return: True
|
||||
"""
|
||||
|
@ -573,9 +573,9 @@ class pos_order(osv.osv):
|
|||
return statement_id
|
||||
|
||||
def add_product(self, cr, uid, order_id, product_id, qty, context=None):
|
||||
|
||||
|
||||
"""Create a new order line the order"""
|
||||
|
||||
|
||||
line_obj = self.pool.get('pos.order.line')
|
||||
values = self.read(cr, uid, order_id, ['partner_id', 'pricelist_id'])
|
||||
|
||||
|
@ -596,9 +596,9 @@ class pos_order(osv.osv):
|
|||
return order_line_id, price
|
||||
|
||||
def refund(self, cr, uid, ids, context=None):
|
||||
|
||||
|
||||
"""Create a copy of order for refund order"""
|
||||
|
||||
|
||||
clone_list = []
|
||||
line_obj = self.pool.get('pos.order.line')
|
||||
|
||||
|
@ -623,9 +623,9 @@ class pos_order(osv.osv):
|
|||
return clone_list
|
||||
|
||||
def action_invoice(self, cr, uid, ids, context=None):
|
||||
|
||||
|
||||
"""Create a invoice of order """
|
||||
|
||||
|
||||
inv_ref = self.pool.get('account.invoice')
|
||||
inv_line_ref = self.pool.get('account.invoice.line')
|
||||
product_obj = self.pool.get('product.product')
|
||||
|
|
|
@ -361,17 +361,22 @@ class procurement_order(osv.osv):
|
|||
"""
|
||||
ok = True
|
||||
if procurement.move_id:
|
||||
message = False
|
||||
id = procurement.move_id.id
|
||||
if not (procurement.move_id.state in ('done','assigned','cancel')):
|
||||
ok = ok and self.pool.get('stock.move').action_assign(cr, uid, [id])
|
||||
cr.execute('select count(id) from stock_warehouse_orderpoint where product_id=%s', (procurement.product_id.id,))
|
||||
if not cr.fetchone()[0]:
|
||||
cr.execute('update procurement_order set message=%s where id=%s',
|
||||
(_('Not enough stock and no minimum orderpoint rule defined.'),
|
||||
procurement.id))
|
||||
message = _("Procurement '%s' is in exception: not enough stock.") % \
|
||||
(procurement.name,)
|
||||
self.log(cr, uid, procurement.id, message)
|
||||
res = cr.fetchone()[0]
|
||||
if not res and not ok:
|
||||
message = _("Not enough stock and no minimum orderpoint rule defined.")
|
||||
elif not res:
|
||||
message = _("No minimum orderpoint rule defined.")
|
||||
elif not ok:
|
||||
message = _("Not enough stock.")
|
||||
|
||||
if message:
|
||||
self.log(cr, uid, procurement.id, _("Procurement '%s' is in exception: ") % (procurement.name) + message)
|
||||
cr.execute('update procurement_order set message=%s where id=%s', (message, procurement.id))
|
||||
return ok
|
||||
|
||||
def action_produce_assign_service(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
'product_data.xml',
|
||||
'product_report.xml',
|
||||
'product_view.xml',
|
||||
'product_shortcut_data.xml',
|
||||
'pricelist_view.xml',
|
||||
'partner_view.xml',
|
||||
'process/product_process.xml'
|
||||
|
|
|
@ -166,10 +166,9 @@ class product_pricelist(osv.osv):
|
|||
pricelist_version_ids = pricelist_ids
|
||||
else:
|
||||
# all pricelists:
|
||||
pricelist_version_ids = product_pricelist_version_obj.search(cr, uid, [])
|
||||
pricelist_version_ids = self.pool.get('product.pricelist').search(cr, uid, [], context=context)
|
||||
|
||||
pricelist_version_ids = list(set(pricelist_version_ids))
|
||||
|
||||
plversions_search_args = [
|
||||
('pricelist_id', 'in', pricelist_version_ids),
|
||||
'|',
|
||||
|
|
|
@ -482,6 +482,19 @@ class product_product(osv.osv):
|
|||
'pricelist_id': fields.dummy(string='Pricelist', relation='product.pricelist', type='many2one'),
|
||||
'name_template': fields.related('product_tmpl_id', 'name', string="Name", type='char', size=128, store=True),
|
||||
}
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
unlink_ids = []
|
||||
unlink_product_tmpl_ids = []
|
||||
for product in self.browse(cr, uid, ids, context=context):
|
||||
tmpl_id = product.product_tmpl_id.id
|
||||
# Check if the product is last product of this template
|
||||
other_product_ids = self.search(cr, uid, [('product_tmpl_id', '=', tmpl_id), ('id', '!=', product.id)], context=context)
|
||||
if not other_product_ids:
|
||||
unlink_product_tmpl_ids.append(tmpl_id)
|
||||
unlink_ids.append(product.id)
|
||||
self.pool.get('product.template').unlink(cr, uid, unlink_product_tmpl_ids, context=context)
|
||||
return super(product_product, self).unlink(cr, uid, unlink_ids, context=context)
|
||||
|
||||
def onchange_uom(self, cursor, user, ids, uom_id,uom_po_id):
|
||||
if uom_id and uom_po_id:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="ir_ui_view_sc_product0" model="ir.ui.view_sc">
|
||||
<field name="name">Products</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="res_id" ref="product.menu_products"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -9,7 +9,7 @@
|
|||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Product">
|
||||
<filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
|
||||
<filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/>
|
||||
<filter string="Stockable" icon="terp-accessories-archiver" domain="['|',('type','=','product'),('type','=','consu')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="To Sell" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/>
|
||||
|
@ -30,7 +30,7 @@
|
|||
<separator orientation="vertical"/>
|
||||
<filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}" />
|
||||
</group>
|
||||
|
||||
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -101,7 +101,7 @@
|
|||
</group>
|
||||
|
||||
<group colspan="2" col="2" groups="base.group_extended">
|
||||
<separator string="Weigths" colspan="2"/>
|
||||
<separator string="Weights" colspan="2"/>
|
||||
<field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight_net" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
|
@ -567,7 +567,7 @@
|
|||
</group>
|
||||
|
||||
<group colspan="2" col="2" groups="base.group_extended">
|
||||
<separator string="Weigths" colspan="2"/>
|
||||
<separator string="Weights" colspan="2"/>
|
||||
<field digits="(14, 3)" name="volume" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
<field digits="(14, 3)" name="weight_net" attrs="{'readonly':[('type','=','service')]}"/>
|
||||
|
@ -635,12 +635,6 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="product_template_tree_view"/>
|
||||
</record>
|
||||
<record id="ir_ui_view_sc_product0" model="ir.ui.view_sc">
|
||||
<field name="name">Products</field>
|
||||
<field name="resource">ir.ui.menu</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="res_id" ref="product.menu_products"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -62,18 +62,18 @@ class product_pricelist(report_sxw.rml_parse):
|
|||
|
||||
def _get_pricelist(self, pricelist_id):
|
||||
pool = pooler.get_pool(self.cr.dbname)
|
||||
pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['name'])[0]
|
||||
pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['name'], context=self.localcontext)[0]
|
||||
return pricelist['name']
|
||||
|
||||
def _get_currency(self, pricelist_id):
|
||||
pool = pooler.get_pool(self.cr.dbname)
|
||||
pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'])[0]
|
||||
pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0]
|
||||
return pricelist['currency_id'][1]
|
||||
|
||||
def _get_currency_symbol(self, pricelist_id):
|
||||
pool = pooler.get_pool(self.cr.dbname)
|
||||
pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'])[0]
|
||||
symbol = pool.get('res.currency').read(self.cr, self.uid, [pricelist['currency_id'][0]], ['symbol'])[0]
|
||||
pricelist = pool.get('product.pricelist').read(self.cr, self.uid, [pricelist_id], ['currency_id'], context=self.localcontext)[0]
|
||||
symbol = pool.get('res.currency').read(self.cr, self.uid, [pricelist['currency_id'][0]], ['symbol'], context=self.localcontext)[0]
|
||||
return symbol['symbol'] or ''
|
||||
|
||||
def _get_categories(self, products,form):
|
||||
|
@ -88,13 +88,13 @@ class product_pricelist(report_sxw.rml_parse):
|
|||
if product.categ_id.id not in cat_ids:
|
||||
cat_ids.append(product.categ_id.id)
|
||||
|
||||
cats = pool.get('product.category').name_get(self.cr, self.uid, cat_ids)
|
||||
cats = pool.get('product.category').name_get(self.cr, self.uid, cat_ids, context=self.localcontext)
|
||||
if not cats:
|
||||
return res
|
||||
for cat in cats:
|
||||
product_ids=pool.get('product.product').search(self.cr, self.uid, [('id','in',pro_ids),('categ_id','=',cat[0])])
|
||||
product_ids=pool.get('product.product').search(self.cr, self.uid, [('id', 'in', pro_ids), ('categ_id', '=', cat[0])], context=self.localcontext)
|
||||
products = []
|
||||
for product in pool.get('product.product').read(self.cr, self.uid, product_ids, ['name','code']):
|
||||
for product in pool.get('product.product').read(self.cr, self.uid, product_ids, ['name', 'code'], context=self.localcontext):
|
||||
val = {
|
||||
'id':product['id'],
|
||||
'name':product['name'],
|
||||
|
@ -114,7 +114,7 @@ class product_pricelist(report_sxw.rml_parse):
|
|||
def _get_price(self,pricelist_id, product_id,qty):
|
||||
sale_price_digits = self.get_digits(dp='Sale Price')
|
||||
pool = pooler.get_pool(self.cr.dbname)
|
||||
price_dict = pool.get('product.pricelist').price_get(self.cr, self.uid, [pricelist_id], product_id,qty)
|
||||
price_dict = pool.get('product.pricelist').price_get(self.cr, self.uid, [pricelist_id], product_id, qty, context=self.localcontext)
|
||||
if price_dict[pricelist_id]:
|
||||
price = self.formatLang(price_dict[pricelist_id], digits=sale_price_digits)
|
||||
else:
|
||||
|
|
|
@ -148,7 +148,7 @@ class purchase_order(osv.osv):
|
|||
STATE_SELECTION = [
|
||||
('draft', 'Request for Quotation'),
|
||||
('wait', 'Waiting'),
|
||||
('confirmed', 'Waiting Supplier Ack'),
|
||||
('confirmed', 'Waiting Approval'),
|
||||
('approved', 'Approved'),
|
||||
('except_picking', 'Shipping Exception'),
|
||||
('except_invoice', 'Invoice Exception'),
|
||||
|
@ -455,6 +455,7 @@ class purchase_order(osv.osv):
|
|||
'state': 'draft',
|
||||
'purchase_line_id': order_line.id,
|
||||
'company_id': order.company_id.id,
|
||||
'price_unit': order_line.price_unit
|
||||
})
|
||||
if order_line.move_dest_id:
|
||||
self.pool.get('stock.move').write(cr, uid, [order_line.move_dest_id.id], {'location_id':order.location_id.id})
|
||||
|
@ -816,4 +817,22 @@ class procurement_order(osv.osv):
|
|||
|
||||
procurement_order()
|
||||
|
||||
class stock_invoice_onshipping(osv.osv_memory):
|
||||
_inherit = "stock.invoice.onshipping"
|
||||
|
||||
def create_invoice(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = super(stock_invoice_onshipping,self).create_invoice(cr, uid, ids, context=context)
|
||||
purchase_obj = self.pool.get('purchase.order')
|
||||
picking_obj = self.pool.get('stock.picking')
|
||||
for pick_id in res:
|
||||
pick = picking_obj.browse(cr, uid, pick_id, context=context)
|
||||
if pick.purchase_id:
|
||||
purchase_obj.write(cr, uid, [pick.purchase_id.id], {
|
||||
'invoice_ids': [(4, res[pick_id])]}, context=context)
|
||||
return res
|
||||
|
||||
stock_invoice_onshipping()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -5,19 +5,19 @@
|
|||
<record id="base.user_demo" model="res.users">
|
||||
<field eval="[(4, ref('group_purchase_user'))]" name="groups_id"/>
|
||||
</record>
|
||||
|
||||
|
||||
<!--Resource: purchase.order-->
|
||||
|
||||
<record id="order_purchase1" model="purchase.order">
|
||||
<field name="location_id" ref="stock.stock_location_stock"/>
|
||||
<field model="product.pricelist" name="pricelist_id" search="[]"/>
|
||||
<field name="pricelist_id" ref="purchase.list0"/>
|
||||
<field name="partner_id" ref="base.res_partner_asus"/>
|
||||
<field name="partner_address_id" ref="base.res_partner_address_tang"/>
|
||||
</record>
|
||||
|
||||
<record id="order_purchase2" model="purchase.order">
|
||||
<field name="location_id" ref="stock.stock_location_stock"/>
|
||||
<field model="product.pricelist" name="pricelist_id" search="[]"/>
|
||||
<field name="pricelist_id" ref="purchase.list0"/>
|
||||
<field name="partner_id" ref="base.res_partner_3"/>
|
||||
<field name="partner_address_id" ref="base.res_partner_address_zen"/>
|
||||
</record>
|
||||
|
@ -48,7 +48,7 @@
|
|||
<field name="order_id" ref="order_purchase2"/>
|
||||
<field name="date_planned" eval="time.strftime('%Y/%m/%d')"/>
|
||||
<field name="name">[PC3] Medium PC</field>
|
||||
<field name="product_id" ref="product.product_product_pc1"/>
|
||||
<field name="product_id" ref="product.product_product_pc3"/>
|
||||
<field name="product_uom" ref="product.product_uom_unit"/>
|
||||
<field name="price_unit">900</field>
|
||||
<field name="product_qty">1</field>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<menuitem
|
||||
id="menu_purchase_config_pricelist" name="Pricelists"
|
||||
parent="menu_purchase_config_purchase" sequence="50"/>
|
||||
|
||||
|
||||
<menuitem
|
||||
action="product.product_pricelist_action" id="menu_product_pricelist_action_purhase"
|
||||
parent="menu_purchase_config_pricelist" sequence="20"/>
|
||||
|
@ -32,7 +32,7 @@
|
|||
<menuitem
|
||||
id="menu_product_in_config_purchase" name="Product"
|
||||
parent="menu_purchase_config_purchase" sequence="30"/>
|
||||
|
||||
|
||||
<menuitem
|
||||
action="product.product_category_action_form" id="menu_product_category_config_purchase"
|
||||
parent="purchase.menu_product_in_config_purchase" sequence="10"/>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<menuitem
|
||||
id="menu_purchase_unit_measure_purchase" name="Units of Measure"
|
||||
parent="purchase.menu_product_in_config_purchase" sequence="20"/>
|
||||
|
||||
|
||||
<menuitem
|
||||
action="product.product_uom_categ_form_action" id="menu_purchase_uom_categ_form_action"
|
||||
parent="menu_purchase_unit_measure_purchase" sequence="30"/>
|
||||
|
@ -113,10 +113,10 @@
|
|||
<!--product menu-->
|
||||
<menuitem id="menu_procurement_management_product" name="Products"
|
||||
parent="base.menu_purchase_root" sequence="8"/>
|
||||
|
||||
|
||||
<menuitem name="Products by Category" id="menu_product_by_category_purchase_form" action="product.product_category_action"
|
||||
parent="menu_procurement_management_product" sequence="10"/>
|
||||
|
||||
|
||||
<menuitem name="Products" id="menu_procurement_partner_contact_form" action="product.product_normal_action_puchased"
|
||||
parent="menu_procurement_management_product"/>
|
||||
|
||||
|
@ -194,7 +194,7 @@
|
|||
<button name="invoice_ok" states="except_invoice" string="Manually Corrected" icon="gtk-convert"/>
|
||||
<button name="purchase_confirm" states="draft" string="Convert to Purchase Order" icon="gtk-go-forward"/>
|
||||
<button name="purchase_appbuyer" states="wait_auth" string="Approve Purchase" icon="gtk-ok"/>
|
||||
<button name="purchase_approve" states="confirmed" string="Approved by Supplier" icon="gtk-go-forward"/>
|
||||
<button name="purchase_approve" states="confirmed" string="Approved" icon="gtk-go-forward"/>
|
||||
<button name="%(report_purchase_order)d" string="Print" states="approved" type="action" icon="gtk-print"/>
|
||||
</group>
|
||||
</page>
|
||||
|
@ -292,7 +292,7 @@
|
|||
<field name="search_view_id" ref="view_purchase_order_filter"/>
|
||||
<field name="help">You can create a request for quotation when you want to buy products to a supplier but the purchase is not confirmed yet. Use also this menu to review requests for quotation created automatically based on your logistic rules (minimum stock, MTO, etc). You can convert the request for quotation into a purchase order once the order is confirmed. If you use the extended interface (from user's preferences), you can select the way to control your supplier invoices: based on the order, based on the receptions or manual encoding.</field>
|
||||
</record>
|
||||
<menuitem action="purchase_rfq" id="menu_purchase_rfq"
|
||||
<menuitem action="purchase_rfq" id="menu_purchase_rfq"
|
||||
parent="menu_procurement_management"
|
||||
sequence="6"/>
|
||||
|
||||
|
@ -458,7 +458,7 @@
|
|||
<field name="name">Purchase Lines Not Invoiced</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">purchase.order.line</field>
|
||||
<field name="domain">[('state','in',('confirmed','done')), ('invoiced', '=', False)]</field>
|
||||
<field name="domain">[('order_id.invoice_method','<>','picking'), ('state','in',('confirmed','done')), ('invoiced', '=', False)]</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="purchase_order_line_search"/>
|
||||
|
|
|
@ -171,7 +171,8 @@
|
|||
</record>
|
||||
|
||||
|
||||
<menuitem id="base.next_id_73" name="Reporting" parent="base.menu_purchase_root" sequence="8"/>
|
||||
<menuitem id="base.next_id_73" name="Reporting" parent="base.menu_purchase_root" sequence="8"
|
||||
groups="purchase.group_purchase_manager"/>
|
||||
<menuitem action="action_purchase_order_report_all" id="menu_action_purchase_order_report_all" parent="base.next_id_73" sequence="3"/>
|
||||
|
||||
<record id="action_stock_move_report_po" model="ir.actions.act_window">
|
||||
|
|
|
@ -58,6 +58,19 @@ class stock_picking(osv.osv):
|
|||
'purchase_id': False,
|
||||
}
|
||||
|
||||
def _get_address_invoice(self, cr, uid, picking):
|
||||
""" Gets invoice address of a partner
|
||||
@return {'contact': address, 'invoice': address} for invoice
|
||||
"""
|
||||
res = super(stock_picking, self)._get_address_invoice(cr, uid, picking)
|
||||
if picking.purchase_id:
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
partner = picking.purchase_id.partner_id or picking.address_id.partner_id
|
||||
data = partner_obj.address_get(cr, uid, [partner.id],
|
||||
['contact', 'invoice'])
|
||||
res.update(data)
|
||||
return res
|
||||
|
||||
def get_currency_id(self, cursor, user, picking):
|
||||
if picking.purchase_id:
|
||||
return picking.purchase_id.pricelist_id.currency_id.id
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<field name="inherit_id" ref="purchase.view_purchase_order_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/search/group/filter[@string='Not Invoiced']" position="after">
|
||||
<filter icon="terp-gtk-jump-to-rtl" string="Requisition" domain="[('requisition_id','!=',False)]" separator="1"/>
|
||||
<filter icon="terp-gtk-jump-to-rtl" string="Requisition" domain="[('requisition_id','!=',False)]" separator="1" help="Purchase Orders with requisition"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_purchase_requisition","purchase.requisition","model_purchase_requisition","purchase.group_purchase_user",1,1,1,1
|
||||
"access_purchase_requisition_line","purchase.requisition.line","model_purchase_requisition_line","purchase.group_purchase_user",1,1,1,1
|
||||
"access_purchase_requisition_line_purchase_user","purchase.requisition.line","model_purchase_requisition_line","purchase.group_purchase_user",1,1,1,1
|
||||
"access_purchase_requisition_manager","purchase.requisition manager","model_purchase_requisition","purchase.group_purchase_manager",1,0,0,0
|
||||
"access_purchase_requisition_line_manager","purchase.requisition.line manager","model_purchase_requisition_line","purchase.group_purchase_manager",1,0,0,0
|
||||
"access_purchase_requisition","purchase.requisition","model_purchase_requisition","stock.group_stock_manager",1,0,1,0
|
||||
"access_purchase_requisition_line","purchase.requisition.line","model_purchase_requisition_line","stock.group_stock_manager",1,0,1,0
|
||||
"access_purchase_requisition_stock_manager","purchase.requisition","model_purchase_requisition","stock.group_stock_manager",1,0,1,0
|
||||
"access_purchase_requisition_line_stock_manager","purchase.requisition.line","model_purchase_requisition_line","stock.group_stock_manager",1,0,1,0
|
||||
|
|
|
|
@ -4,6 +4,9 @@
|
|||
<record id="base.de" model="res.country">
|
||||
<field eval="True" name="intrastat"/>
|
||||
</record>
|
||||
<record id="base.be" model="res.country">
|
||||
<field eval="True" name="intrastat"/>
|
||||
</record>
|
||||
<record id="base.at" model="res.country">
|
||||
<field eval="True" name="intrastat"/>
|
||||
</record>
|
||||
|
|
|
@ -185,7 +185,7 @@ class sale_order(osv.osv):
|
|||
for line in self.pool.get('sale.order.line').browse(cr, uid, ids, context=context):
|
||||
result[line.order_id.id] = True
|
||||
return result.keys()
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Order Reference', size=64, required=True,
|
||||
readonly=True, states={'draft': [('readonly', False)]}, select=True),
|
||||
|
@ -202,9 +202,9 @@ class sale_order(osv.osv):
|
|||
('done', 'Done'),
|
||||
('cancel', 'Cancelled')
|
||||
], 'Order State', readonly=True, help="Gives the state of the quotation or sales order. \nThe exception state is automatically set when a cancel operation occurs in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception). \nThe 'Waiting Schedule' state is set when the invoice is confirmed but waiting for the scheduler to run on the date 'Ordered Date'.", select=True),
|
||||
'date_order': fields.date('Ordered Date', required=True, readonly=True, states={'draft': [('readonly', False)]}),
|
||||
'create_date': fields.date('Creation Date', readonly=True, help="Date on which sales order is created."),
|
||||
'date_confirm': fields.date('Confirmation Date', readonly=True, help="Date on which sales order is confirmed."),
|
||||
'date_order': fields.date('Ordered Date', required=True, readonly=True, select=True, states={'draft': [('readonly', False)]}),
|
||||
'create_date': fields.date('Creation Date', readonly=True, select=True, help="Date on which sales order is created."),
|
||||
'date_confirm': fields.date('Confirmation Date', readonly=True, select=True, help="Date on which sales order is confirmed."),
|
||||
'user_id': fields.many2one('res.users', 'Salesman', states={'draft': [('readonly', False)]}, select=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Customer', readonly=True, states={'draft': [('readonly', False)]}, required=True, change_default=True, select=True),
|
||||
'partner_invoice_id': fields.many2one('res.partner.address', 'Invoice Address', readonly=True, required=True, states={'draft': [('readonly', False)]}, help="Invoice address for current sales order."),
|
||||
|
@ -705,7 +705,6 @@ class sale_order(osv.osv):
|
|||
#'state': 'waiting',
|
||||
'note': line.notes,
|
||||
'company_id': order.company_id.id,
|
||||
'returned_price': line.price_unit,
|
||||
})
|
||||
|
||||
if line.product_id:
|
||||
|
@ -739,12 +738,13 @@ class sale_order(osv.osv):
|
|||
proc_obj.write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
|
||||
|
||||
val = {}
|
||||
for proc_id in proc_ids:
|
||||
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
|
||||
|
||||
if picking_id:
|
||||
wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
|
||||
|
||||
for proc_id in proc_ids:
|
||||
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
|
||||
|
||||
if order.state == 'shipping_except':
|
||||
val['state'] = 'progress'
|
||||
val['shipped'] = False
|
||||
|
|
|
@ -172,6 +172,7 @@
|
|||
<page groups="base.group_extended" string="Extra Info">
|
||||
<field name="th_weight"/>
|
||||
<field name="address_allotment_id"/>
|
||||
<field name="property_ids" colspan="4"/>
|
||||
</page>
|
||||
<page string="Notes">
|
||||
<field colspan="4" name="notes" nolabel="1"/>
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
<separator string="Stocks" colspan="4"/>
|
||||
<field name="qty_available"/>
|
||||
<button name="%(action_view_change_product_quantity)d" string="Update" attrs="{'invisible': [('type', '=', 'service')]}"
|
||||
type="action" icon="gtk-execute" groups = "stock.group_stock_manager,base.group_sale_manager,purchase.group_purchase_manager,stock.group_stock_manager,mrp.group_mrp_manager"/>
|
||||
type="action" icon="gtk-execute" groups = "stock.group_stock_manager,stock.group_stock_user"/>
|
||||
<newline/>
|
||||
<field name="virtual_available"/>
|
||||
</group>
|
||||
|
|
|
@ -864,8 +864,7 @@ class stock_picking(osv.osv):
|
|||
@return {'contact': address, 'invoice': address} for invoice
|
||||
"""
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
partner = (picking.purchase_id and picking.purchase_id.partner_id) or (picking.sale_id and picking.sale_id.partner_id) or picking.address_id.partner_id
|
||||
|
||||
partner = picking.address_id.partner_id
|
||||
return partner_obj.address_get(cr, uid, [partner.id],
|
||||
['contact', 'invoice'])
|
||||
|
||||
|
@ -960,6 +959,7 @@ class stock_picking(osv.osv):
|
|||
|
||||
invoice_obj = self.pool.get('account.invoice')
|
||||
invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
address_obj = self.pool.get('res.partner.address')
|
||||
invoices_group = {}
|
||||
res = {}
|
||||
inv_type = type
|
||||
|
@ -983,6 +983,7 @@ class stock_picking(osv.osv):
|
|||
|
||||
address_contact_id, address_invoice_id = \
|
||||
self._get_address_invoice(cr, uid, picking).values()
|
||||
address = address_obj.browse(cr, uid, address_contact_id, context=context)
|
||||
|
||||
comment = self._get_comment_invoice(cr, uid, picking)
|
||||
if group and partner.id in invoices_group:
|
||||
|
@ -1002,7 +1003,7 @@ class stock_picking(osv.osv):
|
|||
'origin': (picking.name or '') + (picking.origin and (':' + picking.origin) or ''),
|
||||
'type': inv_type,
|
||||
'account_id': account_id,
|
||||
'partner_id': partner.id,
|
||||
'partner_id': address.partner_id.id,
|
||||
'address_invoice_id': address_invoice_id,
|
||||
'address_contact_id': address_contact_id,
|
||||
'comment': comment,
|
||||
|
@ -1159,6 +1160,7 @@ class stock_picking(osv.osv):
|
|||
complete, too_many, too_few = [], [], []
|
||||
move_product_qty = {}
|
||||
prodlot_ids = {}
|
||||
product_avail = {}
|
||||
for move in pick.move_lines:
|
||||
if move.state in ('done', 'cancel'):
|
||||
continue
|
||||
|
@ -1184,6 +1186,12 @@ class stock_picking(osv.osv):
|
|||
move_currency_id = move.company_id.currency_id.id
|
||||
context['currency_id'] = move_currency_id
|
||||
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id)
|
||||
|
||||
if product.id in product_avail:
|
||||
product_avail[product.id] += qty
|
||||
else:
|
||||
product_avail[product.id] = product.qty_available
|
||||
|
||||
if qty > 0:
|
||||
new_price = currency_obj.compute(cr, uid, product_currency,
|
||||
move_currency_id, product_price)
|
||||
|
@ -1194,9 +1202,8 @@ class stock_picking(osv.osv):
|
|||
else:
|
||||
# Get the standard price
|
||||
amount_unit = product.price_get('standard_price', context)[product.id]
|
||||
new_std_price = ((amount_unit * product.qty_available)\
|
||||
+ (new_price * qty))/(product.qty_available + qty)
|
||||
|
||||
new_std_price = ((amount_unit * product_avail[product.id])\
|
||||
+ (new_price * qty))/(product_avail[product.id] + qty)
|
||||
# Write the field according to price type field
|
||||
product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price})
|
||||
|
||||
|
@ -1206,8 +1213,6 @@ class stock_picking(osv.osv):
|
|||
{'price_unit': product_price,
|
||||
'price_currency_id': product_currency})
|
||||
|
||||
if not move.returned_price:
|
||||
move_obj.write(cr, uid, [move.id], {'returned_price': move.price_unit})
|
||||
|
||||
for move in too_few:
|
||||
product_qty = move_product_qty[move.id]
|
||||
|
@ -1547,7 +1552,6 @@ class stock_move(osv.osv):
|
|||
|
||||
# used for colors in tree views:
|
||||
'scrapped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scrapped', readonly=True),
|
||||
'returned_price': fields.float('Returned product price', digits_compute= dp.get_precision('Sale Price')),
|
||||
}
|
||||
_constraints = [
|
||||
(_check_tracking,
|
||||
|
@ -1784,7 +1788,7 @@ class stock_move(osv.osv):
|
|||
picking_obj = self.pool.get('stock.picking')
|
||||
pick_id= picking_obj.create(cr, uid, {
|
||||
'name': pick_name,
|
||||
'origin': str(picking.origin or ''),
|
||||
'origin': tools.ustr(picking.origin or ''),
|
||||
'type': ptype,
|
||||
'note': picking.note,
|
||||
'move_type': picking.move_type,
|
||||
|
@ -1796,6 +1800,51 @@ class stock_move(osv.osv):
|
|||
'date': picking.date,
|
||||
})
|
||||
return pick_id
|
||||
def create_chained_picking(self, cr, uid, moves, context=None):
|
||||
res_obj = self.pool.get('res.company')
|
||||
location_obj = self.pool.get('stock.location')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
new_moves = []
|
||||
if context is None:
|
||||
context = {}
|
||||
seq_obj = self.pool.get('ir.sequence')
|
||||
for picking, todo in self._chain_compute(cr, uid, moves, context=context).items():
|
||||
ptype = todo[0][1][5] and todo[0][1][5] or location_obj.picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0])
|
||||
if picking:
|
||||
# name of new picking according to its type
|
||||
new_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + ptype)
|
||||
pickid = self._create_chained_picking(cr, uid, new_pick_name, picking, ptype, todo, context=context)
|
||||
# Need to check name of old picking because it always considers picking as "OUT" when created from Sale Order
|
||||
old_ptype = location_obj.picking_type_get(cr, uid, picking.move_lines[0].location_id, picking.move_lines[0].location_dest_id)
|
||||
if old_ptype != picking.type:
|
||||
old_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + old_ptype)
|
||||
self.pool.get('stock.picking').write(cr, uid, picking.id, {'name': old_pick_name}, context=context)
|
||||
else:
|
||||
pickid = False
|
||||
for move, (loc, dummy, delay, dummy, company_id, ptype) in todo:
|
||||
new_id = move_obj.copy(cr, uid, move.id, {
|
||||
'location_id': move.location_dest_id.id,
|
||||
'location_dest_id': loc.id,
|
||||
'date_moved': time.strftime('%Y-%m-%d'),
|
||||
'picking_id': pickid,
|
||||
'state': 'waiting',
|
||||
'company_id': company_id or res_obj._company_default_get(cr, uid, 'stock.company', context=context) ,
|
||||
'move_history_ids': [],
|
||||
'date': (datetime.strptime(move.date, '%Y-%m-%d %H:%M:%S') + relativedelta(days=delay or 0)).strftime('%Y-%m-%d'),
|
||||
'move_history_ids2': []}
|
||||
)
|
||||
move_obj.write(cr, uid, [move.id], {
|
||||
'move_dest_id': new_id,
|
||||
'move_history_ids': [(4, new_id)]
|
||||
})
|
||||
new_moves.append(self.browse(cr, uid, [new_id])[0])
|
||||
if pickid:
|
||||
wf_service.trg_validate(uid, 'stock.picking', pickid, 'button_confirm', cr)
|
||||
if new_moves:
|
||||
new_moves += self.create_chained_picking(cr, uid, new_moves, context)
|
||||
return new_moves
|
||||
|
||||
def action_confirm(self, cr, uid, ids, context=None):
|
||||
""" Confirms stock move.
|
||||
@return: List of ids.
|
||||
|
@ -1807,46 +1856,7 @@ class stock_move(osv.osv):
|
|||
move_obj = self.pool.get('stock.move')
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
|
||||
def create_chained_picking(self, cr, uid, moves, context=None):
|
||||
new_moves = []
|
||||
if context is None:
|
||||
context = {}
|
||||
seq_obj = self.pool.get('ir.sequence')
|
||||
for picking, todo in self._chain_compute(cr, uid, moves, context=context).items():
|
||||
ptype = todo[0][1][5] and todo[0][1][5] or location_obj.picking_type_get(cr, uid, todo[0][0].location_dest_id, todo[0][1][0])
|
||||
if picking:
|
||||
# name of new picking according to its type
|
||||
new_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + ptype)
|
||||
pickid = self._create_chained_picking(cr, uid, new_pick_name, picking, ptype, todo, context=context)
|
||||
# Need to check name of old picking because it always considers picking as "OUT" when created from Sale Order
|
||||
old_ptype = location_obj.picking_type_get(cr, uid, picking.move_lines[0].location_id, picking.move_lines[0].location_dest_id)
|
||||
if old_ptype != picking.type:
|
||||
old_pick_name = seq_obj.get(cr, uid, 'stock.picking.' + old_ptype)
|
||||
self.pool.get('stock.picking').write(cr, uid, picking.id, {'name': old_pick_name}, context=context)
|
||||
else:
|
||||
pickid = False
|
||||
for move, (loc, dummy, delay, dummy, company_id, ptype) in todo:
|
||||
new_id = move_obj.copy(cr, uid, move.id, {
|
||||
'location_id': move.location_dest_id.id,
|
||||
'location_dest_id': loc.id,
|
||||
'date_moved': time.strftime('%Y-%m-%d'),
|
||||
'picking_id': pickid,
|
||||
'state': 'waiting',
|
||||
'company_id': company_id or res_obj._company_default_get(cr, uid, 'stock.company', context=context) ,
|
||||
'move_history_ids': [],
|
||||
'date': (datetime.strptime(move.date, '%Y-%m-%d %H:%M:%S') + relativedelta(days=delay or 0)).strftime('%Y-%m-%d'),
|
||||
'move_history_ids2': []}
|
||||
)
|
||||
move_obj.write(cr, uid, [move.id], {
|
||||
'move_dest_id': new_id,
|
||||
'move_history_ids': [(4, new_id)]
|
||||
})
|
||||
new_moves.append(self.browse(cr, uid, [new_id])[0])
|
||||
if pickid:
|
||||
wf_service.trg_validate(uid, 'stock.picking', pickid, 'button_confirm', cr)
|
||||
if new_moves:
|
||||
create_chained_picking(self, cr, uid, new_moves, context)
|
||||
create_chained_picking(self, cr, uid, moves, context)
|
||||
self.create_chained_picking(cr, uid, moves, context)
|
||||
return []
|
||||
|
||||
def action_assign(self, cr, uid, ids, *args):
|
||||
|
@ -2114,6 +2124,8 @@ class stock_move(osv.osv):
|
|||
prodlot_id = partial_datas and partial_datas.get('move%s_prodlot_id' % (move.id), False)
|
||||
if prodlot_id:
|
||||
self.write(cr, uid, [move.id], {'prodlot_id': prodlot_id}, context=context)
|
||||
if move.state not in ('confirmed','done'):
|
||||
self.action_confirm(cr, uid, move_ids, context=context)
|
||||
|
||||
self.write(cr, uid, move_ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
|
||||
for id in move_ids:
|
||||
|
@ -2218,6 +2230,8 @@ class stock_move(osv.osv):
|
|||
'tracking_id': move.tracking_id.id,
|
||||
'prodlot_id': move.prodlot_id.id,
|
||||
}
|
||||
if move.location_id.usage <> 'internal':
|
||||
default_val.update({'location_id': move.location_dest_id.id})
|
||||
new_move = self.copy(cr, uid, move.id, default_val)
|
||||
|
||||
res += [new_move]
|
||||
|
@ -2568,22 +2582,33 @@ class stock_inventory(osv.osv):
|
|||
self.write(cr, uid, [inv.id], {'state': 'confirm', 'move_ids': [(6, 0, move_ids)]})
|
||||
return True
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
def action_cancel_draft(self, cr, uid, ids, context=None):
|
||||
""" Cancels the stock move and change inventory state to draft.
|
||||
@return: True
|
||||
"""
|
||||
for inv in self.browse(cr, uid, ids, context=context):
|
||||
self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context)
|
||||
self.write(cr, uid, [inv.id], {'state': 'draft'})
|
||||
self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context=context)
|
||||
self.write(cr, uid, [inv.id], {'state':'draft'}, context=context)
|
||||
return True
|
||||
|
||||
def action_cancel_inventary(self, cr, uid, ids, context=None):
|
||||
""" Cancels both stock move and inventory
|
||||
@return: True
|
||||
"""
|
||||
move_obj = self.pool.get('stock.move')
|
||||
account_move_obj = self.pool.get('account.move')
|
||||
for inv in self.browse(cr, uid, ids, context=context):
|
||||
self.pool.get('stock.move').action_cancel(cr, uid, [x.id for x in inv.move_ids], context)
|
||||
self.write(cr, uid, [inv.id], {'state':'cancel'})
|
||||
move_obj.action_cancel(cr, uid, [x.id for x in inv.move_ids], context=context)
|
||||
for move in inv.move_ids:
|
||||
account_move_ids = account_move_obj.search(cr, uid, [('name', '=', move.name)])
|
||||
if account_move_ids:
|
||||
account_move_data_l = account_move_obj.read(cr, uid, account_move_ids, ['state'], context=context)
|
||||
for account_move in account_move_data_l:
|
||||
if account_move['state'] == 'posted':
|
||||
raise osv.except_osv(_('UserError'),
|
||||
_('You can not cancel inventory which has any account move with posted state.'))
|
||||
account_move_obj.unlink(cr, uid, [account_move['id']], context=context)
|
||||
self.write(cr, uid, [inv.id], {'state': 'cancel'}, context=context)
|
||||
return True
|
||||
|
||||
stock_inventory()
|
||||
|
|
|
@ -170,11 +170,11 @@
|
|||
<group col="2" colspan="2">
|
||||
<field name="state"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<button name="action_cancel_inventary" states="draft" string="Cancel Inventory" type="object" icon="gtk-cancel"/>
|
||||
<group col="3" colspan="2">
|
||||
<button name="action_cancel_inventary" states="draft,confirm,done" string="Cancel Inventory" type="object" icon="gtk-cancel"/>
|
||||
<button name="action_confirm" states="draft" string="Confirm Inventory" type="object" icon="gtk-apply"/>
|
||||
<button name="action_done" states="confirm" string="Validate Inventory" type="object" icon="gtk-jump-to"/>
|
||||
<button name="action_cancel" states="cancel" string="Set to Draft" type="object" icon="gtk-convert"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object" icon="gtk-convert"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -773,7 +773,7 @@
|
|||
<button name="action_assign" states="confirmed" string="Check Availability" type="object" icon="gtk-find"/>
|
||||
<button name="force_assign" states="confirmed" string="Force Availability" type="object" icon="gtk-jump-to"/>
|
||||
<button name="action_process" states="assigned" string="Process" groups="stock.group_stock_user" type="object" icon="gtk-go-forward"/>
|
||||
<button states="done" name="%(action_stock_invoice_onshipping)d" string="Create Invoice" type="action" icon="terp-gtk-go-back-rtl" />
|
||||
<button states="done" name="%(action_stock_invoice_onshipping)d" string="Create Invoice" attrs="{'invisible': ['|',('invoice_state','=','invoiced'),('invoice_state','=','none')]}" type="action" icon="terp-gtk-go-back-rtl" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Additional info" groups="base.group_extended,base.group_multi_company">
|
||||
|
@ -967,7 +967,7 @@
|
|||
<button name="force_assign" states="confirmed" string="Force Availability" type="object" icon="gtk-jump-to"/>
|
||||
<button name="action_process" states="assigned" string="Process" type="object" icon="gtk-go-forward"/>
|
||||
<button name="%(act_stock_return_picking)d" string="Return Products" states="done" type="action" icon="gtk-execute"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" states="done" type="action" icon="terp-gtk-go-back-rtl"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" states="done" attrs="{'invisible': ['|',('invoice_state','=','invoiced'),('invoice_state','=','none')]}" type="action" icon="terp-gtk-go-back-rtl"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Additional info" groups="base.group_extended,base.group_multi_company">
|
||||
|
@ -1189,7 +1189,7 @@
|
|||
<group colspan="1" states="done">
|
||||
<button name="%(act_stock_return_picking)d" string="Return Products" states="done" type="action" icon="gtk-execute"/>
|
||||
</group>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" type="action" icon="terp-gtk-go-back-rtl"/>
|
||||
<button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" attrs="{'invisible': ['|',('invoice_state','=','invoiced'),('invoice_state','=','none')]}" type="action" icon="terp-gtk-go-back-rtl" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Additional Info" groups="base.group_extended,base.group_multi_company">
|
||||
|
|
|
@ -32,6 +32,19 @@ class stock_change_product_qty(osv.osv_memory):
|
|||
'location_id': fields.many2one('stock.location', 'Location', required=True, domain="[('usage', '=', 'internal')]"),
|
||||
}
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
result = super(stock_change_product_qty, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
|
||||
product_id = context and context.get('active_id', False) or False
|
||||
|
||||
if (context.get('active_model') == 'product.product') and product_id:
|
||||
prod_obj = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
|
||||
fields = result.get('fields', {})
|
||||
if fields and (prod_obj.track_production == True) and (fields.get('prodlot_id')):
|
||||
result['fields']['prodlot_id']['required'] = True
|
||||
else:
|
||||
result['fields']['prodlot_id']['required'] = False
|
||||
return result
|
||||
|
||||
def default_get(self, cr, uid, fields, context):
|
||||
""" To get default values for the object.
|
||||
@param self: The object pointer.
|
||||
|
|
|
@ -85,34 +85,18 @@ class stock_invoice_onshipping(osv.osv_memory):
|
|||
raise osv.except_osv(_('Warning !'), _('None of these picking lists require invoicing.'))
|
||||
return res
|
||||
|
||||
|
||||
|
||||
def create_invoice(self, cr, uid, ids, context=None):
|
||||
def open_invoice(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
picking_pool = self.pool.get('stock.picking')
|
||||
data_pool = self.pool.get('ir.model.data')
|
||||
onshipdata_obj = self.read(cr, uid, ids[0], ['journal_id', 'group', 'invoice_date'])
|
||||
if context.get('new_picking', False):
|
||||
onshipdata_obj['id'] = onshipdata_obj.new_picking
|
||||
onshipdata_obj[ids] = onshipdata_obj.new_picking
|
||||
|
||||
context['date_inv'] = onshipdata_obj['invoice_date']
|
||||
invoice_ids = []
|
||||
active_ids = context.get('active_ids', [])
|
||||
active_picking = picking_pool.browse(cr, uid, context.get('active_id',False), context=context)
|
||||
inv_type = picking_pool._get_invoice_type(active_picking)
|
||||
|
||||
res = picking_pool.action_invoice_create(cr, uid, active_ids,
|
||||
journal_id = onshipdata_obj['journal_id'],
|
||||
group = onshipdata_obj['group'],
|
||||
type = None,
|
||||
context=context)
|
||||
data_pool = self.pool.get('ir.model.data')
|
||||
res = self.create_invoice(cr, uid, ids, context=context)
|
||||
invoice_ids += res.values()
|
||||
if not invoice_ids:
|
||||
raise osv.except_osv(_('Error'), _('No Invoices were created'))
|
||||
inv_type = context.get('inv_type', False)
|
||||
action_model = False
|
||||
action = {}
|
||||
if not invoice_ids:
|
||||
raise osv.except_osv(_('Error'), _('No Invoices were created'))
|
||||
if inv_type == "out_invoice":
|
||||
action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree1")
|
||||
elif inv_type == "in_invoice":
|
||||
|
@ -127,6 +111,26 @@ class stock_invoice_onshipping(osv.osv_memory):
|
|||
action['domain'] = "[('id','in', ["+','.join(map(str,invoice_ids))+"])]"
|
||||
return action
|
||||
|
||||
def create_invoice(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
picking_pool = self.pool.get('stock.picking')
|
||||
onshipdata_obj = self.read(cr, uid, ids, ['journal_id', 'group', 'invoice_date'])
|
||||
if context.get('new_picking', False):
|
||||
onshipdata_obj['id'] = onshipdata_obj.new_picking
|
||||
onshipdata_obj[ids] = onshipdata_obj.new_picking
|
||||
context['date_inv'] = onshipdata_obj[0]['invoice_date']
|
||||
active_ids = context.get('active_ids', [])
|
||||
active_picking = picking_pool.browse(cr, uid, context.get('active_id',False), context=context)
|
||||
inv_type = picking_pool._get_invoice_type(active_picking)
|
||||
context['inv_type'] = inv_type
|
||||
res = picking_pool.action_invoice_create(cr, uid, active_ids,
|
||||
journal_id = onshipdata_obj[0]['journal_id'],
|
||||
group = onshipdata_obj[0]['group'],
|
||||
type = None,
|
||||
context=context)
|
||||
return res
|
||||
|
||||
stock_invoice_onshipping()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<field name="invoice_date" />
|
||||
<separator string="" colspan="4" />
|
||||
<button special="cancel" string="_Cancel" icon='gtk-cancel'/>
|
||||
<button name="create_invoice" string="Create" type="object" icon="terp-gtk-go-back-rtl"/>
|
||||
<button name="open_invoice" string="Create" type="object" icon="terp-gtk-go-back-rtl"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -33,51 +33,71 @@ class stock_partial_picking(osv.osv_memory):
|
|||
'product_moves_in' : fields.one2many('stock.move.memory.in', 'wizard_id', 'Moves'),
|
||||
}
|
||||
|
||||
def __is_in(self,cr, uid, pick_ids):
|
||||
def get_picking_type(self, cr, uid, picking, context=None):
|
||||
picking_type = picking.type
|
||||
for move in picking.move_lines:
|
||||
if picking.type == 'in' and move.product_id.cost_method == 'average':
|
||||
picking_type = 'in'
|
||||
break
|
||||
else:
|
||||
picking_type = 'out'
|
||||
return picking_type
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
""" To get default values for the object.
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
@param uid: ID of the user currently logged in
|
||||
@param fields: List of fields for which we want default values
|
||||
@param context: A standard dictionary
|
||||
@return: A dictionary which of fields with values.
|
||||
"""
|
||||
@return: True if one of the moves has as picking type 'in'
|
||||
"""
|
||||
if not pick_ids:
|
||||
return False
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
|
||||
picking_ids = context.get('active_ids', [])
|
||||
if not picking_ids:
|
||||
return res
|
||||
|
||||
result = []
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
|
||||
pick_type = self.get_picking_type(cr, uid, pick, context=context)
|
||||
for m in pick.move_lines:
|
||||
if m.state in ('done', 'cancel'):
|
||||
continue
|
||||
result.append(self.__create_partial_picking_memory(m, pick_type))
|
||||
|
||||
if 'product_moves_in' in fields:
|
||||
res.update({'product_moves_in': result})
|
||||
if 'product_moves_out' in fields:
|
||||
res.update({'product_moves_out': result})
|
||||
if 'date' in fields:
|
||||
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
|
||||
return res
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
|
||||
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
pick_ids = pick_obj.search(cr, uid, [('id','in',pick_ids)])
|
||||
|
||||
|
||||
for pick in pick_obj.browse(cr, uid, pick_ids):
|
||||
for move in pick.move_lines:
|
||||
if pick.type == 'in' and move.product_id.cost_method == 'average':
|
||||
return True
|
||||
return False
|
||||
|
||||
def __get_picking_type(self, cr, uid, pick_ids):
|
||||
if self.__is_in(cr, uid, pick_ids):
|
||||
return "product_moves_in"
|
||||
else:
|
||||
return "product_moves_out"
|
||||
|
||||
def view_init(self, cr, uid, fields_list, context=None):
|
||||
res = super(stock_partial_picking, self).view_init(cr, uid, fields_list, context=context)
|
||||
return res
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
|
||||
result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
|
||||
|
||||
|
||||
picking_ids = context.get('active_ids', False)
|
||||
picking_type = self.__get_picking_type(cr, uid, picking_ids)
|
||||
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
|
||||
picking_type = self.get_picking_type(cr, uid, pick, context=context)
|
||||
|
||||
_moves_arch_lst = """<form string="%s">
|
||||
<field name="date" invisible="1"/>
|
||||
<separator colspan="4" string="%s"/>
|
||||
<field name="%s" colspan="4" nolabel="1" mode="tree,form" width="550" height="200" ></field>
|
||||
""" % (_('Process Document'), _('Products'), picking_type)
|
||||
""" % (_('Process Document'), _('Products'), "product_moves_" + picking_type)
|
||||
_moves_fields = result['fields']
|
||||
|
||||
# add field related to picking type only
|
||||
_moves_fields.update({
|
||||
'product_moves_in' : {'relation': 'stock.move.memory.in', 'type' : 'one2many', 'string' : 'Product Moves'},
|
||||
'product_moves_out' : {'relation': 'stock.move.memory.out', 'type' : 'one2many', 'string' : 'Product Moves'}
|
||||
'product_moves_' + picking_type: {'relation': 'stock.move.memory.'+picking_type, 'type' : 'one2many', 'string' : 'Product Moves'},
|
||||
})
|
||||
|
||||
|
||||
_moves_arch_lst += """
|
||||
<separator string="" colspan="4" />
|
||||
<label string="" colspan="2"/>
|
||||
|
@ -92,44 +112,22 @@ class stock_partial_picking(osv.osv_memory):
|
|||
result['fields'] = _moves_fields
|
||||
return result
|
||||
|
||||
def __create_partial_picking_memory(self, picking, is_in):
|
||||
def __create_partial_picking_memory(self, picking, pick_type):
|
||||
move_memory = {
|
||||
'product_id' : picking.product_id.id,
|
||||
'quantity' : picking.product_qty,
|
||||
'product_uom' : picking.product_uom.id,
|
||||
'prodlot_id' : picking.prodlot_id.id,
|
||||
'move_id' : picking.id,
|
||||
'product_id' : picking.product_id.id,
|
||||
'quantity' : picking.product_qty,
|
||||
'product_uom' : picking.product_uom.id,
|
||||
'prodlot_id' : picking.prodlot_id.id,
|
||||
'move_id' : picking.id,
|
||||
}
|
||||
|
||||
if is_in:
|
||||
if pick_type == 'in':
|
||||
move_memory.update({
|
||||
'cost' : picking.product_id.standard_price,
|
||||
'currency' : picking.product_id.company_id and picking.product_id.company_id.currency_id and picking.product_id.company_id.currency_id.id or False,
|
||||
'cost' : picking.product_id.standard_price,
|
||||
'currency' : picking.product_id.company_id.currency_id.id,
|
||||
})
|
||||
return move_memory
|
||||
|
||||
def __get_active_stock_pickings(self, cr, uid, context=None):
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
res = []
|
||||
for pick in pick_obj.browse(cr, uid, context.get('active_ids', []), context):
|
||||
need_product_cost = (pick.type == 'in')
|
||||
for m in pick.move_lines:
|
||||
if m.state in ('done', 'cancel'):
|
||||
continue
|
||||
res.append(self.__create_partial_picking_memory(m, need_product_cost))
|
||||
|
||||
return res
|
||||
|
||||
_defaults = {
|
||||
'product_moves_in' : __get_active_stock_pickings,
|
||||
'product_moves_out' : __get_active_stock_pickings,
|
||||
'date' : lambda *a : time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
}
|
||||
|
||||
|
||||
def do_partial(self, cr, uid, ids, context=None):
|
||||
""" Makes partial moves and pickings done.
|
||||
@param self: The object pointer.
|
||||
|
@ -140,6 +138,9 @@ class stock_partial_picking(osv.osv_memory):
|
|||
@return: A dictionary which of fields with values.
|
||||
"""
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
move_obj = self.pool.get('stock.move')
|
||||
location_obj = self.pool.get('stock.location')
|
||||
|
||||
picking_ids = context.get('active_ids', False)
|
||||
partial = self.browse(cr, uid, ids[0], context=context)
|
||||
partial_datas = {
|
||||
|
@ -147,40 +148,24 @@ class stock_partial_picking(osv.osv_memory):
|
|||
}
|
||||
|
||||
for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
|
||||
need_product_cost = (pick.type == 'in')
|
||||
moves_list = need_product_cost and partial.product_moves_in or partial.product_moves_out
|
||||
p_moves = {}
|
||||
for product_move in moves_list:
|
||||
p_moves[product_move.move_id.id] = product_move
|
||||
|
||||
|
||||
for move in pick.move_lines:
|
||||
if move.state in ('done', 'cancel'):
|
||||
continue
|
||||
if not p_moves.get(move.id):
|
||||
continue
|
||||
|
||||
partial_datas['move%s' % (move.id)] = {
|
||||
'product_id' : p_moves[move.id].id,
|
||||
'product_qty' : p_moves[move.id].quantity,
|
||||
'product_uom' :p_moves[move.id].product_uom.id,
|
||||
'prodlot_id' : p_moves[move.id].prodlot_id.id,
|
||||
picking_type = self.get_picking_type(cr, uid, pick, context=context)
|
||||
moves_list = picking_type == 'in' and partial.product_moves_in or partial.product_moves_out
|
||||
|
||||
for move in moves_list:
|
||||
partial_datas['move%s' % (move.move_id.id)] = {
|
||||
'product_id': move.id,
|
||||
'product_qty': move.quantity,
|
||||
'product_uom': move.product_uom.id,
|
||||
'prodlot_id': move.prodlot_id.id,
|
||||
}
|
||||
|
||||
|
||||
if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
|
||||
partial_datas['move%s' % (move.id)].update({
|
||||
'product_price' : p_moves[move.id].cost,
|
||||
'product_currency': p_moves[move.id].currency.id,
|
||||
if (picking_type == 'in') and (move.product_id.cost_method == 'average'):
|
||||
partial_datas['move%s' % (move.move_id.id)].update({
|
||||
'product_price' : move.cost,
|
||||
'product_currency': move.currency.id,
|
||||
})
|
||||
pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
|
||||
return {}
|
||||
|
||||
stock_partial_picking()
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -53,10 +53,8 @@ class stock_return_picking(osv.osv_memory):
|
|||
res['invoice_state'] = 'none'
|
||||
for line in pick.move_lines:
|
||||
return_id = 'return%s'%(line.id)
|
||||
return_price = 'return_price%s'%(line.id)
|
||||
if return_id in fields:
|
||||
res[return_id] = line.product_qty
|
||||
res[return_price]=line.price_unit
|
||||
return res
|
||||
|
||||
def view_init(self, cr, uid, fields_list, context=None):
|
||||
|
@ -88,11 +86,8 @@ class stock_return_picking(osv.osv_memory):
|
|||
valid_lines += 1
|
||||
if 'return%s'%(m.id) not in self._columns:
|
||||
self._columns['return%s'%(m.id)] = fields.float(string=m.name, required=True)
|
||||
if 'return_price%s'%(m.id) not in self._columns:
|
||||
self._columns['return_price%s'%(m.id)] = fields.float(string=m.name, required=True)
|
||||
if 'invoice_state' not in self._columns:
|
||||
self._columns['invoice_state'] = fields.selection([('2binvoiced', 'To be refunded/invoiced'), ('none', 'No invoicing')], string='Invoicing', required=True)
|
||||
|
||||
if not valid_lines:
|
||||
raise osv.except_osv(_('Warning !'), _("There are no products to return (only lines in Done state and not fully returned yet can be returned)!"))
|
||||
return res
|
||||
|
@ -126,10 +121,6 @@ class stock_return_picking(osv.osv_memory):
|
|||
if m.state=='done' and quantity > return_history[m.id]:
|
||||
arch_lst.append('<field name="return%s"/>\n<newline/>' % (m.id,))
|
||||
res['fields']['return%s' % m.id]={'string':m.name, 'type':'float', 'required':True}
|
||||
|
||||
if m.product_id.cost_method == 'average' and pick.type == 'in':
|
||||
arch_lst.append('<field name="return_price%s"/>\n<newline/>' % (m.id,))
|
||||
res['fields']['return_price%s' % m.id]={'string':'Price', 'type':'float', 'required':True}
|
||||
res.setdefault('returns', []).append(m.id)
|
||||
arch_lst.append('<field name="invoice_state"/>\n<newline/>')
|
||||
res['fields']['invoice_state']={'string':_('Invoicing'), 'type':'selection','required':True, 'selection':[('2binvoiced', _('To be refunded/invoiced')), ('none', _('No invoicing'))]}
|
||||
|
@ -142,7 +133,7 @@ class stock_return_picking(osv.osv_memory):
|
|||
return res
|
||||
|
||||
def create_returns(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
"""
|
||||
Creates return picking.
|
||||
@param self: The object pointer.
|
||||
@param cr: A database cursor
|
||||
|
@ -152,13 +143,13 @@ class stock_return_picking(osv.osv_memory):
|
|||
@return: A dictionary which of fields with values.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
context = {}
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
move_obj = self.pool.get('stock.move')
|
||||
pick_obj = self.pool.get('stock.picking')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
|
||||
|
||||
pick = pick_obj.browse(cr, uid, record_id, context=context)
|
||||
data = self.read(cr, uid, ids[0])
|
||||
new_picking = None
|
||||
|
@ -180,7 +171,6 @@ class stock_return_picking(osv.osv_memory):
|
|||
new_location=move.location_dest_id.id
|
||||
if move.state=='done':
|
||||
new_qty = data['return%s' % move.id]
|
||||
price_unit = data['return_price%s' % move.id]
|
||||
returned_qty = move.product_qty
|
||||
|
||||
for rec in move.move_history_ids2:
|
||||
|
@ -188,6 +178,7 @@ class stock_return_picking(osv.osv_memory):
|
|||
|
||||
if returned_qty != new_qty:
|
||||
set_invoice_state_to_none = False
|
||||
|
||||
if new_qty:
|
||||
returned_lines += 1
|
||||
new_move=move_obj.copy(cr, uid, move.id, {
|
||||
|
@ -196,8 +187,7 @@ class stock_return_picking(osv.osv_memory):
|
|||
new_qty, move.product_uos.id),
|
||||
'picking_id':new_picking, 'state':'draft',
|
||||
'location_id':new_location, 'location_dest_id':move.location_id.id,
|
||||
'date':date_cur,
|
||||
'price_unit':price_unit})
|
||||
'date':date_cur,})
|
||||
move_obj.write(cr, uid, [move.id], {'move_history_ids2':[(4,new_move)]})
|
||||
|
||||
if not returned_lines:
|
||||
|
|
Loading…
Reference in New Issue