[MERGE] branch merged with lp:~openerp-dev/openobject-addons/trunk-dev-addons3

bzr revid: mtr@mtr-20101029052434-65iz1ts0s2wujxrc
This commit is contained in:
mtr
2010-10-29 10:54:34 +05:30
20 changed files with 301 additions and 227 deletions
+1 -1
View File
@@ -327,7 +327,7 @@ class account_cash_statement(osv.osv):
for statement in statement_pool.browse(cr, uid, ids, context=context):
vals = {}
if not self._user_allow(cr, uid, statement.id, context=context):
raise osv.except_osv(_('Error !'), _('User %s does not have rights to access %s journal !' % (statement.user_id.name, statement.journal_id.name)))
raise osv.except_osv(_('Error !'), (_('User %s does not have rights to access %s journal !') % (statement.user_id.name, statement.journal_id.name)))
if statement.name and statement.name == '/':
number = self.pool.get('ir.sequence').get(cr, uid, 'account.cash.statement')
+1 -4
View File
@@ -6283,10 +6283,7 @@ msgstr ""
#. module: account
#: code:addons/account/account_cash_statement.py:0
#, python-format
msgid "User %s does not have rights to access %s journal !' % (statement.user_id.name, statement.journal_id.name)))\n"
"\n"
" if statement.name and statement.name == '/':\n"
" number = self.pool.get('ir.sequence"
msgid "User \"%s\" does not have rights to access \"%s\" journal !"
msgstr ""
#. module: account
+9 -1
View File
@@ -916,7 +916,7 @@ class calendar_event(osv.osv):
return [(x.lower(), x) for x in pytz.all_timezones]
def onchange_allday(self, cr, uid, ids, allday, context=None):
"""Sets duration as 24 Hours if event is selcted for all day
"""Sets duration as 24 Hours if event is selected for all day
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@@ -1630,6 +1630,14 @@ true, it will allow you to hide the event alarm information without removing it.
if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
vals['vtimezone'] = vals['vtimezone'][40:]
updated_vals = self.onchange_dates(cr, uid, [],
vals.get('date', False),
vals.get('duration', False),
vals.get('date_deadline', False),
vals.get('allday', False),
context=context)
vals.update(updated_vals.get('value', {}))
res = super(calendar_event, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
+1 -1
View File
@@ -229,7 +229,7 @@
<group col="6" colspan="4">
<field name="name" select="1" string="Summary"
colspan="4" required="1" />
<field name="allday" colspan="2" on_change="onchange_allday(allday)" />
<field name="allday" colspan="2" on_change="onchange_dates(date,False,False,allday)" />
<newline/>
<field name="date" string="Start Date" required="1" select="1"
on_change="onchange_dates(date,duration,False,allday)" />
+1 -1
View File
@@ -32,7 +32,7 @@
<field name="categ_id" widget="selection"
string="Meeting Type" groups="base.group_extended"
domain="[('object_id.model', '=', 'crm.meeting')]" />
<field name="allday" on_change="onchange_allday(allday)" />
<field name="allday" on_change="onchange_dates(date,False,False,allday)" />
<newline/>
<field name="date" string="Start Date" required="1"
on_change="onchange_dates(date,duration,False,allday)" />
+1 -1
View File
@@ -64,7 +64,7 @@ class crm_helpdesk(crm.crm_case, osv.osv):
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.helpdesk')]"),
'duration': fields.float('Duration'),
'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
+1 -1
View File
@@ -183,7 +183,7 @@ class hr_employee(osv.osv):
return {'value': {'work_email' : work_email}}
def _get_photo(self, cr, uid, context=None):
photo_path = addons.get_module_resource('hr','image','photo.png')
photo_path = addons.get_module_resource('hr','image','photo.png')
return open(photo_path, 'rb').read().encode('base64')
_defaults = {
+22 -13
View File
@@ -42,18 +42,22 @@ class base_report(report_sxw.rml_parse):
self.context = context
def _load(self, name, form):
fiscalyear = self.pool.get('account.fiscalyear').browse(self.cr, self.uid, form['fiscalyear'])
period_query_cond=self.pool.get('account.period').search(self.cr, self.uid, [('fiscalyear_id', '=', form['fiscalyear'])])
fiscalyear = self.pool.get('account.fiscalyear').browse(self.cr, self.uid, form['fiscalyear_id'])
period_ids=self.pool.get('account.period').search(self.cr, self.uid, [('fiscalyear_id', '=', form['fiscalyear_id'])])
self.cr.execute("SELECT MIN(date_start) AS date_start, MAX(date_stop) AS date_stop FROM account_period WHERE id IN %s", (tuple(period_query_cond),))
dates = self.cr.dictfetchall()
self._set_variable('date_start', dates[0]['date_start'])
self._set_variable('date_stop', dates[0]['date_stop'])
if period_ids:
self.cr.execute("SELECT MIN(date_start) AS date_start, MAX(date_stop) AS date_stop FROM account_period WHERE id = ANY(%s)", (period_ids,))
dates = self.cr.dictfetchall()
else:
dates = False
if dates:
self._set_variable('date_start', dates[0]['date_start'])
self._set_variable('date_stop', dates[0]['date_stop'])
self.cr.execute("SELECT l10n_fr_line.code,definition FROM l10n_fr_line LEFT JOIN l10n_fr_report ON l10n_fr_report.id=report_id WHERE l10n_fr_report.code=%s",(name,))
datas = self.cr.dictfetchall()
for line in datas:
self._load_accounts(form,line['code'],eval(line['definition']),fiscalyear,period_query_cond)
self._load_accounts(form,line['code'],eval(line['definition']),fiscalyear,period_ids)
def _set_variable(self, variable, valeur):
self.localcontext.update({variable: valeur})
@@ -61,30 +65,35 @@ class base_report(report_sxw.rml_parse):
def _get_variable(self, variable):
return self.localcontext[variable]
def _load_accounts(self,form,code,definition,fiscalyear,period_query_cond):
def _load_accounts(self, form, code, definition, fiscalyear, period_ids):
accounts = {}
for x in definition['load']:
p = x.split(":")
accounts[p[1]] = [p[0],p[2]]
sum = 0.0
if fiscalyear.state != 'done' or not code.startswith('bpcheck'):
query_params = []
query_cond = "("
for account in accounts:
query_cond += "aa.code LIKE '" + account + "%' OR "
query_cond += "aa.code LIKE '" + account + "%%' OR "
query_cond = query_cond[:-4]+")"
if len(definition['except']) > 0:
query_cond = query_cond+" and ("
for account in definition['except']:
query_cond += "aa.code NOT LIKE '"+account+"%' AND "
query_cond += "aa.code NOT LIKE '"+account+"%%' AND "
query_cond = query_cond[:-5]+")"
closed_cond = ""
if fiscalyear.state == 'done':
closed_cond=" AND (aml.move_id NOT IN (SELECT account_move.id as move_id FROM account_move WHERE period_id IN "+str(tuple(period_query_cond))+" AND journal_id=(SELECT res_id FROM ir_model_data WHERE name='closing_journal' AND module='l10n_fr')) OR (aa.type != 'income' AND aa.type !='expense'))"
closed_cond=" AND (aml.move_id NOT IN (SELECT account_move.id as move_id FROM account_move WHERE period_id = ANY(%s) AND journal_id=(SELECT res_id FROM ir_model_data WHERE name='closing_journal' AND module='l10n_fr')) OR (aa.type != 'income' AND aa.type !='expense'))"
query_params.append(list(period_ids))
query = "SELECT aa.code AS code, SUM(debit) as debit, SUM(credit) as credit FROM account_move_line aml LEFT JOIN account_account aa ON aa.id=aml.account_id WHERE "+query_cond+closed_cond+" AND aml.state='valid' AND aml.period_id IN "+str(tuple(period_query_cond))+" GROUP BY code"
self.cr.execute(query)
query = "SELECT aa.code AS code, SUM(debit) as debit, SUM(credit) as credit " \
" FROM account_move_line aml LEFT JOIN account_account aa ON aa.id=aml.account_id "\
" WHERE "+query_cond+closed_cond+" AND aml.state='valid' AND aml.period_id = ANY(%s) GROUP BY code"
query_params.append(list(period_ids))
self.cr.execute(query, query_params)
lines =self.cr.dictfetchall()
for line in lines:
+5
View File
@@ -7,6 +7,11 @@
date_start: '2012-01-01'
date_stop: '2012-12-31'
name: Fiscal Year 2012
-
I create the fiscal periods
-
!python {model: account.fiscalyear}:
self.create_period(cr, uid, [ref('account_fiscalyear_01'),])
-
In order to test the PDF reports defined on a l10n_fr, we will print an Account Move Line Report for l10n_fr
-
+1 -1
View File
@@ -35,7 +35,7 @@
<field name="password">jth</field>
</record>
<record id="res_users_tester" model="res.users">
<field name="name">Alien</field>
<field name="name">Aline</field>
<field eval="[(6, 0, [ref('base.group_user'), ref('project.group_project_user')])]" name="groups_id"/>
<field name="login">apr</field>
<field name="password">apr</field>
+3 -3
View File
@@ -187,7 +187,7 @@ class purchase_order(osv.osv):
help="From Order: a draft invoice will be pre-generated based on the purchase order. The accountant " \
"will just have to validate this invoice for control.\n" \
"From Picking: a draft invoice will be pre-generated based on validated receptions.\n" \
"Manual: no invoice will be pre-generated. The accountant will have to encode manually."
"Manual: allows you to generate suppliers invoices by chosing in the uninvoiced lines of all manual purchase orders."
),
'minimum_planned_date':fields.function(_minimum_planned_date, fnct_inv=_set_minimum_planned_date, method=True,store=True, string='Expected Date', type='date', help="This is computed as the minimum scheduled date of all purchase order lines' products."),
'amount_untaxed': fields.function(_amount_all, method=True, digits_compute= dp.get_precision('Purchase Price'), string='Untaxed Amount',
@@ -597,7 +597,7 @@ class purchase_order_line(osv.osv):
_columns = {
'name': fields.char('Description', size=256, required=True),
'product_qty': fields.float('Quantity', required=True, digits=(16,2)),
'date_planned': fields.date('Scheduled date', required=True),
'date_planned': fields.date('Scheduled Date', required=True),
'taxes_id': fields.many2many('account.tax', 'purchase_order_taxe', 'ord_id', 'tax_id', 'Taxes'),
'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('purchase_ok','=',True)], change_default=True),
@@ -616,7 +616,7 @@ class purchase_order_line(osv.osv):
\n* The \'Cancelled\' state is set automatically when user cancel purchase order.'),
'invoice_lines': fields.many2many('account.invoice.line', 'purchase_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
'invoiced': fields.boolean('Invoiced', readonly=True),
'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner"),
'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner", store=True),
'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date")
}
+13 -7
View File
@@ -144,10 +144,10 @@
<button name="action_cancel" states="approved,except_picking,except_invoice" string="Cancel Purchase Order" type="object" icon="gtk-cancel"/>
<button name="picking_ok" states="except_picking" string="Manually Corrected" icon="gtk-convert"/>
<button name="invoice_ok" states="except_invoice" string="Manually Corrected" icon="gtk-convert"/>
<button name="purchase_confirm" states="draft" string="Confirm Purchase Order" icon="gtk-go-forward"/>
<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="%(report_purchase_order)d" string="Print" states="approved" type="action" icon="gtk-print"/>
<button name="%(report_purchase_order)d" string="Print" states="approved" type="action" icon="gtk-print"/>
</group>
</page>
@@ -307,12 +307,16 @@
<tree string="Purchase Order Lines">
<field name="order_id"/>
<field name="name"/>
<field name="date_planned" widget="date" width="135"/>
<field name="partner_id" string="Supplier" />
<field name="product_id"/>
<field name="product_qty"/>
<field name="product_uom"/>
<field name="price_unit"/>
<field name="product_qty"/>
<field name="product_uom"/>
<field name="price_subtotal"/>
<field name="date_planned" widget="date" width="135"/>
<field name="state" invisible="1"/>
<field name="invoiced" invisible="1"/>
</tree>
@@ -369,10 +373,12 @@
<group>
<field name="order_id"/>
<field name="product_id"/>
</group>
<field name="partner_id" string="Supplier"/>
</group>
<newline/>
<group expand="0" string="Group By...">
<filter string="Product" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by' : 'product_id'}" />
<filter string="Supplier" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by' : 'partner_id'}" />
<filter icon="terp-gtk-jump-to-rtl" string="Order Reference" domain="[]" context="{'group_by' :'order_id'}"/>
<separator orientation="vertical"/>
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by' : 'state'}" />
@@ -401,7 +407,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">[('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"/>
+58 -23
View File
@@ -24,6 +24,7 @@ import ir
from osv import osv
from tools.translate import _
class purchase_line_invoice(osv.osv_memory):
""" To create invoice for purchase order line"""
@@ -31,7 +32,8 @@ class purchase_line_invoice(osv.osv_memory):
_name = 'purchase.order.line_invoice'
_description = 'Purchase Order Line Make Invoice'
def makeInvoices(self, cr, uid, ids, context):
def makeInvoices(self, cr, uid, ids, context=None):
"""
To get Purchase Order line and create Invoice
@param self: The object pointer.
@@ -39,7 +41,11 @@ class purchase_line_invoice(osv.osv_memory):
@param uid: ID of the user currently logged in
@param context: A standard dictionary
@return : retrun view of Invoice
"""
"""
if context is None:
context={}
record_ids = context.get('active_ids',[])
if record_ids:
res = False
@@ -49,35 +55,63 @@ class purchase_line_invoice(osv.osv_memory):
property_obj=self.pool.get('ir.property')
account_fiscal_obj=self.pool.get('account.fiscal.position')
invoice_line_obj=self.pool.get('account.invoice.line')
def make_invoice(order, lines):
a = order.partner_id.property_account_payable.id
if order.partner_id and order.partner_id.property_payment_term.id:
pay_term = order.partner_id.property_payment_term.id
def multiple_order_invoice_name(orders):
name = "PO";
for order in orders:
name += "-%d" % order.id
return name
def multiple_order_invoice_reference(partner, orders):
reference = "P%dPO" % partner.id
for order in orders:
reference += "-%d" % order.id
return reference
def multiple_order_invoice_notes(orders):
notes = ""
for order in orders:
notes += "%s \n" % order.notes
return notes
def make_invoice_by_partner(partner, orders, lines_ids):
"""
create a new invoice for one supplier
@param partner : The object partner
@param orders : The set of orders to add in the invoice
@param lines : The list of line's id
"""
a = partner.property_account_payable.id
if partner and partner.property_payment_term.id:
pay_term = partner.property_payment_term.id
else:
pay_term = False
inv = {
'name': order.name,
'origin': order.name,
'name': multiple_order_invoice_name(orders),
'origin': multiple_order_invoice_name(orders),
'type': 'in_invoice',
'reference': "P%dPO%d" % (order.partner_id.id, order.id),
'reference': multiple_order_invoice_reference(partner, orders),
'account_id': a,
'partner_id': order.partner_id.id,
'address_invoice_id': order.partner_address_id.id,
'address_contact_id': order.partner_address_id.id,
'invoice_line': [(6,0,lines)],
'currency_id' : order.pricelist_id.currency_id.id,
'comment': order.notes,
'partner_id': partner.id,
'address_invoice_id': orders[0].partner_address_id.id,
'address_contact_id': orders[0].partner_address_id.id,
'invoice_line': [(6,0,lines_ids)],
'currency_id' : orders[0].pricelist_id.currency_id.id,
'comment': multiple_order_invoice_notes(orders),
'payment_term': pay_term,
'fiscal_position': order.partner_id.property_account_position.id
'fiscal_position': partner.property_account_position.id
}
inv_id = invoice_obj.create(cr, uid, inv)
return inv_id
for line in purchase_line_obj.browse(cr,uid,record_ids):
if (not line.invoiced) and (line.state not in ('draft','cancel')):
if not line.order_id.id in invoices:
invoices[line.order_id.id] = []
if not line.partner_id.id in invoices:
invoices[line.partner_id.id] = []
if line.product_id:
a = line.product_id.product_tmpl_id.property_account_expense.id
if not a:
@@ -102,18 +136,19 @@ class purchase_line_invoice(osv.osv_memory):
'uos_id': line.product_uom.id,
'product_id': line.product_id.id or False,
'invoice_line_tax_id': [(6, 0, [x.id for x in line.taxes_id])],
'note': line.notes,
'note': line.notes,
'account_analytic_id': line.account_analytic_id and line.account_analytic_id.id or False,
})
cr.execute('insert into purchase_order_line_invoice_rel (order_line_id,invoice_id) values (%s,%s)', (line.id, inv_id))
purchase_line_obj.write(cr, uid, [line.id], {'invoiced': True})
invoices[line.order_id.id].append((line,inv_id))
invoices[line.partner_id.id].append((line,inv_id))
res = []
for result in invoices.values():
order = result[0][0].order_id
il = map(lambda x: x[1], result)
res.append(make_invoice(order, il))
orders = list(set(map(lambda x : x[0].order_id, result)))
res.append(make_invoice_by_partner(orders[0].partner_id, orders, il))
return {
'domain': "[('id','in', ["+','.join(map(str,res))+"])]",
+6 -6
View File
@@ -470,12 +470,13 @@ class sale_order(osv.osv):
inv_ids = list(inv_ids1.difference(inv_ids))
res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
result = {
res_id = res and res[1] or False,
return {
'name': 'Customer Invoices',
'view_type': 'form',
'view_mode': 'form',
'view_id': [res] and [res[1]] or False,
'view_id': [res_id],
'res_model': 'account.invoice',
'context': "{'type':'out_invoice'}",
'type': 'ir.actions.act_window',
@@ -483,7 +484,6 @@ class sale_order(osv.osv):
'target': 'current',
'res_id': inv_ids and inv_ids[0] or False,
}
return result
def action_invoice_create(self, cr, uid, ids, grouped=False, states=['confirmed', 'done', 'exception'], date_inv = False, context=None):
res = False
@@ -1221,8 +1221,8 @@ class sale_config_picking_policy(osv.osv_memory):
if o.step == 'one':
md = self.pool.get('ir.model.data')
location_id = md.get_object_reference(cr, uid, 'stock', 'stock_location_output')
search_id = location_id and location_id[1] or False
self.pool.get('stock.location').write(cr, uid, search_id, {'chained_auto_packing': 'transparent'})
location_id = location_id and location_id[1] or False
self.pool.get('stock.location').write(cr, uid, [location_id], {'chained_auto_packing': 'transparent'})
sale_config_picking_policy()
+1 -1
View File
@@ -210,7 +210,7 @@
<button name="ship_recreate" states="shipping_except" string="Recreate Procurement" icon="gtk-ok"/>
<button name="ship_corrected" states="shipping_except" string="Procurement Corrected" icon="gtk-apply"/>
<button name="action_cancel" states="manual,progress" string="Cancel Order" type="object" icon="gtk-cancel"/>
<button name="manual_invoice" states="manual" string="Create Invoice" icon="gtk-go-forward" type="object"/>
<button name="manual_invoice" states="manual" string="Create Final Invoice" icon="gtk-go-forward" type="object"/>
<button name="ship_cancel" states="shipping_except" string="Cancel Order" icon="gtk-cancel"/>
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object" icon="gtk-convert"/>
<button name="cancel" states="draft" string="Cancel Order" icon="gtk-cancel"/>
@@ -135,8 +135,8 @@ sale_advance_payment_inv()
class sale_open_invoice(osv.osv_memory):
_name = "sale.open.invoice"
_description = "Sale Open Invoice"
def open_invoice(self, cr, uid, ids, context):
def open_invoice(self, cr, uid, ids, context=None):
"""
To open invoice.
@@ -148,7 +148,8 @@ class sale_open_invoice(osv.osv_memory):
@return:
"""
if context is None:
context = {}
mod_obj = self.pool.get('ir.model.data')
for advance_pay in self.browse(cr, uid, ids):
form_res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form')
@@ -170,4 +171,4 @@ class sale_open_invoice(osv.osv_memory):
sale_open_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+7 -3
View File
@@ -1461,12 +1461,15 @@
====================================
Reception Picking (By Stock Move)
====================================
<!-- from stock_partial_move_view -->
<record id="view_move_tree_reception_picking" model="ir.ui.view">
<field name="name">stock.move.tree2</field>
<field name="model">stock.move</field>
<field name="type">tree</field>
<field eval="6" name="priority"/>
<field name="priority" eval="6" />
<field name="arch" type="xml">
<tree colors="grey:state in ('cancel')" string="Moves">
<field name="picking_id" string="Reference"/>
@@ -1521,6 +1524,7 @@
</tree>
</field>
</record>
<record id="view_move_form_reception_picking" model="ir.ui.view">
<field name="name">stock.move.form2</field>
@@ -1672,7 +1676,7 @@
<field name="view_mode">tree,form</field>
<field name="domain">['|','&amp;',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),'&amp;',('picking_id','!=',False),('picking_id.type','=','in')]</field>
<field name="view_id" ref="view_move_tree_reception_picking"/>
<field name="context" eval="'{\'search_default_receive\':1, \'default_location_id\':%d, \'default_location_dest_id\':%d}' % (ref('stock_location_suppliers'),ref('stock_location_stock'))"/>
<field name="context" eval="'{\'search_default_receive\':1, \'product_receive\' : True, \'default_location_id\':%d, \'default_location_dest_id\':%d}' % (ref('stock_location_suppliers'),ref('stock_location_stock') )"/>
<field name="search_view_id" ref="view_move_search_reception_incoming_picking"/>
<field name="help">You will find here the list of all products you are waiting for, according to your preceding purchase orders. Once you receive an order, you can filter based on the name of the supplier or the purchase order reference. Then you can confirm all products received using the buttons on the right of each line.</field>
</record>
+124 -152
View File
@@ -23,164 +23,124 @@ from osv import fields, osv
from tools.translate import _
import time
class stock_partial_move_memory(osv.osv_memory):
_name = "stock.move.memory"
_rec_name = 'product_id'
_columns = {
'product_id' : fields.many2one('product.product', string="Product", required=True, readonly=True),
'quantity' : fields.float("Quantity", required=True),
'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True, readonly=True),
'prodlot_id' : fields.many2one('stock.production.lot', 'Production Lot'),
'move_id' : fields.many2one('stock.move', "Move"),
'wizard_id' : fields.many2one('stock.partial.move', string="Wizard"),
'cost' : fields.float("Cost", help="Unit Cost for this product line", readonly=True),
'currency' : fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", readonly=True),
}
class stock_partial_move(osv.osv_memory):
_name = "stock.partial.move"
_description = "Partial Move"
_columns = {
'date': fields.datetime('Date', required=True),
'type': fields.char("Type", size=3),
'product_moves' : fields.one2many('stock.move.memory', 'wizard_id', 'Moves'),
}
def view_init(self, cr, uid, fields_list, context=None):
res = super(stock_partial_move, self).view_init(cr, uid, fields_list, context=context)
move_obj = self.pool.get('stock.move')
if not context:
context={}
for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
if m.state in ('done', 'cancel'):
context = {}
for move in move_obj.browse(cr, uid, context.get('active_ids', [])):
if move.state in ('done', 'cancel'):
raise osv.except_osv(_('Invalid action !'), _('Cannot deliver products which are already delivered !'))
if 'move%s_product_id'%(m.id) not in self._columns:
self._columns['move%s_product_id'%(m.id)] = fields.many2one('product.product',string="Product")
if 'move%s_product_qty'%(m.id) not in self._columns:
self._columns['move%s_product_qty'%(m.id)] = fields.float("Quantity")
if 'move%s_product_uom'%(m.id) not in self._columns:
self._columns['move%s_product_uom'%(m.id)] = fields.many2one('product.uom',string="Product UOM")
if 'move%s_prodlot_id'%(m.id) not in self._columns:
self._columns['move%s_prodlot_id'%(m.id)] = fields.many2one('stock.production.lot', string="Lot")
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
if 'move%s_product_price'%(m.id) not in self._columns:
self._columns['move%s_product_price'%(m.id)] = fields.float("Cost", help="Unit Cost for this product line")
if 'move%s_product_currency'%(m.id) not in self._columns:
self._columns['move%s_product_currency'%(m.id)] = fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed")
return res
def __create_partial_move_memory(self, move):
move_memory = {
'product_id' : move.product_id.id,
'quantity' : move.product_qty,
'product_uom' : move.product_uom.id,
'prodlot_id' : move.prodlot_id.id,
'move_id' : move.id,
}
if move.picking_id.type == 'in':
move_memory.update({
'cost' : move.product_id.standard_price,
'currency' : move.product_id.company_id.currency_id.id,
})
return move_memory
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
result = super(stock_partial_move, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
def __get_active_stock_moves(self, cr, uid, context=None):
move_obj = self.pool.get('stock.move')
move_ids = context.get('active_ids', False)
move_ids = move_obj.search(cr, uid, [('id','in',move_ids)])
_moves_arch_lst = """<form string="Deliver Products">
<separator colspan="4" string="Delivery Information"/>
<field name="date" colspan="2"/>
<separator colspan="4" string="Move Detail"/>
"""
_moves_fields = result['fields']
if move_ids and view_type in ['form']:
for m in move_obj.browse(cr, uid, move_ids, context):
if m.state in ('done', 'cancel'):
continue
_moves_fields.update({
'move%s_product_id'%(m.id) : {
'string': _('Product'),
'type' : 'many2one',
'relation': 'product.product',
'required' : True,
'readonly' : True,
},
'move%s_product_qty'%(m.id) : {
'string': _('Quantity'),
'type' : 'float',
'required': True,
},
'move%s_product_uom'%(m.id) : {
'string': _('Product UOM'),
'type' : 'many2one',
'relation': 'product.uom',
'required' : True,
'readonly' : True,
},
'move%s_prodlot_id'%(m.id): {
'string': _('Production Lot'),
'type': 'many2one',
'relation': 'stock.production.lot',
}
})
if not context:
context = {}
res = []
for move in move_obj.browse(cr, uid, context.get('active_ids', [])):
if move.state in ('done', 'cancel'):
continue
res.append(self.__create_partial_move_memory(move))
return res
_defaults = {
'product_moves' : __get_active_stock_moves,
'date' : time.strftime('%Y-%m-%d %H:%M:%S'),
}
_moves_arch_lst += """
<group colspan="4" col="10">
<field name="move%s_product_id" nolabel="1"/>
<field name="move%s_product_qty" string="Qty" />
<field name="move%s_product_uom" nolabel="1" />
<field name="move%s_prodlot_id" domain="[('product_id','=',move%s_product_id)]" groups="base.group_extended" />
"""%(m.id, m.id, m.id,m.id,m.id)
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
_moves_fields.update({
'move%s_product_price'%(m.id) : {
'string': _('Cost'),
'type' : 'float',
'help': _('Unit Cost for this product line'),
},
'move%s_product_currency'%(m.id): {
'string': _('Currency'),
'type' : 'many2one',
'relation': 'res.currency',
'help': _("Currency in which Unit Cost is expressed"),
}
})
_moves_arch_lst += """
<field name="move%s_product_price" />
<field name="move%s_product_currency" nolabel="1"/>
"""%(m.id, m.id)
_moves_arch_lst += """
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
height = 2 * 25;
message = {
'title' : _('Deliver Products'),
'info' : _('Delivery Information'),
'button' : _('Deliver'),
}
if context:
height = (len(context.get('active_ids', [])) + 1) * 25
if context.get('product_receive', False):
message = {
'title' : _('Receive Products'),
'info' : _('Receive Information'),
'button' : _('Receive'),
}
message['height'] = height
result = super(stock_partial_move, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
_moves_fields = result['fields']
_moves_fields.update({'product_moves' :
{
'relation': 'stock.move.memory',
'type' : 'one2many',
'string' : 'Product Moves',
}
})
_moves_arch_lst = """
<form string="%(title)s">
<separator colspan="4" string="%(info)s"/>
<field name="date" colspan="2"/>
<separator colspan="4" string="Move Detail"/>
<field name="product_moves" colspan="4" nolabel="1" width="550" height="200" />
<separator string="" colspan="4" />
<label string="" colspan="2"/>
<group col="2" colspan="2">
<button icon='gtk-cancel' special="cancel" string="_Cancel" />
<button name="do_partial" string="%(button)s"
colspan="1" type="object" icon="gtk-apply" />
</group>
"""
_moves_arch_lst += """
<separator string="" colspan="4" />
<label string="" colspan="2"/>
<group col="2" colspan="2">
<button icon='gtk-cancel' special="cancel"
string="_Cancel" />
<button name="do_partial" string="_Deliver"
colspan="1" type="object" icon="gtk-apply" />
</group>
</form>"""
</form> """ % message
result['arch'] = _moves_arch_lst
result['fields'] = _moves_fields
return result
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.
"""
res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
move_obj = self.pool.get('stock.move')
if not context:
context={}
if 'date' in fields:
res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
move_ids = context.get('active_ids', [])
move_ids = move_obj.search(cr, uid, [('id','in',move_ids)])
for m in move_obj.browse(cr, uid, context.get('active_ids', [])):
if m.state in ('done', 'cancel'):
continue
res['type'] = m.picking_id and m.picking_id.type or ''
if 'move%s_product_id'%(m.id) in fields:
res['move%s_product_id'%(m.id)] = m.product_id.id
if 'move%s_product_qty'%(m.id) in fields:
res['move%s_product_qty'%(m.id)] = m.product_qty
if 'move%s_product_uom'%(m.id) in fields:
res['move%s_product_uom'%(m.id)] = m.product_uom.id
if 'move%s_prodlot_id'%(m.id) in fields:
res['move%s_prodlot_id'%(m.id)] = m.prodlot_id.id
if m.picking_id.type == 'in' and m.product_id.cost_method == 'average':
# Always use default product cost and currency from Product Form,
# which belong to the Company owning the product
currency = m.product_id.company_id.currency_id.id
price = m.product_id.standard_price
if 'move%s_product_price'%(m.id) in fields:
res['move%s_product_price'%(m.id)] = price
if 'move%s_product_currency'%(m.id) in fields:
res['move%s_product_currency'%(m.id)] = currency
return res
def do_partial(self, cr, uid, ids, context):
""" Makes partial moves and pickings done.
@param self: The object pointer.
@@ -190,32 +150,44 @@ class stock_partial_move(osv.osv_memory):
@param context: A standard dictionary
@return: A dictionary which of fields with values.
"""
move_obj = self.pool.get('stock.move')
move_ids = context.get('active_ids', False)
partial = self.browse(cr, uid, ids[0], context)
partial_datas = {
'delivery_date' : partial.date
}
for m in move_obj.browse(cr, uid, move_ids):
if m.state in ('done', 'cancel'):
p_moves = {}
for product_move in partial.product_moves:
p_moves[product_move.move_id.id] = product_move
moves_ids_final = []
for move in move_obj.browse(cr, uid, move_ids):
if move.state in ('done', 'cancel'):
continue
partial_datas['move%s'%(m.id)] = {
'product_id' : getattr(partial, 'move%s_product_id'%(m.id)).id,
'product_qty' : getattr(partial, 'move%s_product_qty'%(m.id)),
'product_uom' : getattr(partial, 'move%s_product_uom'%(m.id)).id,
'prodlot_id' : getattr(partial, 'move%s_prodlot_id'%(m.id)).id
if not p_moves.get(move.id, False):
continue
partial_datas['move%s' % (move.id)] = {
'product_id' : p_moves[move.id].product_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,
}
if (m.picking_id.type == 'in') and (m.product_id.cost_method == 'average'):
partial_datas['move%s'%(m.id)].update({
'product_price' : getattr(partial, 'move%s_product_price'%(m.id)),
'product_currency': getattr(partial, 'move%s_product_currency'%(m.id)).id
moves_ids_final.append(move.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,
})
move_obj.do_partial(cr, uid, move_ids, partial_datas, context=context)
move_obj.do_partial(cr, uid, moves_ids_final, partial_datas, context=context)
return {}
stock_partial_move()
stock_partial_move_memory()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -2,13 +2,49 @@
<openerp>
<data>
<act_window name="Deliver Products"
<act_window name="Deliver/Receive Products"
res_model="stock.partial.move"
src_model="stock.move"
view_mode="form"
multi="True"
target="new"
key2="client_action_multi"
id="action_partial_move"/>
id="action_partial_move"></act_window>
<record id="stock_move_memory_tree" model="ir.ui.view">
<field name="name">stock.move.memory.tree</field>
<field name="model">stock.move.memory</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree editable="bottom" string="Product Moves">
<field name="product_id" readonly="1" />
<field name="quantity" ></field>
<field name="product_uom"></field>
<field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" ></field>
<field name="cost"></field>
<field name="currency" ></field>
</tree>
</field>
</record>
<record id="stock_move_memory_form" model="ir.ui.view">
<field name="name">stock.move.memory.form</field>
<field name="model">stock.move.memory</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form>
<field name="product_id" readonly="1" />
<field name="quantity" ></field>
<field name="product_uom"></field>
<field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" ></field>
<field name="cost"></field>
<field name="currency"></field>
</form>
</field>
</record>
</data>
</openerp>
+2 -1
View File
@@ -231,7 +231,8 @@ sale_order_line()
class purchase_order_line(osv.osv):
_inherit = 'purchase.order.line'
def product_id_change(self,cr, uid, ids, pricelist, product, qty, uom,
partner_id, date_order=False, fiscal_position=False):
partner_id, date_order=False, fiscal_position=False, date_planned=False,
name=False, price_unit=False, notes=False):
warning = {}
if not product:
return {'value': {'price_unit': 0.0, 'name':'','notes':'', 'product_uom' : False}, 'domain':{'product_uom':[]}}