[IMP] sale: put stat button with invoices on sale order.

invoice_exists field has been removed, because invoice_count can be used when the
old field was used.
invoiced_rate field has been removed, because it was never used except in a
test.

Also added a stat button with deliveries on sale order.
This commit is contained in:
Amit Vora
2015-03-11 11:13:37 +01:00
committed by Thibault Delavallée
parent 6de2fa858a
commit d6fe36f1f7
7 changed files with 61 additions and 70 deletions
+11 -5
View File
@@ -416,15 +416,21 @@ class purchase_order(osv.osv):
mod_obj = self.pool.get('ir.model.data')
act_obj = self.pool.get('ir.actions.act_window')
result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree2')
id = result and result[1] or False
result = act_obj.read(cr, uid, [id], context=context)[0]
action_id = mod_obj.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree2')
result = act_obj.read(cr, uid, action_id, context=context)
inv_ids = []
for po in self.browse(cr, uid, ids, context=context):
inv_ids+= [invoice.id for invoice in po.invoice_ids]
inv_ids += [invoice.id for invoice in po.invoice_ids]
if not inv_ids:
raise UserError(_('Please create Invoices.'))
result['domain'] = [('id', 'in', inv_ids)]
if len(inv_ids) > 1:
result['domain'] = [('id', 'in', inv_ids)]
else:
res = mod_obj.xmlid_to_res_id(cr, uid, 'account.invoice_supplier_form')
result['views'] = [(res, 'form')]
result['res_id'] = inv_ids and inv_ids[0] or False
return result
def view_invoice(self, cr, uid, ids, context=None):
'''
+15 -48
View File
@@ -68,47 +68,7 @@ class sale_order(osv.osv):
res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
return res
def _invoiced_rate(self, cursor, user, ids, name, arg, context=None):
res = {}
for sale in self.browse(cursor, user, ids, context=context):
if sale.invoiced:
res[sale.id] = 100.0
continue
tot = 0.0
for invoice in sale.invoice_ids:
if invoice.state not in ('draft', 'cancel'):
tot += invoice.amount_untaxed
if tot:
res[sale.id] = min(100.0, tot * 100.0 / (sale.amount_untaxed or 1.00))
else:
res[sale.id] = 0.0
return res
def _invoice_exists(self, cursor, user, ids, name, arg, context=None):
res = {}
for sale in self.browse(cursor, user, ids, context=context):
res[sale.id] = False
if sale.invoice_ids:
res[sale.id] = True
return res
def _invoiced(self, cursor, user, ids, name, arg, context=None):
res = {}
for sale in self.browse(cursor, user, ids, context=context):
res[sale.id] = True
invoice_existence = False
for invoice in sale.invoice_ids:
if invoice.state!='cancel':
invoice_existence = True
if invoice.state != 'paid':
res[sale.id] = False
break
if not invoice_existence or sale.state == 'manual':
res[sale.id] = False
return res
def _invoiced_search(self, cursor, user, obj, name, args, context=None):
def _search_invoiced(self, cursor, user, obj, name, args, context=None):
if not len(args):
return []
clause = ''
@@ -169,6 +129,17 @@ class sale_order(osv.osv):
return int(team_ids[0][0])
return None
def _get_invoiced(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for order in self.browse(cr, uid, ids, context=context):
res[order.id] = {
'invoice_count': len(order.invoice_ids),
'invoiced': False,
}
if order.state != 'manual' and any(invoice.state == 'paid' for invoice in order.invoice_ids):
res[order.id]['invoiced'] = True
return res
_columns = {
'name': fields.char('Order Reference', required=True, copy=False,
readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, select=True),
@@ -206,13 +177,9 @@ class sale_order(osv.osv):
'order_line': fields.one2many('sale.order.line', 'order_id', 'Order Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=True),
'invoice_ids': fields.many2many('account.invoice', 'sale_order_invoice_rel', 'order_id', 'invoice_id', 'Invoices', readonly=True, copy=False, help="This is the list of invoices that have been generated for this sales order. The same sales order may have been invoiced in several times (by line for example)."),
'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced Ratio', type='float'),
'invoiced': fields.function(_invoiced, string='Paid',
fnct_search=_invoiced_search, type='boolean', help="It indicates that an invoice has been paid."),
'invoice_exists': fields.function(_invoice_exists, string='Invoiced',
fnct_search=_invoiced_search, type='boolean', help="It indicates that sales order has at least one invoice."),
'invoice_count': fields.function(_get_invoiced, type='integer', string='Invoices', multi="counts"),
'invoiced': fields.function(_get_invoiced, fnct_search=_search_invoiced, type='boolean', string='Paid', multi="counts"),
'note': fields.text('Terms and conditions'),
'amount_untaxed': fields.function(_amount_all_wrapper, digits_compute=dp.get_precision('Account'), string='Untaxed Amount',
store={
'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10),
@@ -682,7 +649,7 @@ class sale_order(osv.osv):
def action_ignore_delivery_exception(self, cr, uid, ids, context=None):
for sale_order in self.browse(cr, uid, ids, context=context):
self.write(cr, uid, ids, {'state': 'progress' if sale_order.invoice_exists else 'manual'}, context=context)
self.write(cr, uid, ids, {'state': 'progress' if sale_order.invoice_count else 'manual'}, context=context)
return True
def action_ship_create(self, cr, uid, ids, context=None):
+16 -8
View File
@@ -99,8 +99,6 @@
<button name="print_quotation" string="Print" type="object" states="draft" class="oe_highlight" groups="base.group_user"/>
<button name="print_quotation" string="Print" type="object" states="sent,progress,manual" groups="base.group_user"/>
<button name="action_button_confirm" states="draft" string="Confirm Sale" type="object" groups="base.group_user"/>
<button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight"
attrs="{'invisible': [('invoice_exists', '=', False)]}" groups="base.group_user"/>
<button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice"
type="action" states="manual" class="oe_highlight" groups="base.group_user"/>
<button name="copy_quotation" states="cancel" string="New Copy of Quotation" type="object"/>
@@ -110,11 +108,22 @@
<field name="state" widget="statusbar" statusbar_visible="draft,sent,progress,done" statusbar_colors='{"invoice_except":"red","waiting_date":"blue"}'/>
</header>
<sheet>
<h1>
<label string="Quotation " attrs="{'invisible': [('state','not in',('draft','sent'))]}"/>
<label string="Sales Order " attrs="{'invisible': [('state','in',('draft','sent'))]}"/>
<field name="name" class="oe_inline" readonly="1"/>
</h1>
<div class="oe_title">
<h1>
<label string="Quotation " attrs="{'invisible': [('state', 'not in', ('draft', 'sent'))]}"/>
<label string="Sales Order " attrs="{'invisible': [('state', 'in', ('draft', 'sent'))]}"/>
<field name="name" class="oe_inline" readonly="1"/>
</h1>
</div>
<div class="oe_right oe_button_box" name="buttons">
<button name="action_view_invoice"
type="object"
class="oe_stat_button"
icon="fa-pencil-square-o"
attrs="{'invisible': [('invoice_count', '=', 0)]}" groups="base.group_user">
<field name="invoice_count" widget="statinfo" string="Invoices"/>
</button>
</div>
<group>
<group>
<field name="partner_id" on_change="onchange_partner_id(partner_id, context)" domain="[('customer','=',True)]" context="{'search_default_customer':1, 'show_address': 1}" options='{"always_reload": True}'/>
@@ -221,7 +230,6 @@
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'account.group_account_invoice', 'base.group_sale_salesman_all_leads']}"/>
<field name="team_id" options="{'no_create': True}" groups="base.group_multi_salesteams"/>
<field name="client_order_ref"/>
<field name="invoice_exists" invisible="1"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
<group name="sale_pay" string="Invoicing">
+1 -1
View File
@@ -64,6 +64,6 @@
!python {model: sale.order}: |
sale_order = self.browse(cr, uid, ref("sale_order_2"))
assert sale_order.invoice_ids, "Invoice should be created."
assert sale_order.invoice_exists, "Order is not invoiced."
assert sale_order.invoice_count, "Order is not invoiced."
assert sale_order.invoiced, "Order is not paid."
assert sale_order.state == 'done', 'Order should be Done.'
+9 -2
View File
@@ -89,6 +89,12 @@ class sale_order(osv.osv):
invoice_vals['incoterms_id'] = order.incoterm.id or False
return invoice_vals
def _get_delivery_count(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for order in self.browse(cr, uid, ids, context=context):
res[order.id] = len(picking for picking in order.picking_ids if picking.picking_type_id.code == 'outgoing')
return res
_columns = {
'incoterm': fields.many2one('stock.incoterms', 'Incoterms', help="International Commercial Terms are a series of predefined commercial terms used in international transactions."),
'picking_policy': fields.selection([('direct', 'Deliver each product when available'), ('one', 'Deliver all products at once')],
@@ -105,6 +111,7 @@ class sale_order(osv.osv):
}),
'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
'picking_ids': fields.function(_get_picking_ids, method=True, type='one2many', relation='stock.picking', string='Picking associated to this sale'),
'delivery_count': fields.function(_get_delivery_count, type='integer', string='Delivery Orders'),
}
_defaults = {
'warehouse_id': _get_default_warehouse,
@@ -136,8 +143,8 @@ class sale_order(osv.osv):
#compute the number of delivery orders to display
pick_ids = []
for so in self.browse(cr, uid, ids, context=context):
pick_ids += [picking.id for picking in so.picking_ids]
pick_ids += [picking.id for picking in so.picking_ids if picking.picking_type_id.code == 'outgoing']
#choose the view_mode accordingly
if len(pick_ids) > 1:
result['domain'] = "[('id','in',[" + ','.join(map(str, pick_ids)) + "])]"
+9 -5
View File
@@ -12,11 +12,16 @@
<button name="ship_recreate" states="shipping_except" string="Recreate Delivery Order"/>
<button name="ship_corrected" states="shipping_except" string="Ignore Exception"/>
</xpath>
<xpath expr="//button[@name='action_view_invoice']" position="after">
<xpath expr="//button[@name='action_view_invoice']" position="before">
<field name="picking_ids" invisible="1"/>
<button name="action_view_delivery" string="View Delivery Order" type="object" class="oe_highlight"
attrs="{'invisible': ['|',('picking_ids','=',False),('picking_ids','=',[])]}" groups="base.group_user"/>
</xpath>
<button type="object"
name="action_view_delivery"
class="oe_stat_button"
icon="fa-truck"
attrs="{'invisible': [('delivery_count', '=', 0)]}" groups="base.group_user">
<field name="delivery_count" widget="statinfo" string="Transfers" help="Delivery Orders"/>
</button>
</xpath>
<xpath expr="//button[@name='action_cancel']" position="after">
<button name="ship_cancel" states="shipping_except" string="Cancel Order"/>
</xpath>
@@ -56,7 +61,6 @@
</xpath>
<xpath expr="//group[@name='technical']" position="inside">
<field name="shipped" groups="base.group_no_one"/>
<field name="invoice_exists" invisible="1" groups="base.group_no_one"/>
</xpath>
<xpath expr="//page[@string='Order Lines']/field[@name='order_line']/form[@string='Sales Order Lines']/group/group/field[@name='tax_id']" position="after">
<label for="delay"/>
@@ -218,5 +218,4 @@
!python {model: sale.order}: |
order = self.browse(cr, uid, ref("sale_order_service"))
assert order.invoiced == True, "Sale order is not invoiced."
assert order.invoiced_rate == 100, "Invoiced progress is not 100%."
assert order.state == 'done', 'Order should be in closed.'