diff options
| author | Thibault Delavallée <tde@openerp.com> | 2012-09-19 13:10:00 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2012-09-19 13:10:00 +0200 |
| commit | fa27dde6c97add97226a27610845cef183353c26 (patch) | |
| tree | 27698e9e87b5b3fbe3ff8b898a25140fbf16d774 /addons | |
| parent | 9ec025be0ed4a896b37b0323fe427e39f6abb13c (diff) | |
| parent | 819455b73cbc336142579c788445b4d4734bd83f (diff) | |
[MERGE] Merged with addons/trunk.
bzr revid: tde@openerp.com-20120919111000-w3xmyatd6new8ghm
Diffstat (limited to 'addons')
42 files changed, 926 insertions, 270 deletions
diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index 89066ce74bb..0ea2be4f37f 100644 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -418,7 +418,7 @@ <field name="type">ir.actions.act_window</field> <field name="res_model">calendar.event</field> <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar</field> + <field name="view_mode">calendar,tree,form</field> <field name="search_view_id" ref="view_calendar_event_filter"/> </record> diff --git a/addons/base_setup/res_partner_view.xml b/addons/base_setup/res_partner_view.xml index 5e54c0b8629..15b80151831 100644 --- a/addons/base_setup/res_partner_view.xml +++ b/addons/base_setup/res_partner_view.xml @@ -9,14 +9,11 @@ <field name="inherit_id" ref="base.res_partner_kanban_view"/> <field name="arch" type="xml"> <xpath expr="//div[@class='oe_kanban_partner_categories']" position="inside"> - <span class="oe_kanban_list_many2many" data-model="res.partner.category"> - <t t-foreach="record.category_id.raw_value" t-as="category"> - <span class="oe_tag" t-att-data-list_id="category"/> - </t> + <span class="oe_kanban_list_many2many"> + <field name="category_id"/> </span> </xpath> </field> </record> - </data> </openerp> diff --git a/addons/board/static/src/css/dashboard.css b/addons/board/static/src/css/dashboard.css index ed66e338c81..f2bbcd07071 100644 --- a/addons/board/static/src/css/dashboard.css +++ b/addons/board/static/src/css/dashboard.css @@ -1,3 +1,36 @@ +.openerp .oe_dashboard_layout_1 .oe_dashboard_column.index_0 { + width: 100%; +} +.openerp .oe_dashboard_layout_1 .oe_dashboard_column.index_1, .openerp .oe_dashboard_layout_1 .oe_dashboard_column.index_2 { + display: none; +} +.openerp .oe_dashboard_layout_1-1 .oe_dashboard_column { + width: 50%; +} +.openerp .oe_dashboard_layout_1-1 .oe_dashboard_column.index_2 { + display: none; +} +.openerp .oe_dashboard_layout_1-1-1 .oe_dashboard_column { + width: 33%; +} +.openerp .oe_dashboard_layout_2-1 .oe_dashboard_column.index_0 { + width: 70%; +} +.openerp .oe_dashboard_layout_2-1 .oe_dashboard_column.index_1 { + width: 30%; +} +.openerp .oe_dashboard_layout_2-1 .oe_dashboard_column.index_2 { + display: none; +} +.openerp .oe_dashboard_layout_1-2 .oe_dashboard_column.index_0 { + width: 30%; +} +.openerp .oe_dashboard_layout_1-2 .oe_dashboard_column.index_1 { + width: 70%; +} +.openerp .oe_dashboard_layout_1-2 .oe_dashboard_column.index_2 { + display: none; +} .openerp .oe_dashboard_layout_selector ul { white-space: nowrap; } diff --git a/addons/board/static/src/css/dashboard.sass b/addons/board/static/src/css/dashboard.sass index 32f0e3b4f3a..122b6dc232c 100644 --- a/addons/board/static/src/css/dashboard.sass +++ b/addons/board/static/src/css/dashboard.sass @@ -9,6 +9,31 @@ box-shadow: $bsval .openerp + .oe_dashboard_layout_1 .oe_dashboard_column + &.index_0 + width: 100% + &.index_1, &.index_2 + display: none + .oe_dashboard_layout_1-1 .oe_dashboard_column + width: 50% + &.index_2 + display: none + .oe_dashboard_layout_1-1-1 .oe_dashboard_column + width: 33% + .oe_dashboard_layout_2-1 .oe_dashboard_column + &.index_0 + width: 70% + &.index_1 + width: 30% + &.index_2 + display: none + .oe_dashboard_layout_1-2 .oe_dashboard_column + &.index_0 + width: 30% + &.index_1 + width: 70% + &.index_2 + display: none .oe_dashboard_layout_selector ul white-space: nowrap @@ -98,3 +123,4 @@ > tbody tr:nth-child(odd) background: transparent + diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js index 9c37924144d..43d7ca76d39 100644 --- a/addons/board/static/src/js/dashboard.js +++ b/addons/board/static/src/js/dashboard.js @@ -24,6 +24,10 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({ scroll: false }).bind('sortstop', self.do_save_dashboard); + var old_title = this.__parentedParent.get('title'); + this.__parentedParent.on_record_loaded.add_last(function(){ + self.__parentedParent.set({ 'title' : old_title}); + }); // Events this.$el.find('.oe_dashboard_link_reset').click(this.on_reset); this.$el.find('.oe_dashboard_link_change_layout').click(this.on_change_layout); @@ -165,8 +169,6 @@ instance.web.form.DashBoard = instance.web.form.FormWidget.extend({ this.rpc('/web/view/add_custom', { view_id: this.view.fields_view.view_id, arch: arch - }, function() { - self.$el.find('.oe_dashboard_link_reset').show(); }); }, on_load_action: function(result, index, action_attrs) { diff --git a/addons/board/static/src/xml/board.xml b/addons/board/static/src/xml/board.xml index e13fa707776..03ede793036 100644 --- a/addons/board/static/src/xml/board.xml +++ b/addons/board/static/src/xml/board.xml @@ -1,7 +1,7 @@ <template> <t t-name="DashBoard"> <div class="oe_dashboard_links"> - <button type="button" class="button oe_dashboard_link_reset" title="Reset Layout.." t-att-style="view.fields_view.custom_view_id ? null : 'display: none'"> + <button type="button" class="button oe_dashboard_link_reset" title="Reset Layout.." t-att-style="view.fields_view.custom_view_id || session.debug ? null : 'display: none'"> <img src="/board/static/src/img/layout_2-1.png" width="16" height="16"/> <span> Reset </span> </button> diff --git a/addons/claim_from_delivery/__openerp__.py b/addons/claim_from_delivery/__openerp__.py index 9c4395927af..9e3f7f59ca2 100644 --- a/addons/claim_from_delivery/__openerp__.py +++ b/addons/claim_from_delivery/__openerp__.py @@ -30,7 +30,9 @@ Create a claim from a delivery order. Adds a Claim link to the delivery order. """, - 'data' : ['claim_delivery_view.xml'], + 'data' : [ + 'claim_delivery_view.xml', + 'claim_delivery_data.xml',], 'auto_install': False, 'installable': True, 'certificate' : '001101649349223746957', diff --git a/addons/claim_from_delivery/claim_delivery_data.xml b/addons/claim_from_delivery/claim_delivery_data.xml new file mode 100644 index 00000000000..1b69087d4b8 --- /dev/null +++ b/addons/claim_from_delivery/claim_delivery_data.xml @@ -0,0 +1,11 @@ +<?xml version="1.0"?> +<openerp> + <data> + + <record model="res.request.link" id="request_link_claim_from_delivery"> + <field name="name">Delivery Order</field> + <field name="object">stock.picking.out</field> + </record> + + </data> +</openerp> diff --git a/addons/claim_from_delivery/claim_delivery_view.xml b/addons/claim_from_delivery/claim_delivery_view.xml index f345484b4a9..9187b1d11ca 100644 --- a/addons/claim_from_delivery/claim_delivery_view.xml +++ b/addons/claim_from_delivery/claim_delivery_view.xml @@ -1,11 +1,27 @@ <openerp> <data> - <act_window id="action_claim_from_delivery" name="Claim" - domain="[]" target="current" - context="{'default_partner_id': partner_id}" - view_mode="form" res_model="crm.claim" - src_model="stock.picking" /> + <record id="action_claim_from_delivery" model="ir.actions.act_window"> + <field name="name">Claim From Delivery</field> + <field name="res_model">crm.claim</field> + <field name="view_type">form</field> + <field name="view_id" ref="crm_claim.crm_case_claims_tree_view"/> + <field name="context">{'default_ref': 'stock.picking.out,'+str(context.get('active_id', False))}</field> + <field name="domain">[('ref','=','stock.picking.out,'+str(context.get('active_id',False)))]</field> + </record> + + <record id="crm_claim_from_delivery" model="ir.ui.view"> + <field name="name">crm.claim.from_delivery.form</field> + <field name="model">stock.picking.out</field> + <field name="inherit_id" ref="stock.view_picking_out_form"/> + <field name="arch" type="xml"> + <xpath expr="/form/sheet/h1" position="before"> + <div class="oe_right oe_button_box"> + <button name="%(action_claim_from_delivery)d" string="Claims" type="action"/> + </div> + </xpath> + </field> + </record> </data> </openerp> diff --git a/addons/delivery/delivery_view.xml b/addons/delivery/delivery_view.xml index 6a68d1a979f..deb59983ef2 100644 --- a/addons/delivery/delivery_view.xml +++ b/addons/delivery/delivery_view.xml @@ -259,10 +259,10 @@ <record id="view_picking_withweight_internal_move_form" model="ir.ui.view"> <field name="name">stock.picking_withweight.internal.move.form.view</field> - <field name="model">stock.picking</field> - <field name="inherit_id" ref="stock.view_picking_form"/> + <field name="model">stock.move</field> + <field name="inherit_id" ref="stock.view_move_picking_tree"/> <field name="arch" type="xml"> - <xpath expr="/form/sheet/notebook/page/field[@name='move_lines']/tree/field[@name='product_uom']" position="after"> + <xpath expr="//field[@name='product_uom']" position="after"> <field name="weight"/> <field name="weight_net" groups="base.group_no_one"/> </xpath> @@ -306,7 +306,7 @@ <record id="view_delivery_order_inherit_stock" model="ir.ui.view"> <field name="name">stock.picking.out.form</field> - <field name="model">stock.picking</field> + <field name="model">stock.picking.out</field> <field name="inherit_id" ref="stock.view_picking_out_form"/> <field name="arch" type="xml"> <xpath expr="/form/header//button[@string='Create Invoice/Refund']" position="after"> diff --git a/addons/fetchmail/i18n/mk.po b/addons/fetchmail/i18n/mk.po new file mode 100644 index 00000000000..741b3547812 --- /dev/null +++ b/addons/fetchmail/i18n/mk.po @@ -0,0 +1,333 @@ +# Macedonian translation for openobject-addons +# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2012. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2012-02-08 00:36+0000\n" +"PO-Revision-Date: 2012-09-18 16:07+0000\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: Macedonian <mk@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2012-09-19 04:37+0000\n" +"X-Generator: Launchpad (build 15966)\n" + +#. module: fetchmail +#: selection:fetchmail.server,state:0 +msgid "Confirmed" +msgstr "Потврдено" + +#. module: fetchmail +#: field:fetchmail.server,server:0 +msgid "Server Name" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,script:0 +msgid "Script" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,priority:0 +msgid "Defines the order of processing, lower values mean higher priority" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,is_ssl:0 +msgid "" +"Connections are encrypted with SSL/TLS through a dedicated port (default: " +"IMAPS=993, POP3S=995)" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,attach:0 +msgid "Keep Attachments" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,original:0 +msgid "" +"Whether a full original copy of each email should be kept for referenceand " +"attached to each processed message. This will usually double the size of " +"your message database." +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,priority:0 +msgid "Server Priority" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,state:0 +msgid "State" +msgstr "Состојба" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "POP" +msgstr "POP" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Fetch Now" +msgstr "" + +#. module: fetchmail +#: model:ir.actions.act_window,name:fetchmail.action_email_server_tree +#: model:ir.ui.menu,name:fetchmail.menu_action_fetchmail_server_tree +msgid "Incoming Mail Servers" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,port:0 +msgid "Port" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "POP/IMAP Servers" +msgstr "POP/IMAP сервери" + +#. module: fetchmail +#: selection:fetchmail.server,type:0 +msgid "Local Server" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,user:0 +msgid "Username" +msgstr "" + +#. module: fetchmail +#: model:ir.model,name:fetchmail.model_fetchmail_server +msgid "POP/IMAP Server" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Reset Confirmation" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "SSL" +msgstr "" + +#. module: fetchmail +#: model:ir.model,name:fetchmail.model_mail_message +msgid "Email Message" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,date:0 +msgid "Last Fetch Date" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,action_id:0 +msgid "" +"Optional custom server action to trigger for each incoming mail, on the " +"record that was created or updated by this mail" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "# of emails" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,original:0 +msgid "Keep Original" +msgstr "" + +#. module: fetchmail +#: code:addons/fetchmail/fetchmail.py:155 +#, python-format +msgid "" +"Here is what we got instead:\n" +" %s" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +#: field:fetchmail.server,configuration:0 +msgid "Configuration" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Incoming Mail Server" +msgstr "" + +#. module: fetchmail +#: code:addons/fetchmail/fetchmail.py:155 +#, python-format +msgid "Connection test failed!" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,server:0 +msgid "Hostname or IP of the mail server" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Server type IMAP." +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,name:0 +msgid "Name" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,is_ssl:0 +msgid "SSL/TLS" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Test & Confirm" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,action_id:0 +msgid "Server Action" +msgstr "" + +#. module: fetchmail +#: field:mail.message,fetchmail_server_id:0 +msgid "Inbound Mail Server" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,message_ids:0 +#: model:ir.actions.act_window,name:fetchmail.act_server_history +msgid "Messages" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Search Incoming Mail Servers" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,active:0 +msgid "Active" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,attach:0 +msgid "" +"Whether attachments should be downloaded. If not enabled, incoming emails " +"will be stripped of any attachments before being processed" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Advanced Options" +msgstr "" + +#. module: fetchmail +#: selection:fetchmail.server,type:0 +msgid "IMAP Server" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "IMAP" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Server type POP." +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,password:0 +msgid "Password" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Actions to Perform on Incoming Mails" +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,type:0 +msgid "Server Type" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Login Information" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Server Information" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "If SSL required." +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Advanced" +msgstr "" + +#. module: fetchmail +#: view:fetchmail.server:0 +msgid "Server & Login" +msgstr "" + +#. module: fetchmail +#: help:fetchmail.server,object_id:0 +msgid "" +"Process each incoming mail as part of a conversation corresponding to this " +"document type. This will create new documents for new conversations, or " +"attach follow-up emails to the existing conversations (documents)." +msgstr "" + +#. module: fetchmail +#: field:fetchmail.server,object_id:0 +msgid "Create a New Record" +msgstr "" + +#. module: fetchmail +#: selection:fetchmail.server,state:0 +msgid "Not Confirmed" +msgstr "Непотврдено" + +#. module: fetchmail +#: selection:fetchmail.server,type:0 +msgid "POP Server" +msgstr "" + +#. module: fetchmail +#: view:mail.message:0 +msgid "Mail Server" +msgstr "" + +#~ msgid "Confirm" +#~ msgstr "Потврди" + +#~ msgid "Group By..." +#~ msgstr "Групирај по..." + +#~ msgid "Type" +#~ msgstr "Вид" + +#~ msgid "" +#~ "Warning! Record for selected Model can not be created\n" +#~ "Please choose valid Model" +#~ msgstr "" +#~ "Предупредување! Записот за избраниот Модел не може да се креира\n" +#~ "Изберете валиден Модел" diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml index 098a8aec210..08e5f31a2d2 100644 --- a/addons/hr_recruitment/hr_recruitment_view.xml +++ b/addons/hr_recruitment/hr_recruitment_view.xml @@ -314,9 +314,7 @@ </div> <div class="oe_kanban_footer_left" style="margin-top:5px;"> <div class="oe_left oe_tags"> - <t t-foreach="record.categ_ids.raw_value" t-as="categ_id"> - <span class="oe_tag" t-att-data-categ_id="categ_id"></span> - </t> + <field name="categ_ids"/> </div> </div> </div> diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index 9c51853f865..92e882ae6d8 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -26,6 +26,7 @@ import mail_message import mail_mail import mail_thread import mail_group +import mail_vote import res_partner import res_users import report diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index d5cdc9fcfc3..65ee7f41d77 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -131,6 +131,8 @@ class mail_message(osv.Model): type='boolean', string='Unread', help='Functional field to search for unread messages linked to uid'), 'subtype_id': fields.many2one('mail.message.subtype', 'Subtype'), + 'vote_user_ids': fields.many2many('res.users', 'mail_vote', 'message_id', 'user_id', string='Votes', + help='Users that voted for this message'), } def _needaction_domain_get(self, cr, uid, context=None): @@ -149,11 +151,34 @@ class mail_message(osv.Model): } #------------------------------------------------------ + # Vote/Like + #------------------------------------------------------ + + def vote_toggle(self, cr, uid, ids, user_ids=None, context=None): + ''' Toggles voting ''' + if not user_ids: + user_ids = [uid] + for message in self.read(cr, uid, ids, ['vote_user_ids'], context=context): + for user_id in user_ids: + has_voted = user_id in message.get('vote_user_ids') + if not has_voted: + self.write(cr, uid, message.get('id'), {'vote_user_ids': [(4, user_id)]}, context=context) + else: + self.write(cr, uid, message.get('id'), {'vote_user_ids': [(3, user_id)]}, context=context) + return True + + #------------------------------------------------------ # Message loading for web interface #------------------------------------------------------ def _message_dict_get(self, cr, uid, msg, context=None): """ Return a dict representation of the message browse record. """ + has_voted = False + vote_ids = self.pool.get('res.users').name_get(cr, uid, [user.id for user in msg.vote_user_ids], context=context) + for vote in vote_ids: + if vote[0] == uid: + has_voted = True + break attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)] author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0] author_user_id = self.pool.get('res.users').name_get(cr, uid, [msg.author_id.user_ids[0].id], context=context)[0] @@ -172,6 +197,8 @@ class mail_message(osv.Model): 'author_user_id': author_user_id, 'partner_ids': partner_ids, 'child_ids': [], + 'vote_user_ids': vote_ids, + 'has_voted': has_voted } def message_read_tree_flatten(self, cr, uid, messages, current_level, level, context=None): diff --git a/addons/mail/mail_vote.py b/addons/mail/mail_vote.py new file mode 100644 index 00000000000..1e439fe0aeb --- /dev/null +++ b/addons/mail/mail_vote.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2012-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> +# +############################################################################## + +from osv import osv, fields + + +class mail_vote(osv.Model): + ''' Mail vote feature allow users to like and unlike messages attached + to a document. This allows for example to build a ranking-based + displaying of messages, for FAQ. ''' + + _name = 'mail.vote' + _description = 'Mail Vote' + _columns = { + 'message_id': fields.many2one('mail.message', 'Message', select=1, + ondelete='cascade', required=True), + 'user_id': fields.many2one('res.users', 'User', select=1, + ondelete='cascade', required=True), + } + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mail/security/ir.model.access.csv b/addons/mail/security/ir.model.access.csv index 5680184a9fb..e06950ab3fc 100644 --- a/addons/mail/security/ir.model.access.csv +++ b/addons/mail/security/ir.model.access.csv @@ -11,3 +11,4 @@ access_mail_alias_system,mail.alias,model_mail_alias,base.group_system,1,1,1,1 access_mail_message_subtype,mail.message.subtype,model_mail_message_subtype,,1,1,1,1
access_mail_mail_user,mail.mail,model_mail_mail,base.group_user,1,1,1,0
access_mail_mail_manager,mail.mail,model_mail_mail,group_mail_manager,1,1,1,1
+access_mail_vote_all,mail.vote.all,model_mail_vote,,1,1,1,1
diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 48a178732b0..2f9b35f1c95 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -260,6 +260,31 @@ display: none; } +/*--------------------------------------------------------------*/ +/* mail.vote +/*--------------------------------------------------------------*/ + +.openerp .oe_mail_msg_content button.oe_mail_msg_vote { + height:21px; + width: 30px; + padding: 1px; + background: #8A89BA; + margin-top: -4px; +} + +.openerp .oe_mail_msg_content button.oe_mail_msg_vote_true { + background:#DC5F59; +} + +.openerp .oe_mail_msg_content button.oe_mail_msg_vote span { + color: white; +} + +.openerp .oe_mail_msg_content span.oe_mail_vote_count{ + color: #807FB4; +} + + /* ------------------------------------------------------------ */ /* mail.compose.message form view & OpenERP hacks /* ------------------------------------------------------------ */ diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 71665bc69fb..57c777441e7 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -291,6 +291,7 @@ openerp.mail = function(session) { truncate_limit: options.truncate_limit || 250, } // datasets and internal vars + this.records = {}; this.ds_thread = new session.web.DataSetSearch(this, this.context.default_model); this.ds_notification = new session.web.DataSetSearch(this, 'mail.notification'); this.ds_message = new session.web.DataSetSearch(this, 'mail.message'); @@ -355,6 +356,8 @@ openerp.mail = function(session) { 'default_parent_id': parseInt(msg_id), 'default_content_subtype': 'html'} ); }); + // event: click on 'Vote' button + this.$el.on('click', 'button.oe_mail_msg_vote', this.on_vote); }, on_message_delete: function (event) { @@ -373,6 +376,16 @@ openerp.mail = function(session) { return this.ds_notification.call('set_message_read', [parseInt(msg_id)]); }, + on_vote: function (event) { + event.stopPropagation(); + var self = this; + var message_id = $(event.srcElement).parent().data().msg_id; + var vote_node = $(event.srcElement).parents('li').eq(0); + if (! message_id) { return false; } + return this.ds_message.call('vote_toggle', [[parseInt(message_id)]]).pipe( + self.toggle_vote(message_id, vote_node)); + }, + /** * Override-hack of do_action: automatically reload the chatter. * Normally it should be called only when clicking on 'Post/Send' @@ -492,6 +505,8 @@ openerp.mail = function(session) { attach['url'] = mail.ChatterUtils.get_attachment_url(this.session, attach); } record.is_author = mail.ChatterUtils.is_author(this, record.author_user_id[0]); + // add to internal storage + this.records[record.id] = record; // render, add the expand feature var rendered = session.web.qweb.render('mail.thread.message', {'record': record, 'thread': this, 'options': this.options}); $(rendered).appendTo(this.$el.children('div.oe_mail_thread_display:first')); @@ -505,6 +520,23 @@ openerp.mail = function(session) { }); }, + // Render vote Display template. + toggle_vote: function (message_id, vote_node) { + var self = this; + var record = this.records[message_id]; + if (record.has_voted) { + var idx = _.map(record.vote_user_ids, function (x) { return x[0]; }).indexOf(message_id); + record.vote_user_ids.splice(idx, 1); + } + else { + record.vote_user_ids.push([this.session.uid, 'You']); + } + record.has_voted = ! record.has_voted; + var vote_element = session.web.qweb.render('mail.thread.message.vote', {'record': record}); + vote_node.empty(); + vote_node.html(vote_element); + }, + /** Display 'show more' button */ update_fetch_more: function (new_value) { if (new_value) { diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index bf339f21f1c..e3586e723e4 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -142,11 +142,9 @@ </li> <li><a t-attf-href="#model=res.partner&id=#{record.author_id[0]}"><t t-raw="record.author_id[1]"/></a></li> <li><span t-att-title="record.date"><t t-raw="record.timerelative"/></span></li> + <t t-call="mail.thread.message.vote"/> <li t-if="options.show_reply"><a class="oe_mail_msg_reply">Reply</a></li> <li t-if="options.show_reply_by_email"><a class="oe_mail_msg_reply_by_email" t-attf-data-msg_id="{record.id}">Reply</a></li> - <!-- uncomment when merging vote - <li><a href="#">Like</a></li> - --> <li t-if="record.attachment_ids.length > 0"> <a class="oe_mail_msg_view_attachments"> <t t-if="record.attachment_ids.length == 1">1 Attachment</t> @@ -180,4 +178,17 @@ </ul> </t> + <!-- mail.thread.message.vote + Template used to display Like/Unlike in a mail.message + --> + <li t-name="mail.thread.message.vote"> + <t t-if='record.vote_user_ids.length > 0'> + <span class="oe_left oe_mail_vote_count"><t t-esc="record.vote_user_ids.length"/> votes</span> + </t> + <button t-attf-class="oe_mail_msg_vote oe_mail_msg_vote_#{record.has_voted}" t-attf-data-msg_id="{record.id}"> + <t t-if="! record.has_voted"><span>+1</span></t> + <t t-if="record.has_voted"><span>-1</span></t> + </button> + </li> + </template> diff --git a/addons/mail/tests/test_mail.py b/addons/mail/tests/test_mail.py index ebaceaeaccb..2dfb7a75136 100644 --- a/addons/mail/tests/test_mail.py +++ b/addons/mail/tests/test_mail.py @@ -648,8 +648,37 @@ class test_mail(TestMailMockups): msg1.refresh() self.assertEqual(5, len(group_pigs.message_ids), 'group should contain 5 messages') self.assertEqual(2, len(msg1.child_ids), 'msg1 should have 2 children now') + + def test_60_vote(self): + """ Test designed for the vote/unvote feature. """ + cr, uid = self.cr, self.uid + group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id) + msg1 = group_pigs.message_post(body='My Body', subject='1') + msg1 = self.mail_message.browse(cr, uid, msg1) + + # Create user Bert Tartopoils + user_bert_id = self.res_users.create(cr, uid, {'name': 'Bert', 'login': 'bert'}) + user_bert = self.res_users.browse(cr, uid, user_bert_id) + + # Test: msg1 and msg2 have void vote_user_ids + self.assertFalse(msg1.vote_user_ids, 'newly created message msg1 has not void vote_user_ids') + # Do: Admin vote for msg1 + self.mail_message.vote_toggle(cr, uid, [msg1.id]) + msg1.refresh() + # Test: msg1 has Admin as voter + self.assertEqual(set(msg1.vote_user_ids), set([user_admin]), 'after voting, Admin is not the voter') + # Do: Bert vote for msg1 + self.mail_message.vote_toggle(cr, uid, [msg1.id], [user_bert_id]) + msg1.refresh() + # Test: msg1 has Admin and Bert as voters + self.assertEqual(set(msg1.vote_user_ids), set([user_admin, user_bert]), 'after voting, Admin and Bert are not the voters') + # Do: Admin unvote for msg1 + self.mail_message.vote_toggle(cr, uid, [msg1.id]) + msg1.refresh() + # Test: msg1 has Bert as voter + self.assertEqual(set(msg1.vote_user_ids), set([user_bert]), 'after unvoting for Admin, Bert is not the voter') - def test_60_message_subtype(self): + def test_70_message_subtype(self): """ Tests designed for message_subtype. """ cr, uid = self.cr, self.uid self.res_users.write(cr, uid, [uid], {'signature': 'Admin', 'email': 'a@a'}) @@ -676,3 +705,4 @@ class test_mail(TestMailMockups): msg_id = self.mail_group.message_post(cr, uid, [self.group_pigs_id], body=_body1, subject=_subject, type='comment',subtype_xml_id='mail_subtype_comment') notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', msg_id)]) self.assertTrue(len(notif_ids) >= 1,"subtype is email and show notification on wall") + diff --git a/addons/mrp/board_manufacturing_view.xml b/addons/mrp/board_manufacturing_view.xml index cae1fea07dc..6bd07c2648b 100644 --- a/addons/mrp/board_manufacturing_view.xml +++ b/addons/mrp/board_manufacturing_view.xml @@ -30,7 +30,8 @@ icon="terp-graph" id="menu_board_manufacturing" parent="base.menu_reporting_dashboard" - sequence="30"/> + sequence="30" + groups="group_mrp_manager"/> </data> </openerp> diff --git a/addons/note/note.py b/addons/note/note.py index 65848ed7828..a7bad7f6a55 100644 --- a/addons/note/note.py +++ b/addons/note/note.py @@ -22,6 +22,7 @@ from openerp.osv import osv, fields from tools.translate import _ import re +from openerp.tools.misc import html2plaintext class note_stage(osv.osv): """ Category of Note """ @@ -65,23 +66,24 @@ class note_note(osv.osv): text_note = (note.memo or '').strip().split('\n')[0] text_note = re.sub(r'(\S?)(<br[ /]*>|<[/]?p>|<[/]?div>|<table>)[\s\S]*',r'\1',text_note) text_note = re.sub(r'<[^>]+>','',text_note) + text_note = html2plaintext(text_note) res[note.id] = text_note return res #unactivate a sticky note and record the date def onclick_note_is_done(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, { 'active' : False, 'date_done' : fields.date.today() }) + self.write(cr, uid, ids, { 'open' : False, 'date_done' : fields.date.today() }) self.message_post(cr, uid, ids[0], body='Note is done.', subject=False, type='notification', parent_id=False, attachments=None, context=context) return False #activate a note def onclick_note_not_done(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, {'active' : True}) + self.write(cr, uid, ids, {'open' : True}) self.message_post(cr, uid, ids[0], body='Note has been activated.', subject=False, type='notification', parent_id=False, attachments=None, context=context) return False - + #used for undisplay the follower if it's the current user def _get_my_current_partner(self, cr, uid, ids, name, args, context=None): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) @@ -119,14 +121,14 @@ class note_note(osv.osv): type='many2one', relation='note.stage'), 'stage_ids': fields.many2many('note.stage','note_stage_rel','note_id','stage_id','Stages of Users'), - 'active': fields.boolean('Active'), + 'open': fields.boolean('Active'), 'date_done': fields.date('Date done'), 'color': fields.integer('Color Index'), 'tag_ids' : fields.many2many('note.tag','note_tags_rel','note_id','tag_id','Tags'), 'current_partner_id' : fields.function(_get_my_current_partner), } _defaults = { - 'active' : 1, + 'open' : 1, 'stage_id' : _get_default_stage_id, } _order = 'sequence' diff --git a/addons/note/note_demo.xml b/addons/note/note_demo.xml index 82601f903c0..1cc1b2fc790 100644 --- a/addons/note/note_demo.xml +++ b/addons/note/note_demo.xml @@ -138,14 +138,5 @@ <field name="color">7</field> </record> - <record id="note_13" model="note.note"> - <field name="memo"><![CDATA[Read those books - <br/><br/>* Open ERP: a modern approach to integrated business management - <br/>* Open ERP for Retail and Industrial Management - ]]> - </field> - <field name="stage_id" ref="note_stage_03"/> - </record> - </data> </openerp> diff --git a/addons/note/note_view.xml b/addons/note/note_view.xml index 1166e687750..ccb07544c09 100644 --- a/addons/note/note_view.xml +++ b/addons/note/note_view.xml @@ -1,7 +1,6 @@ <?xml version="1.0"?> <openerp> <data> - <menuitem name="Organizer" id="note_my_stuff" parent="mail.mail_feeds_main"/> <!-- note Stage Form View --> @@ -51,7 +50,7 @@ <field name="sequence"/> <field name="name"/> <field name="stage_id"/> - <field name="active"/> + <field name="open"/> <field name="memo"/> <field name="date_done"/> <field name="current_partner_id"/> @@ -65,8 +64,8 @@ <div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_global_click_edit oe_semantic_html_override oe_kanban_card #{record.group_fancy==1 ? 'oe_kanban_card_fancy' : ''}"> <div class="oe_dropdown_kanban"> <span> - <a name="onclick_note_is_done" type="object" t-if="record.active.raw_value" class="oe_e">W</a> - <a name="onclick_note_not_done" type="object" t-if="!record.active.raw_value" class="oe_e">è</a> + <a name="onclick_note_is_done" type="object" t-if="record.open.raw_value" class="oe_e">W</a> + <a name="onclick_note_not_done" type="object" t-if="!record.open.raw_value" class="oe_e">è</a> </span> <!-- dropdown menu --> @@ -78,13 +77,12 @@ </ul> </div> </div> - <!-- kanban note --> - <div t-attf-class="oe_kanban_content #{record.active.raw_value ? '' : 'note_text_line_through'}"> + <div t-attf-class="oe_kanban_content #{record.open.raw_value ? '' : 'note_text_line_through'}"> <!-- title --> <field name="name"/> </div> - <div widget="many2many_tags" t-att-data="record.tag_ids.raw_value" model="note.tag"/> + <field name="tag_ids"/> <div class="oe_right"> <t t-foreach="record.message_follower_ids.raw_value" t-as="follower"> <img t-if="record.current_partner_id.raw_value!=follower" t-att-src="kanban_image('res.partner', 'image_small', follower)" width="24" height="24" class="oe_kanban_avatar" t-att-data-member_id="follower"/> @@ -105,7 +103,7 @@ <field name="arch" type="xml"> <tree string="Stages"> <field name="name"/> - <field name="active"/> + <field name="open"/> <field name="stage_id"/> <field name="tag_ids" widget="many2many_tags" groups="note.group_note_tags"/> </tree> @@ -139,9 +137,8 @@ <search string="Notes"> <field name="memo" string="Note"/> <field name="tag_ids" groups="note.group_note_tags"/> - <field name="stage_id"/> - <filter name="active_true" string="Active" domain="['|',('active', '=', True),('date_done','=',time.strftime('%%Y-%%m-%%d'))]"/> - <filter name="active_false" string="Old" domain="[('active', '=', False)]"/> + <filter name="open_true" string="Active" domain="['|',('open', '=', True),('date_done','=',time.strftime('%%Y-%%m-%%d'))]"/> + <filter name="open_false" string="Archive" domain="[('open', '=', False)]"/> <group expand="0" string="Group By..."> <filter icon="terp-stock_symbol-selection" string="Stage" help="By sticky note Category" context="{'group_by':'stage_id'}"/> </group> @@ -185,7 +182,7 @@ <field name="view_type">form</field> <field name="view_mode">kanban,tree,form</field> <field name="search_view_id" ref="view_note_note_filter"/> - <field name="context">{'search_default_active_true':True}</field> + <field name="context">{'search_default_open_true':True}</field> </record> <menuitem name="Notes" id="note_notes" parent="note_my_stuff" sequence="20" action="action_note_note"/> diff --git a/addons/note/security/ir.rule.xml b/addons/note/security/ir.rule.xml index 3d2f0d242f6..1195314cc9e 100644 --- a/addons/note/security/ir.rule.xml +++ b/addons/note/security/ir.rule.xml @@ -1,12 +1,19 @@ <?xml version="1.0"?> <openerp> <data> - <record id="note_note_rule_global" model="ir.rule"> - <field name="name">Only followers can access a sticky notes</field> - <field model="ir.model" ref="model_note_note" name="model_id"/> - <field name="domain_force">['|',('message_follower_ids','=',False),('message_follower_ids','=',user.partner_id.id)]</field> - <field eval="True" name="global"/> - </record> + <record id="note_note_rule_global" model="ir.rule"> + <field name="name">Only followers can access a sticky notes</field> + <field model="ir.model" ref="model_note_note" name="model_id"/> + <field name="domain_force">[('message_follower_ids','=',user.partner_id.id)]</field> + <field eval="True" name="global"/> + </record> + + <record id="note_stage_rule_global" model="ir.rule"> + <field name="name">Each user have his stage name</field> + <field model="ir.model" ref="model_note_stage" name="model_id"/> + <field name="domain_force">['|',('user_id','=',False),('user_id','=',user.id)]</field> + <field eval="True" name="global"/> + </record> </data> </openerp> diff --git a/addons/portal_project_issue/portal_project_issue_view.xml b/addons/portal_project_issue/portal_project_issue_view.xml index 5d0b4ce081e..1030dedbdf8 100644 --- a/addons/portal_project_issue/portal_project_issue_view.xml +++ b/addons/portal_project_issue/portal_project_issue_view.xml @@ -27,6 +27,7 @@ <t t-foreach="record.categ_ids.raw_value" t-as="categ_id"> <span class="oe_tag" t-att-data-categ_id="categ_id"></span> </t> + <field name="categ_ids"/> </div> <div class="oe_right"> Creation: <field name="create_date"/> diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index dcb47f1af88..950c295f27b 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -554,7 +554,7 @@ class stock_warehouse_orderpoint(osv.osv): 'logic': fields.selection([('max','Order to Max'),('price','Best price (not yet active!)')], 'Reordering Mode', required=True), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', required=True, ondelete="cascade"), 'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="cascade"), - 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade', domain=[('type','=','product')]), + 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade', domain=[('type','!=','service')]), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'product_min_qty': fields.float('Minimum Quantity', required=True, help="When the virtual stock goes below the Min Quantity specified for this field, OpenERP generates "\ diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index fea22c519a8..be7427fe8f4 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -269,9 +269,7 @@ </div> <div class="oe_kanban_footer_left"> <div class="oe_left oe_tags"> - <t t-foreach="record.categ_ids.raw_value" t-as="categ_id"> - <span class="oe_tag" t-att-data-categ_id="categ_id"></span> - </t> + <field name="categ_ids"/> </div> <div class="oe_right"> <span class="oe_kanban_highlight"> diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index b0f10d3f71f..8bcd6d39ef9 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -548,6 +548,7 @@ class purchase_order(osv.osv): 'partner_id': order.dest_address_id.id or order.partner_id.id, 'move_dest_id': order_line.move_dest_id.id, 'state': 'draft', + 'type':'in', 'purchase_line_id': order_line.id, 'company_id': order.company_id.id, 'price_unit': order_line.price_unit diff --git a/addons/purchase/stock_view.xml b/addons/purchase/stock_view.xml index b522618ed2e..21c52b4d2ec 100644 --- a/addons/purchase/stock_view.xml +++ b/addons/purchase/stock_view.xml @@ -31,7 +31,7 @@ <field name="purchase_id"/> </xpath> <xpath expr="//field[@name='company_id']" position="after"> - <field name="warehouse_id"/> + <field name="warehouse_id" groups="stock.group_locations"/> </xpath> </field> </record> diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 6767d841b08..cc6e5f71f30 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -145,6 +145,14 @@ class sale_order(osv.osv): 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): @@ -156,7 +164,7 @@ class sale_order(osv.osv): if invoice.state != 'paid': res[sale.id] = False break - if not invoice_existence: + if not invoice_existence or sale.state == 'manual': res[sale.id] = False return res @@ -245,6 +253,8 @@ class sale_order(osv.osv): 'invoiced_rate': fields.function(_invoiced_rate, string='Invoiced', 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 sale order has at least one invoice."), 'note': fields.text('Terms and conditions'), 'amount_untaxed': fields.function(_amount_all, digits_compute= dp.get_precision('Account'), string='Untaxed Amount', @@ -518,68 +528,45 @@ class sale_order(osv.osv): This function returns an action that display existing invoices of given sale order ids. It can either be a in a list or in a form view, if there is only one invoice to show. ''' mod_obj = self.pool.get('ir.model.data') - result = { - 'name': _('Cutomer Invoice'), - 'view_type': 'form', - 'res_model': 'account.invoice', - 'context': "{'type':'out_invoice', 'journal_type': 'sale'}", - 'type': 'ir.actions.act_window', - 'nodestroy': True, - 'target': 'current', - } + act_obj = self.pool.get('ir.actions.act_window') + + result = mod_obj.get_object_reference(cr, uid, 'account', 'action_invoice_tree1') + id = result and result[1] or False + result = act_obj.read(cr, uid, [id], context=context)[0] #compute the number of invoices to display inv_ids = [] for so in self.browse(cr, uid, ids, context=context): inv_ids += [invoice.id for invoice in so.invoice_ids] #choose the view_mode accordingly if len(inv_ids)>1: - res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_tree') - result.update({ - 'view_mode': 'tree,form', - 'res_id': inv_ids or False - }) + result['domain'] = "[('id','in',["+','.join(map(str, inv_ids))+"])]" else: res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form') - result.update({ - 'view_mode': 'form', - 'res_id': inv_ids and inv_ids[0] or False, - }) - result.update(view_id = res and res[1] or False) + result['views'] = [(res and res[1] or False, 'form')] + result['res_id'] = inv_ids and inv_ids[0] or False return result - def action_view_delivery(self, cr, uid, ids, context=None): ''' This function returns an action that display existing delivery orders of given sale order ids. It can either be a in a list or in a form view, if there is only one delivery order to show. ''' mod_obj = self.pool.get('ir.model.data') - result = { - 'name': _('Delivery Order'), - 'view_type': 'form', - 'res_model': 'stock.picking', - 'context': "{'type':'out'}", - 'type': 'ir.actions.act_window', - 'nodestroy': True, - 'target': 'current', - } + act_obj = self.pool.get('ir.actions.act_window') + + result = mod_obj.get_object_reference(cr, uid, 'stock', 'action_picking_tree') + id = result and result[1] or False + result = act_obj.read(cr, uid, [id], context=context)[0] #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] #choose the view_mode accordingly if len(pick_ids) > 1: - res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_tree') - result.update({ - 'view_mode': 'tree,form', - 'res_id': pick_ids or False - }) + result['domain'] = "[('id','in',["+','.join(map(str, pick_ids))+"])]" else: res = mod_obj.get_object_reference(cr, uid, 'stock', 'view_picking_out_form') - result.update({ - 'view_mode': 'form', - 'res_id': pick_ids and pick_ids[0] or False, - }) - result.update(view_id = res and res[1] or False) + result['views'] = [(res and res[1] or False, 'form')] + result['res_id'] = pick_ids and pick_ids[0] or False return result def test_no_product(self, cr, uid, order, context): @@ -883,6 +870,7 @@ class sale_order(osv.osv): 'sale_line_id': line.id, 'tracking_id': False, 'state': 'draft', + 'type':'out', #'state': 'waiting', 'note': '\n'.join(line.name.split('\n')[1:]), 'company_id': order.company_id.id, diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 651454ef73d..5c2320a7d5c 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -163,7 +163,7 @@ <button name="action_button_confirm" states="draft" string="Confirm" type="object"/> <button name="action_button_confirm" states="sent" string="Confirm" class="oe_highlight" type="object"/> <button name="action_view_invoice" string="View Invoice" type="object" class="oe_highlight" - attrs="{'invisible': ['|','|',('state', '!=','progress'), ('invoiced', '=', True),('order_policy','=','picking')]}"/> + attrs="{'invisible': [('invoice_exists', '=', False)]}"/> <button name="action_view_delivery" string="View Delivery Order" type="object" class="oe_highlight" attrs="{'invisible': ['|','|','|',('picking_ids','=',False),('picking_ids','=',[]), ('state', 'not in', ('progress','manual')),('shipped','=',True)]}"/> <button name="%(action_view_sale_advance_payment_inv)d" string="Create Invoice" @@ -320,6 +320,7 @@ <group> <field name="invoiced"/> <field name="shipped"/> + <field name="invoice_exists" invisible="1"/> </group> </group> </page> diff --git a/addons/sale/stock_view.xml b/addons/sale/stock_view.xml index eb0f1e415f5..0eb64f98e9b 100644 --- a/addons/sale/stock_view.xml +++ b/addons/sale/stock_view.xml @@ -9,9 +9,6 @@ <field name="move_type" position="before"> <field name="sale_id"/> </field> - <label for="partner_id" position="replace"> - <label for="partner_id" class="oe_edit_only" string="Contact"/> - </label> </field> </record> diff --git a/addons/sale/test/manual_order_policy.yml b/addons/sale/test/manual_order_policy.yml index 3a8dcbd2f5b..17ebeb9f86b 100644 --- a/addons/sale/test/manual_order_policy.yml +++ b/addons/sale/test/manual_order_policy.yml @@ -1,5 +1,5 @@ - - I confirm the Quotation with "Deliver & invoice on demand". + I confirm the Quotation with "On Demand" order policy. - !workflow {model: sale.order, action: order_confirm, ref: sale_order_2} - @@ -9,44 +9,34 @@ sale_order = self.browse(cr, uid, ref("sale_order_2")) assert len(sale_order.invoice_ids) == False, "Invoice should not created." - - I create advance invoice. + I create advance invoice where type is 'Fixed Price'. - !python {model: sale.advance.payment.inv}: | ctx = context.copy() ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_2")], "active_id":ref("sale_order_2")}) order_line = self.pool.get('sale.order.line').browse(cr, uid, ref("sale_order_line_4"), context=context) - pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_subtotal, 'qtty': order_line.product_uom_qty}) + pay_id = self.create(cr, uid, {'advance_payment_method': 'fixed', 'product_id': order_line.product_id.id, 'amount': order_line.price_unit}) self.create_invoices(cr, uid, [pay_id], context=ctx) - - I check Invoice which made advance + I check Invoice which made advance. - !python {model: sale.order}: | order = self.browse(cr, uid, ref('sale_order_2')) assert order.invoice_ids, "Invoice should be created after make advance invoice." - - I create Invoice from sale order line. + I create advance invoice where type is 'Invoice all the Sale Order'. - - !python {model: sale.order.line.make.invoice}: | + !python {model: sale.advance.payment.inv}: | ctx = context.copy() - ctx.update({"active_model": 'sale.order.line', "active_ids": [ref("sale_order_line_5")], "active_id":ref("sale_order_line_5")}) - self.make_invoices(cr, uid, [], context=ctx) -- - I check Invoice which made from sale order line. -- - !python {model: sale.order.line}: | - line = self.browse(cr, uid, ref('sale_order_line_5')) - assert line.invoiced, "Line is not invoiced." - assert line.invoice_lines, "Invoice line should be created." -- - I create manual Invoice for order. + ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_2")], "active_id":ref("sale_order_2")}) + pay_id = self.create(cr, uid, {'advance_payment_method': 'all'}) + self.create_invoices(cr, uid, [pay_id], context=ctx) - - !record {model: sale.make.invoice, id: sale_make_invoice_1}: - invoice_date: !eval time.strftime('%Y-%m-%d') + I check Invoice which made advance where type is 'Invoice all the Sale Order'. - - !python {model: sale.make.invoice}: | - ctx = context.copy() - ctx = ctx.update({"active_model": 'sale.order', "active_ids": [ref("sale_order_2")], "active_id":ref("sale_order_2")}) - self.make_invoices(cr, uid, [ref("sale_make_invoice_1")], context) + !python {model: sale.order}: | + order = self.browse(cr, uid, ref('sale_order_2')) + assert order.invoice_ids, "Invoice should be created after make advance invoice where type is 'Invoice all the Sale Order'." - I open the Invoice. - @@ -57,7 +47,7 @@ for invoice in so.invoice_ids: wf_service.trg_validate(uid, 'account.invoice', invoice.id, 'invoice_open', cr) - - I pay the invoice + I pay the invoice. - !python {model: account.invoice}: | sale_order = self.pool.get('sale.order') @@ -75,8 +65,9 @@ !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.invoiced, "Order is not invoiced." - assert sale_order.state == 'manual', 'Order should be in Manual.' + assert sale_order.invoice_exists, "Order is not invoiced." + assert sale_order.invoiced, "Order is not paid." + assert sale_order.state == 'progress', 'Order should be in Progress.' - I set order policy "Deliver & invoice on demand" as default policy. diff --git a/addons/stock/board_warehouse_view.xml b/addons/stock/board_warehouse_view.xml index b223e731e8f..839a99c1fa7 100644 --- a/addons/stock/board_warehouse_view.xml +++ b/addons/stock/board_warehouse_view.xml @@ -61,7 +61,7 @@ parent="base.menu_reporting_dashboard" action="open_board_warehouse" sequence="25" - groups="group_stock_manager"/> + groups="stock.group_stock_user"/> </data> </openerp> diff --git a/addons/stock/report/report_stock_move_view.xml b/addons/stock/report/report_stock_move_view.xml index a78a506cefe..4c911dd6e7c 100644 --- a/addons/stock/report/report_stock_move_view.xml +++ b/addons/stock/report/report_stock_move_view.xml @@ -6,7 +6,8 @@ id="stock.next_id_61" name="Warehouse" sequence="15" - parent="base.menu_reporting"/> + parent="base.menu_reporting" + groups="group_stock_manager"/> <record id="view_stock_tree" model="ir.ui.view"> <field name="name">report.stock.move.tree</field> diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv index f56696bcbaa..b0ae333a9ef 100644 --- a/addons/stock/security/ir.model.access.csv +++ b/addons/stock/security/ir.model.access.csv @@ -21,11 +21,11 @@ access_stock_production_lot_manager,stock.production.lot manager,model_stock_pro access_stock_production_lot_user,stock.production.lot user,model_stock_production_lot,stock.group_stock_user,1,1,1,1
access_stock_production_lot_revision,stock.production.lot.revision,model_stock_production_lot_revision,stock.group_stock_user,1,1,1,1
access_stock_move_manager,stock.move manager,model_stock_move,stock.group_stock_manager,1,1,0,0
-access_stock_move_user,stock.move user,model_stock_move,stock.group_stock_user,1,0,0,0
+access_stock_move_user,stock.move user,model_stock_move,stock.group_stock_user,1,1,1,0
access_stock_move_warehouse_manager,stock.move.manager,model_stock_move,stock.group_stock_manager,1,1,1,1
-access_stock_inventory_user,stock.inventory user,model_stock_inventory,stock.group_stock_user,1,0,0,0
+access_stock_inventory_user,stock.inventory user,model_stock_inventory,stock.group_stock_user,1,1,1,0
access_stock_inventory_manager,stock.inventory manager,model_stock_inventory,stock.group_stock_manager,1,1,1,1
-access_stock_inventory_line_user,stock.inventory.line user,model_stock_inventory_line,stock.group_stock_user,1,0,0,0
+access_stock_inventory_line_user,stock.inventory.line user,model_stock_inventory_line,stock.group_stock_user,1,1,1,0
access_stock_inventory_line_manager,stock.inventory.line manager,model_stock_inventory_line,stock.group_stock_manager,1,1,1,1
access_stock_report_prodlots,stock.report.prodlots,model_stock_report_prodlots,stock.group_stock_manager,1,0,0,0
access_stock_location_sale_manager,stock.location sale manager,model_stock_location,base.group_sale_manager,1,0,0,0
@@ -61,3 +61,4 @@ access_product_group_res_partner_stock_manager,res_partner group_stock_manager,b access_product_pricelist_version_stock_manager,product.pricelist.version stock_manager,product.model_product_pricelist_version,stock.group_stock_manager,1,1,1,1
access_product_pricelist_item_stock_manager,product.pricelist.item stock_manager,product.model_product_pricelist_item,stock.group_stock_manager,1,1,1,1
access_account_account_stock_manager,account.account stock manager,account.model_account_account,stock.group_stock_manager,1,0,0,0
+access_board_stock_user,board.board user,board.model_board_board,stock.group_stock_user,1,1,0,0
diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 50e85fa5191..77849e12627 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1667,6 +1667,7 @@ 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), + 'type': fields.related('picking_id', 'type', type='selection', selection=[('out', 'Sending Goods'), ('in', 'Getting Goods'), ('internal', 'Internal')], string='Shipping Type'), } def _check_location(self, cr, uid, ids, context=None): for record in self.browse(cr, uid, ids, context=context): @@ -1746,10 +1747,25 @@ class stock_move(osv.osv): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) return user.company_id.partner_id.id + def _default_move_type(self, cr, uid, context=None): + """ Gets default type of move + @return: type + """ + if context is None: + context = {} + picking_type = context.get('picking_type') + type = 'internal' + if picking_type == 'in': + type = 'in' + elif picking_type == 'out': + type = 'out' + return type + _defaults = { 'location_id': _default_location_source, 'location_dest_id': _default_location_destination, 'partner_id': _default_destination_address, + 'type': _default_move_type, 'state': 'draft', 'priority': '1', 'product_qty': 1.0, @@ -1903,6 +1919,32 @@ class stock_move(osv.osv): result['location_dest_id'] = loc_dest_id return {'value': result} + def onchange_move_type(self, cr, uid, ids, type, context=None): + """ On change of move type gives sorce and destination location. + @param type: Move Type + @return: Dictionary of values + """ + mod_obj = self.pool.get('ir.model.data') + location_source_id = False + location_dest_id = False + if type == 'in': + location_source_id = 'stock_location_suppliers' + location_dest_id = 'stock_location_stock' + elif type == 'out': + location_source_id = 'stock_location_stock' + location_dest_id = 'stock_location_customers' + if location_source_id: + try: + location_model, location_source_id = mod_obj.get_object_reference(cr, uid, 'stock', location_source_id) + except ValueError, e: + location_source_id = False + if location_dest_id: + try: + location_model, location_dest_id = mod_obj.get_object_reference(cr, uid, 'stock', location_dest_id) + except ValueError, e: + location_dest_id = False + return {'value':{'location_id': location_source_id, 'location_dest_id': location_dest_id}} + def onchange_date(self, cr, uid, ids, date, date_expected, context=None): """ On change of Scheduled Date gives a Move date. @param date_expected: Scheduled Date diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 154927a2f19..83fed186f42 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -106,13 +106,16 @@ <field name="arch" type="xml"> <form string="Physical Inventory" version="7.0"> <header> - <button name="action_confirm" states="draft" string="Confirm Inventory" type="object" class="oe_highlight"/> - <button name="action_done" states="confirm" string="Validate Inventory" type="object" class="oe_highlight"/> + <button name="action_confirm" states="draft" string="Confirm Inventory" type="object" class="oe_highlight" groups="stock.group_stock_user"/> + <button name="action_done" states="confirm" string="Validate Inventory" type="object" class="oe_highlight" groups="stock.group_stock_manager"/> <button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object"/> <button name="action_cancel_inventory" states="draft,confirm,done" string="Cancel Inventory" type="object"/> <field name="state" widget="statusbar" statusbar_visible="draft,confirm"/> </header> <sheet> + <div class="oe_right oe_button_box"> + <button name="%(action_view_stock_fill_inventory)d" string="Fill Inventory" type="action" /> + </div> <group> <group> <field name="name" placeholder="e.g. Annual inventory"/> @@ -231,9 +234,9 @@ <field name="active"/> </group> <group groups="stock.group_tracking_lot" string="Traceability"> - <button name="action_traceability" icon="gtk-go-up" string="Upstream Traceability" type="object" + <button name="action_traceability" string="Upstream Traceability" type="object" colspan="2"/> - <button name="action_traceability" icon="gtk-go-down" string="Downstream Traceability" type="object" + <button name="action_traceability" string="Downstream Traceability" type="object" context="{'type': 'move_history_ids'}" colspan="2"/> </group> </group> @@ -334,8 +337,8 @@ <field name="arch" type="xml"> <form string="Serial Number" version="7.0"> <div class="oe_button_box oe_right"> - <button name="action_traceability" string="Upstream Traceability" type="object" context="{'type': '', 'field': 'prodlot_id'}" icon="gtk-go-up"/> - <button name="action_traceability" string="Downstream Traceability" type="object" context="{'type': 'move_history_ids', 'field': 'prodlot_id'}" icon="gtk-go-down"/> + <button name="action_traceability" string="Upstream Traceability" type="object" context="{'type': 'move_history_ids2', 'field': 'prodlot_id'}"/> + <button name="action_traceability" string="Downstream Traceability" type="object" context="{'type': 'move_history_ids', 'field': 'prodlot_id'}"/> </div> <div class="oe_title"> <label for="name" class="oe_edit_only"/> @@ -759,15 +762,10 @@ <label for="name" class="oe_edit_only"/> <h1> <field name="name" class="oe_inline"/> - <span attrs="{'invisible': [('origin','=',False)]}"> - </span> - <field name="origin" placeholder="e.g. PO0032" class="oe_inline"/> </h1> - <label for="partner_id" class="oe_edit_only"/> - <h2> - <field name="partner_id" on_change="onchange_partner_in(partner_id)"/> - </h2> <group> <group> + <field name="partner_id" on_change="onchange_partner_in(partner_id)"/> <field name="backorder_id" readonly="1"/> <field name="invoice_state" string="Invoice Control" groups="account.group_account_invoice" attrs="{'invisible':[('invoice_state', '=', 'none')]}"/> <field name="stock_journal_id" widget="selection" groups="account.group_account_user"/> @@ -775,119 +773,23 @@ <group> <field name="date"/> <field name="min_date" readonly="1"/> + <field name="origin" placeholder="e.g. PO0032" class="oe_inline"/> </group> </group> <notebook> <page string="Products"> - <field name="move_lines" context="{'address_in_id': partner_id}"> - <tree colors="grey:scrapped == True" string="Stock Moves"> - <field name="product_id"/> - <field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/> - <field name="product_uom" string="Unit of Measure" groups="product.group_uom"/> - <field name="product_uos" groups="product.group_uos"/> - <button name="%(stock.move_scrap)d" - string="Scrap Products" type="action" - icon="gtk-convert" context="{'scrap': True}" - states="draft,waiting,confirmed,assigned" - groups="base.group_user"/> - <field name="scrapped" invisible="1"/> - <field name="prodlot_id" groups="stock.group_production_lot"/> - <button - name="%(stock.track_line)d" - string="Split in Serial Number" - groups="stock.group_production_lot" - type="action" icon="terp-stock_effects-object-colorize" - states="draft,waiting,confirmed,assigned"/> - <field groups="stock.group_tracking_lot" name="tracking_id"/> - <button name="setlast_tracking" string="Put in current pack" type="object" - attrs="{'invisible': [('tracking_id','<>',False)]}" - icon="terp-stock_effects-object-colorize" - groups="stock.group_tracking_lot" - states="draft,assigned,confirmed"/> - <button name="%(split_into)d" string="Put in a new pack" type="action" - groups="product.group_stock_packaging" - icon="terp-stock_effects-object-colorize" - states="draft,assigned,confirmed"/> - <field name="location_dest_id" groups="stock.group_locations"/> - <field name="state"/> - </tree> - <form string="Stock Moves" version="7.0"> - <header> - <span groups="base.group_user"> - <button name="force_assign" states="confirmed" string="Force Availability" type="object" icon="gtk-jump-to"/> - <button name="action_confirm" states="draft" string="Confirm" type="object" icon="gtk-apply"/> - <button name="cancel_assign" states="assigned" string="Cancel Availability" type="object" icon="gtk-find"/> - </span> - <field name="state" widget="statusbar" statusbar_visible="draft,assigned,done"/> - </header> - <group> - <group> - <field name="name" invisible="1"/> - <field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, parent.partner_id)"/> - <label for="product_qty"/> - <div> - <field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)" class="oe_inline"/> - <field name="product_uom" string="Unit Of Measure" groups="product.group_uom" class="oe_inline"/> - <button name="%(stock.move_scrap)d" - string="Scrap" type="action" - icon="gtk-convert" context="{'scrap': True}" - states="draft,waiting,confirmed,assigned" - groups="base.group_user"/> - </div> - <label for="product_uos_qty" groups="product.group_uos"/> - <div groups="product.group_uos"> - <field name="product_uos_qty" on_change="onchange_uos_quantity(product_id, product_uos_qty, product_uos, product_uom)" class="oe_inline"/> - <field name="product_uos" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)" class="oe_inline"/> - </div> - <field name="product_packaging" groups="product.group_stock_packaging" domain="[('product_id','=',product_id)]"/> - </group> - <group> - <field name="create_date" invisible="1"/> - <field name="date"/> - <field name="date_expected" on_change="onchange_date(date,date_expected)"/> - </group> - - <group string="Locations" groups="stock.group_locations"> - <field name="location_id" domain="[('usage','<>','view')]"/> - <field name="location_dest_id" domain="[('usage','=','internal')]" groups="stock.group_locations"/> - </group> - - <group groups="stock.group_tracking_lot" string="Traceability"> - <label for="tracking_id"/> - <div> - <field name="tracking_id" groups="stock.group_tracking_lot" class="oe_inline"/> - <button name="%(split_into)d" string="New Pack" type="action" - groups="product.group_stock_packaging" - icon="terp-stock_effects-object-colorize" - states="draft,assigned,confirmed"/> - </div> - - <label for="prodlot_id"/> - <div> - <field name="prodlot_id" groups="stock.group_production_lot" - context="{'location_id':location_id, 'product_id':product_id}" - domain="[('product_id','=?',product_id)]" - on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id, product_uom)" class="oe_inline"/> - <button name="%(track_line)d" - groups="stock.group_tracking_lot" - states="draft,waiting,confirmed,assigned" - string="Split" type="action" icon="terp-stock_effects-object-colorize"/> - </div> - </group> - </group> - </form> - </field> + <field name="move_lines" context="{'address_in_id': partner_id, 'form_view_ref':'view_move_picking_form', 'tree_view_ref':'view_move_picking_tree'}"/> </page> <page string="Additional Info"> <group> <group> <field name="move_type"/> - <field name="type" groups="base.group_user"/> + <field name="type" groups="base.group_no_one"/> <field name="auto_picking" groups="base.group_user"/> </group> <group> <field name="company_id" groups="base.group_multi_company" widget="selection"/> - <field name="date_done"/> + <field name="date_done" groups="base.group_no_one"/> </group> </group> </page> @@ -972,7 +874,7 @@ <record id="view_picking_out_tree" model="ir.ui.view"> <field name="name">stock.picking.out.tree</field> - <field name="model">stock.picking</field> + <field name="model">stock.picking.out</field> <field name="arch" type="xml"> <tree colors="blue:state == 'draft';grey:state == 'cancel';red:state not in ('cancel', 'done') and min_date < current_date" string="Delivery Orders"> <field name="name"/> @@ -1002,13 +904,16 @@ <button name="action_assign" states="confirmed" string="Check Availability" type="object" class="oe_highlight"/> </xpath> <xpath expr="/form/header//button[@name='action_process']" position="replace"> - <button name="action_process" states="assigned" string="Deliver" type="object" icon="gtk-go-forward" class="oe_highlight"/> + <button name="action_process" states="assigned" string="Deliver" type="object" class="oe_highlight"/> </xpath> <xpath expr="/form/header//field[@name='state']" position="replace"> <field name="state" nolabel="1" readonly="1" widget="statusbar" statusbar_visible="draft,confirmed,assigned,done" statusbar_colors='{"auto":"blue", "confirmed":"blue"}'/> </xpath> <xpath expr="//field[@name='partner_id']" position="replace"> - <field name="partner_id" on_change="onchange_partner_in(partner_id)" colspan="4" string="Customer"/> + <field name="partner_id" on_change="onchange_partner_in(partner_id)" string="Customer"/> + </xpath> + <xpath expr="//field[@name='move_lines']" position="replace"> + <field name="move_lines" context="{'address_in_id': partner_id, 'picking_type': 'out', 'form_view_ref':'view_move_picking_form', 'tree_view_ref':'view_move_picking_tree'}"/> </xpath> <xpath expr="/form/sheet" position="after"> <div class="oe_chatter"> @@ -1131,7 +1036,10 @@ <button name="action_process" states="assigned" string="Receive" type="object" class="oe_highlight"/> </xpath> <xpath expr="//field[@name='partner_id']" position="replace"> - <field name="partner_id" on_change="onchange_partner_in(partner_id)" colspan="4" string="Supplier"/> + <field name="partner_id" on_change="onchange_partner_in(partner_id)" string="Supplier"/> + </xpath> + <xpath expr="//field[@name='move_lines']" position="replace"> + <field name="move_lines" context="{'address_in_id': partner_id, 'picking_type': 'in', 'form_view_ref':'view_move_picking_form', 'tree_view_ref':'view_move_picking_tree'}"/> </xpath> <xpath expr="/form/sheet" position="after"> <div class="oe_chatter"> @@ -1207,7 +1115,7 @@ </record> <menuitem action="action_picking_tree4" id="menu_action_picking_tree4" parent="menu_stock_warehouse_mgmt" sequence="1"/> - <menuitem action="action_picking_tree6" id="menu_action_picking_tree6" parent="menu_stock_warehouse_mgmt" sequence="2"/> + <menuitem action="action_picking_tree6" id="menu_action_picking_tree6" parent="menu_stock_warehouse_mgmt" sequence="2" groups="stock.group_locations"/> <record id="view_move_tree" model="ir.ui.view"> <field name="name">stock.move.tree</field> @@ -1218,6 +1126,7 @@ <field name="name"/> <field name="picking_id" string="Reference"/> <field name="origin"/> + <field name="type" on_change="onchange_move_type(type)"/> <field name="create_date" invisible="1" groups="base.group_no_one"/> <field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, False)"/> <field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/> @@ -1251,6 +1160,45 @@ </field> </record> + <record id="view_move_picking_tree" model="ir.ui.view"> + <field name="name">stock.move.tree</field> + <field name="model">stock.move</field> + <field eval="4" name="priority"/> + <field name="arch" type="xml"> + <tree colors="grey:scrapped == True" string="Stock Moves"> + <field name="product_id"/> + <field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/> + <field name="product_uom" string="Unit of Measure" groups="product.group_uom"/> + <field name="product_uos" groups="product.group_uos"/> + <button name="%(stock.move_scrap)d" + string="Scrap Products" type="action" + icon="gtk-convert" context="{'scrap': True}" + states="draft,waiting,confirmed,assigned" + groups="base.group_user"/> + <field name="scrapped" invisible="1"/> + <field name="prodlot_id" groups="stock.group_production_lot"/> + <button + name="%(stock.track_line)d" + string="Split in Serial Number" + groups="stock.group_production_lot" + type="action" icon="terp-stock_effects-object-colorize" + states="draft,waiting,confirmed,assigned"/> + <field groups="stock.group_tracking_lot" name="tracking_id"/> + <button name="setlast_tracking" string="Put in current pack" type="object" + attrs="{'invisible': [('tracking_id','<>',False)]}" + icon="terp-stock_effects-object-colorize" + groups="stock.group_tracking_lot" + states="draft,assigned,confirmed"/> + <button name="%(split_into)d" string="Put in a new pack" type="action" + groups="product.group_stock_packaging" + icon="terp-stock_effects-object-colorize" + states="draft,assigned,confirmed"/> + <field name="location_dest_id" groups="stock.group_locations"/> + <field name="state"/> + </tree> + </field> + </record> + <record id="view_move_form" model="ir.ui.view"> <field name="name">stock.move.form</field> <field name="model">stock.move</field> @@ -1292,6 +1240,7 @@ </group> <group name="origin_grp" string="Origin"> <field name="picking_id"/> + <field name="type" on_change="onchange_move_type(type)"/> <field name="location_id" groups="stock.group_locations"/> <field name="create_date" groups="base.group_no_one"/> </group> @@ -1329,6 +1278,81 @@ </field> </record> + <record id="view_move_picking_form" model="ir.ui.view"> + <field name="name">stock.move.form</field> + <field name="model">stock.move</field> + <field eval="2" name="priority"/> + <field name="arch" type="xml"> + <form string="Stock Moves" version="7.0"> + <header> + <span groups="base.group_user"> + <button name="force_assign" states="confirmed" string="Force Availability" type="object"/> + <button name="action_confirm" states="draft" string="Confirm" type="object"/> + <button name="cancel_assign" states="assigned" string="Cancel Availability" type="object"/> + </span> + <field name="state" widget="statusbar" statusbar_visible="draft,assigned,done"/> + </header> + <group> + <group> + <field name="name" invisible="1"/> + <field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, parent.partner_id)"/> + <field name="type" invisible="1"/> + <label for="product_qty"/> + <div> + <field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)" class="oe_inline"/> + <field name="product_uom" string="Unit Of Measure" groups="product.group_uom" class="oe_inline"/> + <button name="%(stock.move_scrap)d" + string="Scrap" type="action" + icon="gtk-convert" context="{'scrap': True}" + states="draft,waiting,confirmed,assigned" + groups="base.group_user"/> + </div> + <label for="product_uos_qty" groups="product.group_uos"/> + <div groups="product.group_uos"> + <field name="product_uos_qty" on_change="onchange_uos_quantity(product_id, product_uos_qty, product_uos, product_uom)" class="oe_inline"/> + <field name="product_uos" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)" class="oe_inline"/> + </div> + <field name="product_packaging" groups="product.group_stock_packaging" domain="[('product_id','=',product_id)]"/> + </group> + <group> + <field name="create_date" invisible="1"/> + <field name="date"/> + <field name="date_expected" on_change="onchange_date(date,date_expected)"/> + </group> + + <group string="Locations" groups="stock.group_locations"> + <field name="location_id" domain="[('usage','<>','view')]"/> + <field name="location_dest_id" domain="[('usage','=','internal')]" groups="stock.group_locations"/> + </group> + + <group groups="stock.group_tracking_lot" string="Traceability"> + <label for="tracking_id"/> + <div> + <field name="tracking_id" groups="stock.group_tracking_lot" class="oe_inline"/> + <button name="%(split_into)d" + string="New Pack" type="action" + groups="product.group_stock_packaging" + icon="terp-stock_effects-object-colorize" + states="draft,assigned,confirmed"/> + </div> + + <label for="prodlot_id"/> + <div> + <field name="prodlot_id" groups="stock.group_production_lot" + context="{'location_id':location_id, 'product_id':product_id}" + domain="[('product_id','=?',product_id)]" + on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id, product_uom)" class="oe_inline"/> + <button name="%(track_line)d" + groups="stock.group_tracking_lot" + states="draft,waiting,confirmed,assigned" + string="Split" type="action" icon="terp-stock_effects-object-colorize"/> + </div> + </group> + </group> + </form> + </field> + </record> + <record id="view_move_search" model="ir.ui.view"> <field name="name">stock.move.search</field> <field name="model">stock.move</field> @@ -1380,6 +1404,21 @@ </p> </field> </record> + + <record model="ir.actions.act_window.view" id="action_stock_move_tree_all"> + <field name="sequence" eval="1"/> + <field name="view_mode">tree</field> + <field name="view_id" ref="view_move_tree"/> + <field name="act_window_id" ref="action_move_form2"/> + </record> + + <record model="ir.actions.act_window.view" id="action_stock_move_form_all"> + <field name="sequence" eval="3"/> + <field name="view_mode">form</field> + <field name="view_id" ref="view_move_form"/> + <field name="act_window_id" ref="action_move_form2"/> + </record> + <menuitem action="action_move_form2" id="menu_action_move_form2" parent="menu_traceability" sequence="3"/> <!-- @@ -1453,7 +1492,7 @@ <field name="view_mode">tree,form</field> <field name="domain">['|','&',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False),('picking_id.type','=','in')]</field> <field name="view_id" ref="view_move_tree_reception_picking"/> - <field name="context" eval="'{\'product_receive\' : True, \'default_location_id\':%d, \'default_location_dest_id\':%d, \'search_default_future\': 1}' % (ref('stock_location_suppliers'),ref('stock_location_stock') )"/> + <field name="context">{'product_receive': True, 'search_default_future': True, 'picking_type': 'in'}</field> <field name="help" type="html"> <p> Click to register a product reception. @@ -1588,7 +1627,7 @@ <field name="view_mode">tree,form</field> <field name="domain">['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False),('picking_id.type','=','out')]</field> <field name="view_id" ref="view_move_tree_reception_picking"/> - <field name="context" eval="'{\'default_location_id\':%d, \'default_location_dest_id\':%d, \'search_default_future\': 1}' % (ref('stock_location_stock'),ref('stock_location_customers'))"/> + <field name="context">{'picking_type': 'out', 'search_default_future': True}</field> <field name="help" type="html"> <p> You will find in this list all products you have to deliver to diff --git a/addons/stock/wizard/stock_fill_inventory.py b/addons/stock/wizard/stock_fill_inventory.py index 10a1d625e16..9b730d22982 100644 --- a/addons/stock/wizard/stock_fill_inventory.py +++ b/addons/stock/wizard/stock_fill_inventory.py @@ -25,11 +25,23 @@ from tools.translate import _ class stock_fill_inventory(osv.osv_memory): _name = "stock.fill.inventory" _description = "Import Inventory" + + def _default_location(self, cr, uid, ids, context=None): + try: + loc_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock') + except ValueError, e: + return False + return location_id or False + _columns = { 'location_id': fields.many2one('stock.location', 'Location', required=True), 'recursive': fields.boolean("Include children",help="If checked, products contained in child locations of selected location will be included as well."), 'set_stock_zero': fields.boolean("Set to zero",help="If checked, all product quantities will be set to zero to help ensure a real physical inventory is done"), } + _defaults = { + 'location_id': _default_location, + } + def view_init(self, cr, uid, fields_list, context=None): """ Creates view dynamically and adding fields at runtime. diff --git a/addons/stock/wizard/stock_fill_inventory_view.xml b/addons/stock/wizard/stock_fill_inventory_view.xml index 47e6355bcdc..5533bf0580e 100644 --- a/addons/stock/wizard/stock_fill_inventory_view.xml +++ b/addons/stock/wizard/stock_fill_inventory_view.xml @@ -8,8 +8,8 @@ <form string="Import Inventory" version="7.0"> <separator string="Import current product inventory from the following location"/> <group> - <field name="location_id"/> - <field name="recursive"/> + <field name="location_id" groups="stock.group_locations"/> + <field name="recursive" groups="stock.group_locations"/> <field name="set_stock_zero"/> </group> <footer> @@ -21,14 +21,16 @@ </field> </record> - <act_window name="Import Inventory" - res_model="stock.fill.inventory" - src_model="stock.inventory" - view_mode="form" - target="new" - context="{'search_default_in_location':1}" - key2="client_action_multi" - id="action_view_stock_fill_inventory"/> - + <record id="action_view_stock_fill_inventory" model="ir.actions.act_window"> + <field name="name">Fill Inventory</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">stock.fill.inventory</field> + <field name="view_type">form</field> + <field name="view_mode">form</field> + <field name="view_id" ref="view_stock_fill_inventory"/> + <field name="target">new</field> + <field name="context">{'search_default_in_location':1}</field> + </record> + </data> </openerp> diff --git a/addons/stock/wizard/stock_partial_picking.py b/addons/stock/wizard/stock_partial_picking.py index b3720b8a51b..755da7c42ee 100644 --- a/addons/stock/wizard/stock_partial_picking.py +++ b/addons/stock/wizard/stock_partial_picking.py @@ -78,7 +78,7 @@ class stock_partial_picking(osv.osv_memory): if context is None: context={} res = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) - type = context.get('active_model','').split('.')[-1] + type = context.get('default_type', False) if type: doc = etree.XML(res['arch']) for node in doc.xpath("//button[@name='do_partial']"): |
