From b5793bc85b97e99b89875417f1212a9be471fca7 Mon Sep 17 00:00:00 2001 From: Mohammed Shekha Date: Mon, 1 Apr 2013 11:05:00 +0530 Subject: [PATCH 001/140] [FIX]Fixed the issue of file input widget which is not working in firefox and IE. bzr revid: msh@openerp.com-20130401053500-q8tsnnr59u2aqawt --- addons/web/static/src/css/base.css | 9 +++++---- addons/web/static/src/css/base.sass | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index 385405e39ca..cbfa554c735 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -1,4 +1,4 @@ -@charset "utf-8"; +@charset "UTF-8"; @font-face { font-family: "mnmliconsRegular"; src: url("/web/static/src/font/mnmliconsv21-webfont.eot") format("eot"); @@ -1269,7 +1269,7 @@ color: white; padding: 2px 4px; margin: 1px 6px 0 0; - border: 1px solid lightGray; + border: 1px solid lightgrey; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -1301,7 +1301,7 @@ transform: scale(1.1); } .openerp .oe_secondary_submenu .oe_active { - border-top: 1px solid lightGray; + border-top: 1px solid lightgrey; border-bottom: 1px solid #dedede; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2), inset 0 -1px 3px rgba(40, 40, 40, 0.2); @@ -2284,7 +2284,7 @@ } .openerp .oe_form .oe_form_label_help[for] span, .openerp .oe_form .oe_form_label[for] span { font-size: 80%; - color: darkGreen; + color: darkgreen; vertical-align: top; position: relative; top: -4px; @@ -2475,6 +2475,7 @@ } .openerp .oe_hidden_input_file { position: relative; + overflow-x: hidden; } .openerp .oe_hidden_input_file input.oe_form_binary_file { z-index: 0; diff --git a/addons/web/static/src/css/base.sass b/addons/web/static/src/css/base.sass index 5fe5b1ceaf4..fcace37ec03 100644 --- a/addons/web/static/src/css/base.sass +++ b/addons/web/static/src/css/base.sass @@ -1967,6 +1967,7 @@ $sheet-padding: 16px // Position: relative is used for the hidden input[type=file] // Do not remove it anymore ! position: relative + overflow-x: hidden input.oe_form_binary_file z-index: 0 line-height: 0 From 7c1f4fb61973276d401050c1a243bd3100a9b8f4 Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Thu, 20 Feb 2014 15:59:58 +0530 Subject: [PATCH 002/140] [IMP]convert subtypes list into selection. bzr revid: dka@tinyerp.com-20140220102958-l2uwymwtnzcxnetw --- addons/mail/static/src/css/mail.css | 2 +- addons/mail/static/src/js/mail_followers.js | 8 ++--- addons/mail/static/src/xml/mail_followers.xml | 34 ++++++++++++------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index bfae7571a9c..090a7ac0924 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -576,7 +576,7 @@ .openerp .oe_followers button.oe_follower{ display: block; text-align: center; - width:100%; + width:135px; } .openerp .oe_followers button.oe_follower.oe_following{ color: white; diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 938d6a01f6d..a058f453639 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -246,7 +246,7 @@ openerp_mail_followers = function(session, mail) { if (user_pid) { dialog = true; } else { - var subtype_list_ul = this.$('.oe_subtype_list').empty(); + var subtype_list_ul = this.$('.oe_subtype_list ul').empty(); if (! this.message_is_follower) return; } var id = this.view.datarecord.id; @@ -261,9 +261,8 @@ openerp_mail_followers = function(session, mail) { var $list = self.$dialog; } else { - var $list = this.$('.oe_subtype_list'); + var $list = this.$('.oe_subtype_list ul'); } - $list.empty().hide(); var records = data[id].message_subtype_data; this.records_length = $.map(records, function(value, index) { return index; }).length; if (this.records_length > 1) { self.display_followers(); } @@ -272,9 +271,6 @@ openerp_mail_followers = function(session, mail) { record.followed = record.followed || undefined; $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo($list); }); - if (_.size(records) > 1) { - $list.show(); - } }, do_follow: function () { diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index a936b8237d6..2aa27a6bc27 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -5,17 +5,23 @@ followers main template Template used to display the followers, the actions and the subtypes in a record. --> -
+
- +
+ + + +
+
-

Followers

@@ -40,12 +46,14 @@ Template used to display message subtypes of a follower subscription --> - - - - - -
+
  • + + + + + +
    +
  • From 30201e75fd54fae19f454df9b0f9a78edacbc64a Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Thu, 20 Feb 2014 16:56:38 +0530 Subject: [PATCH 003/140] [IMP]improve spacing. bzr revid: dka@tinyerp.com-20140220112638-5in8gomndoy3z08g --- addons/mail/static/src/xml/mail_followers.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index 2aa27a6bc27..e3667f183f8 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -14,7 +14,7 @@ Following
    @@ -49,7 +49,7 @@
  • - +
    From 1e16c40ab00f21f49a12b6c43b08df864d400b90 Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Fri, 21 Feb 2014 10:21:07 +0530 Subject: [PATCH 004/140] [IMP]mail_followers: remove li from dropdown and keep table as it is. bzr revid: dka@tinyerp.com-20140221045107-ete68out3asvjign --- addons/mail/static/src/xml/mail_followers.xml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index e3667f183f8..8982e1d3b18 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -46,14 +46,12 @@ Template used to display message subtypes of a follower subscription --> -
  • - - - - - -
    -
  • + + + + + +
    From 37a119cbc8f927223f4cc2de10581413e6b56d81 Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Mon, 24 Feb 2014 15:19:51 +0530 Subject: [PATCH 005/140] [IMP]mail_follower:improved subtype selection event to keep dropdown list open untill click outside of dropdown or on the follow/unfollow button. bzr revid: dka@tinyerp.com-20140224094951-hixzix3ptl6f2g5e --- addons/mail/static/src/js/mail_followers.js | 13 +++++++++---- addons/mail/static/src/xml/mail_followers.xml | 8 ++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index e192204f693..c36e1176114 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -70,7 +70,13 @@ openerp_mail_followers = function(session, mail) { self.do_unfollow(); }); // event: click on a subtype, that (un)subscribe for this subtype - this.$el.on('click', '.oe_subtype_list input', self.do_update_subscription); + this.$el.on('click', '.oe_subtype_list input', function(event) { + self.do_update_subscription(); + $list = self.$('.oe_subtype_list'); + if(!$list.hasClass('open')) + $list.addClass('open') + event.stopPropagation(); + }); // event: click on 'invite' button, that opens the invite wizard this.$('.oe_invite').on('click', self.on_invite_follower); // event: click on 'edit_subtype(pencil)' button to edit subscription @@ -267,7 +273,7 @@ openerp_mail_followers = function(session, mail) { _(records).each(function (record, record_name) { record.name = record_name; record.followed = record.followed || undefined; - $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo($list); + $(session.web.qweb.render('mail.followers.subtype', {'record': record,'dialog': dialog})).appendTo($list); }); }, @@ -323,8 +329,7 @@ openerp_mail_followers = function(session, mail) { } } else { var context = new session.web.CompoundContext(this.build_context(), {}); - return this.ds_model.call(action_subscribe, [[this.view.datarecord.id], follower_ids, checklist, context]) - .then(this.proxy('read_value')); + return this.ds_model.call(action_subscribe, [[this.view.datarecord.id], follower_ids, checklist, context]).then(this.proxy('read_value')); } }, }); diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index 5ec73716c5e..35a5ad320bb 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -48,8 +48,12 @@ - - + +
    + + + +
    From 8bf832b259840a386b60bc55afd083aef1e361ab Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Mon, 24 Feb 2014 15:37:58 +0530 Subject: [PATCH 006/140] [IMP]improved spacing. bzr revid: dka@tinyerp.com-20140224100758-ibz8u54u7sv68yqz --- addons/mail/static/src/js/mail_followers.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index c36e1176114..0e674efcf52 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -273,7 +273,7 @@ openerp_mail_followers = function(session, mail) { _(records).each(function (record, record_name) { record.name = record_name; record.followed = record.followed || undefined; - $(session.web.qweb.render('mail.followers.subtype', {'record': record,'dialog': dialog})).appendTo($list); + $(session.web.qweb.render('mail.followers.subtype', {'record': record, 'dialog': dialog})).appendTo($list); }); }, @@ -329,7 +329,8 @@ openerp_mail_followers = function(session, mail) { } } else { var context = new session.web.CompoundContext(this.build_context(), {}); - return this.ds_model.call(action_subscribe, [[this.view.datarecord.id], follower_ids, checklist, context]).then(this.proxy('read_value')); + return this.ds_model.call(action_subscribe, [[this.view.datarecord.id], follower_ids, checklist, context]) + .then(this.proxy('read_value')); } }, }); From dad39a22d6c6966bfe8f1e7afa7ae09dd4aa4454 Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Mon, 24 Feb 2014 16:22:49 +0530 Subject: [PATCH 007/140] [IMP]solved Error Cannot read property 'target' of undefined. bzr revid: dka@tinyerp.com-20140224105249-lr50s4x6bvhbl1tx --- addons/mail/static/src/js/mail_followers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 5823def2dc0..245bd4ee369 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -71,7 +71,7 @@ openerp_mail_followers = function(session, mail) { }); // event: click on a subtype, that (un)subscribe for this subtype this.$el.on('click', '.oe_subtype_list input', function(event) { - self.do_update_subscription(); + self.do_update_subscription(event); $list = self.$('.oe_subtype_list'); if(!$list.hasClass('open')) $list.addClass('open') From 7dc413070c396c7ad3318ccde9c1415d91c20e3f Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Tue, 25 Feb 2014 10:21:42 +0530 Subject: [PATCH 008/140] [IMP]mail_follower:closed dropdown when there is no child element in ul. bzr revid: dka@tinyerp.com-20140225045142-fg6qbnlvl4ylys0k --- addons/mail/static/src/js/mail_followers.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 947667627d7..955049f2e25 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -73,8 +73,12 @@ openerp_mail_followers = function(session, mail) { this.$el.on('click', '.oe_subtype_list input', function(event) { self.do_update_subscription(event); var $list = self.$('.oe_subtype_list'); - if(!$list.hasClass('open')) + if(!$list.hasClass('open')) { $list.addClass('open'); + } + if(self.$('.oe_subtype_list ul')[0].children.length < 1) { + $list.removeClass('open'); + } event.stopPropagation(); }); // event: click on 'invite' button, that opens the invite wizard @@ -296,6 +300,7 @@ openerp_mail_followers = function(session, mail) { }, do_unfollow: function (user_pid) { + var self = this; if (confirm(_t("Warning! \nYou won't be notified of any email or discussion on this document. Do you really want to unfollow this document ?"))) { _(this.$('.oe_msg_subtype_check')).each(function (record) { $(record).attr('checked',false); @@ -334,6 +339,8 @@ openerp_mail_followers = function(session, mail) { if (!checklist.length) { if (!this.do_unfollow(user_pid)) { $(event.target).attr("checked", "checked"); + } else { + self.$('.oe_subtype_list ul').empty(); } } else { var context = new session.web.CompoundContext(this.build_context(), {}); From 0eb99442224bb12bedc7150139796e8de64a7e1f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Mon, 24 Mar 2014 09:50:46 +0100 Subject: [PATCH 009/140] [IMP] refactoring of readgroup method. It should have the same functionality, but is much simpler. This is necessary to implement eager groupby (orm.py) bzr revid: ged@openerp.com-20140324085046-zpfpcostivf8454q --- openerp/osv/orm.py | 230 ++++++++++++++++++++------------------------- 1 file changed, 100 insertions(+), 130 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 64fa06783ab..cc8e7aa066b 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2222,7 +2222,7 @@ class BaseModel(object): self._name, order_part) return groupby_terms, orderby_terms - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context={}, orderby=False): """ Get the list of records in list view grouped by the given ``groupby`` fields @@ -2252,91 +2252,80 @@ class BaseModel(object): * if user tries to bypass access rules for read on the requested object """ - context = context or {} self.check_access_rights(cr, uid, 'read') - if not fields: - fields = self._columns.keys() - query = self._where_calc(cr, uid, domain, context=context) - self._apply_ir_rules(cr, uid, query, 'read', context=context) - - # Take care of adding join(s) if groupby is an '_inherits'ed field - groupby_list = groupby - qualified_groupby_field = groupby - if groupby: - if isinstance(groupby, list): - groupby = groupby[0] - splitted_groupby = groupby.split(':') - if len(splitted_groupby) == 2: - groupby = splitted_groupby[0] - groupby_function = splitted_groupby[1] - else: - groupby_function = False - qualified_groupby_field = self._inherits_join_calc(groupby, query) - - if groupby: - assert not groupby or groupby in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)" - groupby_def = self._columns.get(groupby) or (self._inherit_fields.get(groupby) and self._inherit_fields.get(groupby)[2]) - assert groupby_def and groupby_def._classic_write, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True" - - # TODO it seems fields_get can be replaced by _all_columns (no need for translation) + # Step 0 : preparing some useful variables + fields = fields or self._columns.keys() fget = self.fields_get(cr, uid, fields) - group_by_params = {} - select_terms = [] - groupby_type = None - if groupby: - if fget.get(groupby): - groupby_type = fget[groupby]['type'] - if groupby_type in ('date', 'datetime'): - if groupby_function: - interval = groupby_function - else: - interval = 'month' + if isinstance(groupby, basestring): + groupby = [groupby] + split_groupby = groupby[0].split(':') if groupby else None + first_groupby = split_groupby[0] if split_groupby else None + groupby_function = split_groupby[1] if split_groupby and len(split_groupby) == 2 else None + interval = groupby_function if groupby_function else 'month' + groupby_type = fget[first_groupby]['type'] if first_groupby else None + if groupby_type in ('date', 'datetime'): + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby_type == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + tz_convert = groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones + time_display_format = { + 'day': 'dd MMM YYYY', + 'week': "'W'w YYYY", + 'month': 'MMMM YYYY', + 'quarter': 'QQQ YYYY', + 'year': 'YYYY'}[interval] + time_interval = { + 'day': dateutil.relativedelta.relativedelta(months=3), + 'week': datetime.timedelta(days=7), + 'month': dateutil.relativedelta.relativedelta(months=1), + 'quarter': dateutil.relativedelta.relativedelta(months=3), + 'year': dateutil.relativedelta.relativedelta(years=1)}[interval] - if interval == 'day': - display_format = 'dd MMM YYYY' - elif interval == 'week': - display_format = "'W'w YYYY" - elif interval == 'month': - display_format = 'MMMM YYYY' - elif interval == 'quarter': - display_format = 'QQQ YYYY' - elif interval == 'year': - display_format = 'YYYY' + query = self._where_calc(cr, uid, domain, context=context) - if groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones: - # Convert groupby result to user TZ to avoid confusion! - # PostgreSQL is compatible with all pytz timezone names, so we can use them - # directly for conversion, starting with timestamps stored in UTC. - timezone = context.get('tz', 'UTC') - qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field) - qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field) - elif groupby_type == 'boolean': - qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field - select_terms.append("%s as %s " % (qualified_groupby_field, groupby)) - else: + # Step 1: security stuff + # add relevant ir_rules to the where clause, perform some basic sanity checks + self._apply_ir_rules(cr, uid, query, 'read', context=context) + if first_groupby: + assert first_groupby in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)" + groupby_def = self._columns.get(first_groupby) or (self._inherit_fields.get(first_groupby) and self._inherit_fields.get(first_groupby)[2]) + assert groupby_def and groupby_def._classic_write, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True" + if not (first_groupby in fget): # Don't allow arbitrary values, as this would be a SQL injection vector! raise except_orm(_('Invalid group_by'), - _('Invalid group_by specification: "%s".\nA group_by specification must be a list of valid fields.')%(groupby,)) + _('Invalid group_by specification: "%s".\nA group_by specification must be a list of valid fields.')%(first_groupby,)) + # Step 2: preparing the query: + # compute aggregated fields, format groupbys, adjust timezone, ... aggregated_fields = [ f for f in fields if f not in ('id', 'sequence', groupby) if fget[f]['type'] in ('integer', 'float') if (f in self._all_columns and getattr(self._all_columns[f].column, '_classic_write'))] - for f in aggregated_fields: - group_operator = fget[f].get('group_operator', 'sum') - qualified_field = self._inherits_join_calc(f, query) - select_terms.append("%s(%s) AS %s" % (group_operator, qualified_field, f)) - order = orderby or groupby or '' - groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type) + field_formatter = lambda f: (fget[f].get('group_operator', 'sum'), self._inherits_join_calc(f, query), f) + select_terms = ["%s(%s) AS %s" % field_formatter(f) for f in aggregated_fields] + + qualified_groupby_field = self._inherits_join_calc(first_groupby, query) if first_groupby else None + + if groupby_type in ('date', 'datetime'): + if tz_convert: + # Convert groupby result to user TZ to avoid confusion! + # PostgreSQL is compatible with all pytz timezone names, so we can use them + # directly for conversion, starting with timestamps stored in UTC. + timezone = context.get('tz', 'UTC') + qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field) + qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field) + + if groupby_type == 'boolean': + qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field + + if first_groupby: + select_terms.append("%s as %s " % (qualified_groupby_field, first_groupby)) + + order = orderby or first_groupby or '' + groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, first_groupby, qualified_groupby_field, query, groupby_type) from_clause, where_clause, where_clause_params = query.get_sql() - if len(groupby_list) < 2 and context.get('group_by_no_leaf'): - count_field = '_' - else: - count_field = groupby prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else '' prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else '' @@ -2352,7 +2341,7 @@ class BaseModel(object): %(offset)s """ % { 'table': self._table, - 'count_field': count_field, + 'count_field': '_' if (len(groupby) < 2 and context.get('group_by_no_leaf')) else first_groupby, 'extra_fields': prefix_terms(',', select_terms), 'from': from_clause, 'where': prefix_term('WHERE', where_clause), @@ -2362,73 +2351,54 @@ class BaseModel(object): 'offset': prefix_term('OFFSET', int(offset) if limit else None), } cr.execute(query, where_clause_params) - alldata = {} - fetched_data = cr.dictfetchall() - data_ids = [] - for r in fetched_data: - for fld, val in r.items(): - if val is None: r[fld] = False - alldata[r['id']] = r - data_ids.append(r['id']) - del r['id'] + if not first_groupby: + return {r.pop('id'): r for r in cr.dictfetchall() } - if groupby: - data = self.read(cr, uid, data_ids, [groupby], context=context) - # restore order of the search as read() uses the default _order (this is only for groups, so the footprint of data should be small): - data_dict = dict((d['id'], d[groupby] ) for d in data) - result = [{'id': i, groupby: data_dict[i]} for i in data_ids] - else: - result = [{'id': i} for i in data_ids] + none_to_false = lambda record: {k: (False if v is None else v) for k,v in record.iteritems() } + fetched_data = map(none_to_false, cr.dictfetchall()) - for d in result: - if groupby: - d['__domain'] = [(groupby, '=', alldata[d['id']][groupby] or False)] + domain - if not isinstance(groupby_list, (str, unicode)): - if groupby or not context.get('group_by_no_leaf', False): - d['__context'] = {'group_by': groupby_list[1:]} - if groupby and groupby in fget: - groupby_type = fget[groupby]['type'] - if d[groupby] and groupby_type in ('date', 'datetime'): - groupby_datetime = alldata[d['id']][groupby] - if isinstance(groupby_datetime, basestring): - _default = datetime.datetime(1970, 1, 1) # force starts of month - groupby_datetime = dateutil.parser.parse(groupby_datetime, default=_default) - tz_convert = groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones - if tz_convert: - groupby_datetime = pytz.timezone(context['tz']).localize(groupby_datetime) - d[groupby] = babel.dates.format_date( - groupby_datetime, format=display_format, locale=context.get('lang', 'en_US')) - domain_dt_begin = groupby_datetime - if interval == 'quarter': - domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(months=3) - elif interval == 'month': - domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(months=1) - elif interval == 'week': - domain_dt_end = groupby_datetime + datetime.timedelta(days=7) - elif interval == 'day': - domain_dt_end = groupby_datetime + datetime.timedelta(days=1) - else: - domain_dt_end = groupby_datetime + dateutil.relativedelta.relativedelta(years=1) - if tz_convert: - # the time boundaries were all computed in the apparent TZ of the user, - # so we need to convert them to UTC to have proper server-side values. - domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) - domain_dt_end = domain_dt_end.astimezone(pytz.utc) - dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby_type == 'datetime' else DEFAULT_SERVER_DATE_FORMAT - d['__domain'] = [(groupby, '>=', domain_dt_begin.strftime(dt_format)), - (groupby, '<', domain_dt_end.strftime(dt_format))] + domain - del alldata[d['id']][groupby] - d.update(alldata[d['id']]) - del d['id'] + data_ids = [r['id'] for r in fetched_data] + data_dict = {d['id']: d[first_groupby] for d in self.read(cr, uid, data_ids, [first_groupby], context=context)} + sorted_data = [{first_groupby: data_dict[id]} for id in data_ids] - if groupby and groupby in self._group_by_full: - result = self._read_group_fill_results(cr, uid, domain, groupby, groupby_list, + def format_result (fromquery, fromread): + result = { + '__domain': [(first_groupby, '=', fromquery[first_groupby] or False)] + domain, + '__context': {'group_by': groupby[1:]} + } + result.update(fromquery) + result.update(fromread) + + if groupby_type in ('date', 'datetime') and fromquery[first_groupby]: + groupby_datetime = fromquery[first_groupby] + if isinstance(groupby_datetime, basestring): + groupby_datetime = datetime.datetime.strptime(groupby_datetime, dt_format) + if tz_convert: + groupby_datetime = pytz.timezone(context['tz']).localize(groupby_datetime) + result[first_groupby] = babel.dates.format_date( + groupby_datetime, format=time_display_format, locale=context.get('lang', 'en_US')) + domain_dt_begin = groupby_datetime + domain_dt_end = groupby_datetime + time_interval + if tz_convert: + # the time boundaries were all computed in the apparent TZ of the user, + # so we need to convert them to UTC to have proper server-side values. + domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) + domain_dt_end = domain_dt_end.astimezone(pytz.utc) + result['__domain'] = [(first_groupby, '>=', domain_dt_begin.strftime(dt_format)), + (first_groupby, '<', domain_dt_end.strftime(dt_format))] + domain + del result['id'] + return result + + result = map(format_result, fetched_data, sorted_data) + + if first_groupby in self._group_by_full: + result = self._read_group_fill_results(cr, uid, domain, first_groupby, groupby, aggregated_fields, result, read_group_order=order, context=context) - return result + def _inherits_join_add(self, current_model, parent_model_name, query): """ Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates) From 27f38edb258a6f327c90863f16397126cc269c9b Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 25 Mar 2014 11:07:22 +0100 Subject: [PATCH 010/140] [FIX] dirty saas-3 fix for url lang switching with model converters bzr revid: fme@openerp.com-20140325100722-temaci88fowcr2m5 --- addons/website/models/ir_http.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 46b9efc15a8..696734b5f05 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -65,7 +65,7 @@ class ir_http(orm.AbstractModel): def reroute(self, path): if not hasattr(request, 'rerouting'): - request.rerouting = [] + request.rerouting = [request.httprequest.path] if path in request.rerouting: raise Exception("Rerouting loop is forbidden") request.rerouting.append(path) @@ -79,7 +79,11 @@ class ir_http(orm.AbstractModel): return self._dispatch() def _postprocess_args(self, arguments): - url = request.httprequest.url + if hasattr(request, 'rerouting'): + url = request.rerouting[0] + else: + url = request.httprequest.url + original_url = url for arg in arguments.itervalues(): if isinstance(arg, orm.browse_record) and isinstance(arg._uid, RequestUID): placeholder = arg._uid @@ -91,7 +95,7 @@ class ir_http(orm.AbstractModel): url = url.replace(placeholder.value, good_slug) except KeyError: return self._handle_exception(werkzeug.exceptions.NotFound()) - if url != request.httprequest.url: + if url != original_url: werkzeug.exceptions.abort(werkzeug.utils.redirect(url)) def _handle_exception(self, exception=None, code=500): From 30e787511f743648c7c86d932e215a854b7a5448 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Tue, 25 Mar 2014 17:11:04 +0100 Subject: [PATCH 011/140] [IMP] refactoring of readgroup method, to make it eager. Still incomplete, but it is mostly working (orm.py) bzr revid: ged@openerp.com-20140325161104-d0xgof4bcskh4ie6 --- openerp/osv/orm.py | 217 +++++++++++++++++++++++++-------------------- 1 file changed, 119 insertions(+), 98 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index cc8e7aa066b..ac07a6f5bca 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -55,7 +55,7 @@ import traceback import types import babel.dates -import dateutil.parser +import dateutil.relativedelta import psycopg2 from lxml import etree @@ -2185,20 +2185,21 @@ class BaseModel(object): r['__fold'] = folded.get(r[groupby] and r[groupby][0], False) return result - def _read_group_prepare(self, orderby, aggregated_fields, groupby, qualified_groupby_field, query, groupby_type=None): + def _read_group_prepare(self, orderby, aggregated_fields, annotated_groupbys, query, fget): """ Prepares the GROUP BY and ORDER BY terms for the read_group method. Adds the missing JOIN clause to the query if order should be computed against m2o field. :param orderby: the orderby definition in the form "%(field)s %(order)s" :param aggregated_fields: list of aggregated fields in the query :param groupby: the current groupby field name - :param qualified_groupby_field: the fully qualified SQL name for the grouped field + :param qualified_field: the fully qualified SQL name for the grouped field :param osv.Query query: the query under construction :param groupby_type: the type of the grouped field :return: (groupby_terms, orderby_terms) """ orderby_terms = [] - groupby_terms = [qualified_groupby_field] if groupby else [] + groupby_terms = [gb['qualified_field'] for gb in annotated_groupbys] + groupby_fields = [gb['field'] for gb in annotated_groupbys] if not orderby: return groupby_terms, orderby_terms @@ -2206,8 +2207,9 @@ class BaseModel(object): for order_part in orderby.split(','): order_split = order_part.split() order_field = order_split[0] - if order_field == groupby: - if groupby_type == 'many2one': + if order_field in groupby_fields: + + if fget[order_field]['type'] == 'many2one': order_clause = self._generate_order_by(order_part, query).replace('ORDER BY ', '') if order_clause: orderby_terms.append(order_clause) @@ -2222,7 +2224,7 @@ class BaseModel(object): self._name, order_part) return groupby_terms, orderby_terms - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context={}, orderby=False): + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context={}, orderby=False, lazy=True): """ Get the list of records in list view grouped by the given ``groupby`` fields @@ -2242,6 +2244,9 @@ class BaseModel(object): overriding the natural sort ordering of the groups, see also :py:meth:`~osv.osv.osv.search` (supported only for many2one fields currently) + :param bool lazy: if true, the results are only grouped by the first groupby and the + remaining groupbys are put in the __context key. If false, all the groupbys are + done in one call. :return: list of dictionaries(one dictionary for each record) containing: * the values of fields grouped by the fields in ``groupby`` argument @@ -2253,86 +2258,84 @@ class BaseModel(object): """ self.check_access_rights(cr, uid, 'read') - - # Step 0 : preparing some useful variables + query = self._where_calc(cr, uid, domain, context=context) fields = fields or self._columns.keys() fget = self.fields_get(cr, uid, fields) - if isinstance(groupby, basestring): - groupby = [groupby] - split_groupby = groupby[0].split(':') if groupby else None - first_groupby = split_groupby[0] if split_groupby else None - groupby_function = split_groupby[1] if split_groupby and len(split_groupby) == 2 else None - interval = groupby_function if groupby_function else 'month' - groupby_type = fget[first_groupby]['type'] if first_groupby else None - if groupby_type in ('date', 'datetime'): - dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby_type == 'datetime' else DEFAULT_SERVER_DATE_FORMAT - tz_convert = groupby_type == 'datetime' and context.get('tz') in pytz.all_timezones - time_display_format = { - 'day': 'dd MMM YYYY', - 'week': "'W'w YYYY", - 'month': 'MMMM YYYY', - 'quarter': 'QQQ YYYY', - 'year': 'YYYY'}[interval] - time_interval = { - 'day': dateutil.relativedelta.relativedelta(months=3), - 'week': datetime.timedelta(days=7), - 'month': dateutil.relativedelta.relativedelta(months=1), - 'quarter': dateutil.relativedelta.relativedelta(months=3), - 'year': dateutil.relativedelta.relativedelta(years=1)}[interval] + groupby = [groupby] if isinstance(groupby, basestring) else groupby + display_formats = { + 'day': 'dd MMM YYYY', + 'week': "'W'w YYYY", + 'month': 'MMMM YYYY', + 'quarter': 'QQQ YYYY', + 'year': 'YYYY' + } + time_intervals = { + 'day': dateutil.relativedelta.relativedelta(months=3), + 'week': datetime.timedelta(days=7), + 'month': dateutil.relativedelta.relativedelta(months=1), + 'quarter': dateutil.relativedelta.relativedelta(months=3), + 'year': dateutil.relativedelta.relativedelta(years=1) + } - query = self._where_calc(cr, uid, domain, context=context) + def process_groupby (gb): + split = gb.split(':') + field_type = fget[split[0]]['type'] + gb_function = split[1] if len(split) == 2 else None + temporal = field_type in ('date', 'datetime') + tz_convert = field_type == 'datetime' and context.get('tz') in pytz.all_timezones + qualified_field = self._inherits_join_calc(split[0], query) + if temporal: + if tz_convert: + qualified_field = "timezone('%s', timezone('UTC',%s))" % (context.get('tz', 'UTC'), qualified_field) + qualified_field = "date_trunc('%s', %s)" % (gb_function or 'month', qualified_field) + if field_type == 'boolean': + qualified_field = "coalesce(%s,false)" % qualified_field + return { + 'field': split[0], + 'type': field_type, + 'display_format': display_formats[gb_function or 'month'] if temporal else None, + 'interval': time_intervals[gb_function or 'month'] if temporal else None, + 'tz_convert': tz_convert, + 'qualified_field': qualified_field + } + + annotated_groupbys = map(process_groupby, groupby[:1] if lazy else groupby) + groupby_fields = [g['field'] for g in annotated_groupbys] + order = orderby or ','.join(groupby_fields) + groupby_dict = {gb['field']: gb for gb in annotated_groupbys} - # Step 1: security stuff - # add relevant ir_rules to the where clause, perform some basic sanity checks self._apply_ir_rules(cr, uid, query, 'read', context=context) - if first_groupby: - assert first_groupby in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)" - groupby_def = self._columns.get(first_groupby) or (self._inherit_fields.get(first_groupby) and self._inherit_fields.get(first_groupby)[2]) + for gb in groupby_fields: + assert gb in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)" + groupby_def = self._columns.get(gb) or (self._inherit_fields.get(gb) and self._inherit_fields.get(gb)[2]) assert groupby_def and groupby_def._classic_write, "Fields in 'groupby' must be regular database-persisted fields (no function or related fields), or function fields with store=True" - if not (first_groupby in fget): + if not (gb in fget): # Don't allow arbitrary values, as this would be a SQL injection vector! raise except_orm(_('Invalid group_by'), - _('Invalid group_by specification: "%s".\nA group_by specification must be a list of valid fields.')%(first_groupby,)) + _('Invalid group_by specification: "%s".\nA group_by specification must be a list of valid fields.')%(gb,)) - # Step 2: preparing the query: - # compute aggregated fields, format groupbys, adjust timezone, ... aggregated_fields = [ f for f in fields - if f not in ('id', 'sequence', groupby) + if f not in ('id', 'sequence') + if f not in groupby_fields if fget[f]['type'] in ('integer', 'float') if (f in self._all_columns and getattr(self._all_columns[f].column, '_classic_write'))] field_formatter = lambda f: (fget[f].get('group_operator', 'sum'), self._inherits_join_calc(f, query), f) select_terms = ["%s(%s) AS %s" % field_formatter(f) for f in aggregated_fields] - qualified_groupby_field = self._inherits_join_calc(first_groupby, query) if first_groupby else None - - if groupby_type in ('date', 'datetime'): - if tz_convert: - # Convert groupby result to user TZ to avoid confusion! - # PostgreSQL is compatible with all pytz timezone names, so we can use them - # directly for conversion, starting with timestamps stored in UTC. - timezone = context.get('tz', 'UTC') - qualified_groupby_field = "timezone('%s', timezone('UTC',%s))" % (timezone, qualified_groupby_field) - qualified_groupby_field = "date_trunc('%s', %s)" % (interval, qualified_groupby_field) - - if groupby_type == 'boolean': - qualified_groupby_field = "coalesce(%s,false)" % qualified_groupby_field - - if first_groupby: - select_terms.append("%s as %s " % (qualified_groupby_field, first_groupby)) - - order = orderby or first_groupby or '' - groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, first_groupby, qualified_groupby_field, query, groupby_type) + for gb in annotated_groupbys: + select_terms.append("%s as %s " % (gb['qualified_field'], gb['field'])) + groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query, fget) from_clause, where_clause, where_clause_params = query.get_sql() + count_field = groupby_fields[0] if (len(groupby_fields) == 1 and context.get('group_by_no_leaf')) else '_' prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else '' prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else '' query = """ - SELECT min(%(table)s.id) AS id, count(%(table)s.id) AS %(count_field)s_count - %(extra_fields)s + SELECT min(%(table)s.id) AS id, count(%(table)s.id) AS %(count_field)s_count %(extra_fields)s FROM %(from)s %(where)s %(groupby)s @@ -2341,7 +2344,7 @@ class BaseModel(object): %(offset)s """ % { 'table': self._table, - 'count_field': '_' if (len(groupby) < 2 and context.get('group_by_no_leaf')) else first_groupby, + 'count_field': count_field, 'extra_fields': prefix_terms(',', select_terms), 'from': from_clause, 'where': prefix_term('WHERE', where_clause), @@ -2352,53 +2355,71 @@ class BaseModel(object): } cr.execute(query, where_clause_params) - if not first_groupby: + if not groupby_fields: return {r.pop('id'): r for r in cr.dictfetchall() } - none_to_false = lambda record: {k: (False if v is None else v) for k,v in record.iteritems() } - fetched_data = map(none_to_false, cr.dictfetchall()) + def prepare_data(key, value): + value = False if value is None else value + gb = groupby_dict.get(key) + if gb and gb['type'] in ('date', 'datetime') and value: + if isinstance(value, basestring): + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + value = datetime.datetime.strptime(value, dt_format) + if gb['tz_convert']: + value = pytz.timezone(context['tz']).localize(value) + return value - data_ids = [r['id'] for r in fetched_data] - data_dict = {d['id']: d[first_groupby] for d in self.read(cr, uid, data_ids, [first_groupby], context=context)} - sorted_data = [{first_groupby: data_dict[id]} for id in data_ids] + fetched_data = cr.dictfetchall() - def format_result (fromquery, fromread): - result = { - '__domain': [(first_groupby, '=', fromquery[first_groupby] or False)] + domain, - '__context': {'group_by': groupby[1:]} - } - result.update(fromquery) - result.update(fromread) + many2onefields = [gb['field'] for gb in annotated_groupbys if gb['type'] == 'many2one'] + if many2onefields: + data_ids = [r['id'] for r in fetched_data] + data_dict = {d['id']: d for d in self.read(cr, uid, data_ids, many2onefields, context=context)} + for d in fetched_data: + d.update(data_dict[d['id']]) - if groupby_type in ('date', 'datetime') and fromquery[first_groupby]: - groupby_datetime = fromquery[first_groupby] - if isinstance(groupby_datetime, basestring): - groupby_datetime = datetime.datetime.strptime(groupby_datetime, dt_format) - if tz_convert: - groupby_datetime = pytz.timezone(context['tz']).localize(groupby_datetime) - result[first_groupby] = babel.dates.format_date( - groupby_datetime, format=time_display_format, locale=context.get('lang', 'en_US')) - domain_dt_begin = groupby_datetime - domain_dt_end = groupby_datetime + time_interval - if tz_convert: - # the time boundaries were all computed in the apparent TZ of the user, - # so we need to convert them to UTC to have proper server-side values. + data = map(lambda r: {k: prepare_data(k,v) for k,v in r.iteritems()}, fetched_data) + + def get_domain(gb, value): + if gb['type'] in ('date', 'datetime') and value: + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + domain_dt_begin = value + domain_dt_end = value + gb['interval'] + if gb['tz_convert']: domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) domain_dt_end = domain_dt_end.astimezone(pytz.utc) - result['__domain'] = [(first_groupby, '>=', domain_dt_begin.strftime(dt_format)), - (first_groupby, '<', domain_dt_end.strftime(dt_format))] + domain + return [(gb['field'], '>=', domain_dt_begin.strftime(dt_format)), + (gb['field'], '<', domain_dt_end.strftime(dt_format))] + if gb['type'] == 'many2one' and value: + value = value[0] + return [(gb['field'], '=', value)] + + def format_result (fromquery): + domain_group = [dom for gb in annotated_groupbys for dom in get_domain(gb, fromquery[gb['field']])] + result = { + '__domain': domain_group + domain, + '__context': {'group_by': groupby[len(annotated_groupbys):]} + } + result.update(fromquery) + for k,v in result.iteritems(): + gb = groupby_dict.get(k) + if gb and gb['type'] in ('date', 'datetime') and v: + result[k] = babel.dates.format_date(v, format=gb['display_format'], locale=context.get('lang', 'en_US')) del result['id'] return result - result = map(format_result, fetched_data, sorted_data) + for gb in groupby_fields: + if gb in self._group_by_full: + print "DING" + result = map(format_result, data) - if first_groupby in self._group_by_full: - result = self._read_group_fill_results(cr, uid, domain, first_groupby, groupby, - aggregated_fields, result, read_group_order=order, - context=context) + # TO DO!!!!!!!!!!!! + # if first_groupby in self._group_by_full: + # result = self._read_group_fill_results(cr, uid, domain, first_groupby, groupby, + # aggregated_fields, result, read_group_order=order, + # context=context) return result - def _inherits_join_add(self, current_model, parent_model_name, query): """ Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates) From 062ee7485c2a3f98a2bb44901096b42472e67df0 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 25 Mar 2014 18:21:47 +0100 Subject: [PATCH 012/140] [FIX] IE9 - Catch error when we try to load a new stylesheet but that we have already reached the max number of sheet in IE9 : 31 bzr revid: jke@openerp.com-20140325172147-6ymq1ixebawj4ce2 --- .../static/lib/jquery.sparkline/jquery.sparkline.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/web_kanban_sparkline/static/lib/jquery.sparkline/jquery.sparkline.js b/addons/web_kanban_sparkline/static/lib/jquery.sparkline/jquery.sparkline.js index 43b24c080a6..56498763549 100644 --- a/addons/web_kanban_sparkline/static/lib/jquery.sparkline/jquery.sparkline.js +++ b/addons/web_kanban_sparkline/static/lib/jquery.sparkline/jquery.sparkline.js @@ -582,7 +582,11 @@ var tag; //if ('\v' == 'v') /* ie only */ { if (document.createStyleSheet) { - document.createStyleSheet().cssText = css; + try { + document.createStyleSheet().cssText = css; + } catch(err) { + console.log('Failed - IE9 limit 31 sheets CSS'); + } } else { tag = document.createElement('style'); tag.type = 'text/css'; From b2ea875f4ca3f4a9f3032057e19c58f080fa1073 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 25 Mar 2014 18:32:05 +0100 Subject: [PATCH 013/140] [FIX] IE9 - Move the placeholder in base_import from view to js, to use the mechanism of select2 and not the jquery.placeholder. Else, jq.placeholder override the select2 value, because the style option is in reality an input in dom. bzr revid: jke@openerp.com-20140325173205-n2q0dw1kynlkint7 --- addons/base_import/static/src/js/import.js | 2 +- addons/base_import/static/src/xml/import.xml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/addons/base_import/static/src/js/import.js b/addons/base_import/static/src/js/import.js index 1238bc9570f..78cb09001a9 100644 --- a/addons/base_import/static/src/js/import.js +++ b/addons/base_import/static/src/js/import.js @@ -285,7 +285,7 @@ openerp.base_import = function (instance) { callback(item_finder(default_value)); }, - + placeholder: _t('Don\'t import'), width: 'resolve', dropdownCssClass: 'oe_import_selector' }); diff --git a/addons/base_import/static/src/xml/import.xml b/addons/base_import/static/src/xml/import.xml index 97bf3e66f7a..8d7155912e6 100644 --- a/addons/base_import/static/src/xml/import.xml +++ b/addons/base_import/static/src/xml/import.xml @@ -347,8 +347,7 @@ - + From ebb14f776a54c3494d9205e091422f98321ad1e0 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 26 Mar 2014 16:47:38 +0100 Subject: [PATCH 014/140] [FIX] crm_partner_assign: custom next client is not anymore usefull, cases where the record was no more readable after write (due to security changes) are now handled by the web client bzr revid: dle@openerp.com-20140326154738-jocgzfjpiucdfxki --- .../crm_partner_assign/static/src/js/next.js | 19 ------------------- .../wizard/crm_channel_interested.py | 5 +---- 2 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 addons/crm_partner_assign/static/src/js/next.js diff --git a/addons/crm_partner_assign/static/src/js/next.js b/addons/crm_partner_assign/static/src/js/next.js deleted file mode 100644 index b3a4fff2732..00000000000 --- a/addons/crm_partner_assign/static/src/js/next.js +++ /dev/null @@ -1,19 +0,0 @@ -openerp.crm_partner_assign = function (instance) { - instance.crm_partner_assign = instance.crm_partner_assign || {}; - instance.crm_partner_assign.next_or_list = function(parent) { - var view = parent.inner_widget.active_view; - var controller = parent.inner_widget.views[view].controller; - if (view === "form"){ - if (controller.dataset.size()) { - controller.execute_pager_action('next'); - } else { - controller.do_action('history_back'); - } - } - controller.do_action({ type: 'ir.actions.act_window_close' }); - if (view === "list"){ - controller.records.remove(controller.records.get(parent.dialog_widget.action.context.active_id)); - } - }; - instance.web.client_actions.add("next_or_list", "instance.crm_partner_assign.next_or_list"); -} \ No newline at end of file diff --git a/addons/crm_partner_assign/wizard/crm_channel_interested.py b/addons/crm_partner_assign/wizard/crm_channel_interested.py index a407ca7b910..87fd5669008 100644 --- a/addons/crm_partner_assign/wizard/crm_channel_interested.py +++ b/addons/crm_partner_assign/wizard/crm_channel_interested.py @@ -70,8 +70,5 @@ class crm_lead_forward_to_partner(osv.TransientModel): for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context): lead_obj.convert_opportunity(cr, SUPERUSER_ID, [lead.id], lead.partner_id and lead.partner_id.id or None, context=None) return { - 'type': 'ir.actions.client', - 'tag': 'next_or_list', - 'params': { - }, + 'type': 'ir.actions.act_window_close', } From e80a179d021d88419555c7d371a2850ea37b92fa Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 26 Mar 2014 18:08:18 +0100 Subject: [PATCH 015/140] [FIX] search widgets: m2o autocompletion had been disabled when @operator or @filter_domain were set, but it was actually useful Was disabled at rev 3878 revid:xmo@openerp.com-20131107111231-nkrllqv0afqdmix6 bzr revid: odo@openerp.com-20140326170818-sc5hqnmq89ayufso --- addons/web/static/src/js/search.js | 3 --- addons/web/static/test/search.js | 38 +++++++++++++++++------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 7c04ad40149..04bb1a61d99 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -1560,9 +1560,6 @@ instance.web.search.ManyToOneField = instance.web.search.CharField.extend({ this.model = new instance.web.Model(this.attrs.relation); }, complete: function (needle) { - if (this.attrs.operator || this.attrs.filter_domain) { - return this._super(needle); - } var self = this; // FIXME: "concurrent" searches (multiple requests, mis-ordered responses) var context = instance.web.pyeval.eval( diff --git a/addons/web/static/test/search.js b/addons/web/static/test/search.js index 9874795e1c9..96bbb660103 100644 --- a/addons/web/static/test/search.js +++ b/addons/web/static/test/search.js @@ -620,29 +620,33 @@ openerp.testing.section('search.completions', { {relation: 'dummy.model'}, view); return f.complete("bob"); }); - test("M2O custom operator", {asserts: 6}, function (instance) { - var view = { inputs: [], }; + test("M2O custom operator", {asserts: 10}, function (instance, $s, mock) { + mock('dummy.model:name_search', function (args, kwargs) { + deepEqual(args, [], "should have no positional arguments"); + // the operator is meant for the final search term generation, not the autocompletion + equal(kwargs.operator, undefined, "operator should not be used for autocompletion") + strictEqual(kwargs.name, 'bob'); + return [[42, "Match"]]; + }); + var view = {inputs: [], dataset: {get_context: function () {}}}; var f = new instance.web.search.ManyToOneField( - {attrs: {string: 'Dummy', operator:'ilike'}}, + {attrs: {string: 'Dummy', operator: 'ilike'}}, {relation: 'dummy.model'}, view); return f.complete('bob') - .done(function (completions) { - equal(completions.length, 1, "should provide a single completion"); - var c = completions[0]; - equal(c.label, "Search Dummy for: bob", - "should propose fuzzy searching of the value"); - ok(c.facet, "should have a facet"); + .done(function (c) { + equal(c.length, 2, "should return result + title"); + var title = c[0]; + equal(title.label, f.attrs.string, "title should match field name"); + ok(!title.facet, "title should not have a facet"); - var facet = new instance.web.search.Facet(c.facet); - equal(facet.get('category'), f.attrs.string, - "completion facet should bear the field's name"); - strictEqual(facet.get('field'), f, - "completion facet should yield the field"); - deepEqual(facet.values.toJSON(), [{label: 'bob', value: 'bob'}], - "facet should have a single value using the completion item"); + var f1 = new instance.web.search.Facet(c[1].facet); + equal(c[1].label, "Match"); + equal(f1.get('category'), f.attrs.string); + equal(f1.get('field'), f); + deepEqual(f1.values.toJSON(), [{label: 'Match', value: 42}]); }); -}); + }); test('Integer: invalid', {asserts: 1}, function (instance) { var view = {inputs: []}; var f = new instance.web.search.IntegerField( From f652402dd786eff52f7a34a0ca2bf48c3b9c8331 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 27 Mar 2014 12:24:56 +0100 Subject: [PATCH 016/140] [FIX] web: read_ids of data.js use method search_read if check_access_rule option is true. This fix is related to revision 3985 revid:dle@openerp.com-20140326142040-pls0dk2kd03z55ro, which did not worked for buffered dataset (virtual one2many line in view form search_read is used instead of read to not return records for which we lose the access rights bzr revid: dle@openerp.com-20140327112456-iyceuf9dnn07hwke --- addons/web/static/src/js/data.js | 14 +++++++++++--- addons/web/static/src/js/view_form.js | 18 +++++++----------- addons/web/static/src/js/view_list.js | 10 +++++----- addons/web/static/test/list-editable.js | 4 ++-- addons/web/static/test/list.js | 3 ++- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 517afa7f5c2..b31de507be4 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -457,9 +457,17 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, return $.Deferred().resolve([]); options = options || {}; - return this._model.call('read', - [ids, fields || false], - {context: this.get_context(options.context)}) + var method = 'read'; + var ids_arg = ids; + var context = this.get_context(options.context); + if (options.check_access_rule === true){ + method = 'search_read'; + ids_arg = [['id', 'in', ids]]; + context.active_test = false; + } + return this._model.call(method, + [ids_arg, fields || false], + {context: context}) .then(function (records) { if (records.length <= 1) { return records; } var indexes = {}; diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 8b68e3ec730..fd838686ba9 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -962,21 +962,17 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM } else { var fields = _.keys(self.fields_view.fields); fields.push('display_name'); - // Use of search_read instead of read to check if we can still read the record (security rules) - return self.dataset.call('search_read', [[['id', '=', self.dataset.ids[self.dataset.index]]], fields], + return self.dataset.read_index(fields, { context: { 'bin_size': true, - 'future_display_name': true, - 'active_test': false - } + 'future_display_name': true + }, + check_access_rule: true }).then(function(r) { - if (_.isEmpty(r)){ - self.do_action('history_back'); - } - else{ - self.trigger('load_record', r[0]); - } + self.trigger('load_record', r); + }).fail(function (){ + self.do_action('history_back'); }); } }); diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 7b12300ec78..cdb9ff8302f 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -533,14 +533,14 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi }, reload_record: function (record) { var self = this; - // Use of search_read instead of read to check if we can still read the record (security rules) - return this.dataset.call('search_read', [ - [['id', '=', record.get('id')]], + return this.dataset.read_ids( + [record.get('id')], _.pluck(_(this.columns).filter(function (r) { return r.tag === 'field'; - }), 'name')] + }), 'name'), + {check_access_rule: true} ).done(function (records) { - var values = _.isEmpty(records) ? undefined : records[0]; + var values = records[0]; if (!values) { self.records.remove(record); return; diff --git a/addons/web/static/test/list-editable.js b/addons/web/static/test/list-editable.js index c6985875b6f..e73249549b8 100644 --- a/addons/web/static/test/list-editable.js +++ b/addons/web/static/test/list-editable.js @@ -329,9 +329,9 @@ openerp.testing.section('list.edition.onwrite', { throw new Error(JSON.stringify(_.toArray(arguments))); }); mock('demo:search_read', function (args, kwargs) { - if (_.isEqual(args[0], [['id', '=', 1]])) { + if (_.isEqual(args[0], [['id', 'in', [1]]])) { return [{id: 1, a: 'some value'}]; - } else if (_.isEqual(args[0], [['id', '=', 42]])) { + } else if (_.isEqual(args[0], [['id', 'in', [42]]])) { return [ {id: 42, a: 'foo'} ]; } throw new Error(JSON.stringify(_.toArray(arguments))); diff --git a/addons/web/static/test/list.js b/addons/web/static/test/list.js index 33f6534bf9a..2ea8790a694 100644 --- a/addons/web/static/test/list.js +++ b/addons/web/static/test/list.js @@ -22,7 +22,8 @@ openerp.testing.section('list.buttons', { throw new Error(JSON.stringify(_.toArray(arguments))); }); mock('demo:search_read', function (args, kwargs) { - if (_.isEqual(args[0], [['id', '=', 2]])) { + console.log(args); + if (_.isEqual(args[0], [['id', 'in', [2]]])) { return []; } throw new Error(JSON.stringify(_.toArray(arguments))); From c771903c3baf11aef0b6d0b6b0bdf9fa870125d3 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 27 Mar 2014 19:25:20 +0100 Subject: [PATCH 017/140] [IMP] account* reports: removed rml, added qweb template, changed the wizard to return qweb actions bzr revid: sle@openerp.com-20140327182520-uu7ezsqic30x7mqo --- addons/account/__openerp__.py | 21 +- addons/account/account_invoice.py | 12 +- addons/account/account_report.xml | 187 ++++- addons/account/project/project_report.xml | 65 +- .../project/report/analytic_balance.rml | 234 ------ .../project/report/analytic_journal.rml | 346 --------- addons/account/project/report/cost_ledger.rml | 305 -------- .../report/inverted_analytic_balance.rml | 229 ------ .../project/report/quantity_cost_ledger.rml | 281 -------- .../project/views/report_analyticbalance.xml | 62 ++ .../views/report_analyticcostledger.xml | 90 +++ .../report_analyticcostledgerquantity.xml | 87 +++ .../project/views/report_analyticjournal.xml | 90 +++ .../views/report_invertedanalyticbalance.xml | 91 +++ .../wizard/account_analytic_balance_report.py | 20 +- ...analytic_cost_ledger_for_journal_report.py | 20 +- .../account_analytic_cost_ledger_report.py | 19 +- ...ccount_analytic_inverted_balance_report.py | 20 +- .../wizard/account_analytic_journal_report.py | 19 +- addons/account/report/__init__.py | 4 - .../report/account_aged_partner_balance.rml | 285 -------- addons/account/report/account_balance.rml | 313 --------- .../report/account_central_journal.rml | 338 --------- .../report/account_financial_report.rml | 303 -------- .../report/account_general_journal.rml | 387 ---------- .../account/report/account_general_ledger.rml | 619 ---------------- .../account_general_ledger_landscape.rml | 658 ----------------- addons/account/report/account_journal.rml | 311 -------- .../report/account_journal_sale_purchase.rml | 346 --------- .../report/account_partner_balance.rml | 257 ------- .../account/report/account_partner_ledger.rml | 658 ----------------- .../report/account_partner_ledger_other.rml | 665 ------------------ .../account/report/account_print_invoice.py | 37 - .../account/report/account_print_invoice.rml | 373 ---------- .../account/report/account_print_overdue.rml | 290 -------- .../views/report_agedpartnerbalance.xml | 133 ++++ .../account/views/report_centraljournal.xml | 93 +++ addons/account/views/report_financial.xml | 128 ++++ .../account/views/report_generaljournal.xml | 98 +++ addons/account/views/report_generalledger.xml | 133 ++++ addons/account/views/report_invoice.xml | 153 ++++ addons/account/views/report_journal.xml | 88 +++ addons/account/views/report_overdue.xml | 113 +++ .../account/views/report_partnerbalance.xml | 125 ++++ addons/account/views/report_partnerledger.xml | 131 ++++ .../views/report_partnerledgerother.xml | 131 ++++ .../views/report_salepurchasejournal.xml | 107 +++ addons/account/views/report_trialbalance.xml | 94 +++ .../wizard/account_financial_report.py | 12 +- .../wizard/account_report_account_balance.py | 3 +- .../account_report_aged_partner_balance.py | 8 +- .../wizard/account_report_central_journal.py | 9 +- .../wizard/account_report_general_journal.py | 5 +- .../wizard/account_report_general_ledger.py | 8 +- .../wizard/account_report_partner_balance.py | 9 +- .../wizard/account_report_partner_ledger.py | 19 +- .../wizard/account_report_print_journal.py | 10 +- addons/account/wizard/account_vat.py | 3 +- addons/account_analytic_plans/__openerp__.py | 4 +- .../account_analytic_plans_report.xml | 13 +- .../report/crossovered_analytic.rml | 304 -------- .../views/report_crossoveredanalyticplans.xml | 66 ++ .../wizard/account_crossovered_analytic.py | 7 +- .../__openerp__.py | 1 + .../account_bank_statement_report.xml | 23 +- .../report/bank_statement_balance_report.rml | 145 ---- .../views/report_bankstatementbalance.xml | 35 + addons/account_budget/__openerp__.py | 8 +- .../account_budget/account_budget_report.xml | 48 +- .../report/analytic_account_budget_report.rml | 226 ------ .../account_budget/report/budget_report.rml | 188 ----- .../report/crossovered_budget_report.rml | 203 ------ .../views/report_analyticaccountbudget.xml | 69 ++ addons/account_budget/views/report_budget.xml | 77 ++ .../views/report_crossoveredbudget.xml | 81 +++ .../wizard/account_budget_analytic.py | 21 +- .../account_budget_crossovered_report.py | 17 +- ...count_budget_crossovered_summary_report.py | 20 +- .../wizard/account_budget_report.py | 20 +- addons/account_check_writing/__openerp__.py | 4 +- .../account_check_writing_report.xml | 36 +- .../data/report_paperformat.xml | 20 + .../report/check_print_bottom.rml | 318 --------- .../report/check_print_middle.rml | 356 ---------- .../report/check_print_top.rml | 336 --------- .../views/report_check.xml | 48 ++ addons/account_followup/__openerp__.py | 3 +- addons/account_followup/account_followup.py | 17 +- .../account_followup_reports.xml | 14 + .../account_followup_view.xml | 1 - .../report/account_followup_print.rml | 238 ------- .../tests/test_account_followup.py | 4 +- .../views/report_followup.xml | 58 ++ addons/account_payment/__openerp__.py | 2 + .../account_payment_report.xml | 9 +- addons/account_payment/report/order.rml | 290 -------- .../views/report_paymentorder.xml | 104 +++ addons/account_test/__openerp__.py | 15 +- addons/account_test/account_test_report.xml | 21 +- addons/account_test/report/account_test.rml | 78 -- .../account_test/views/report_accounttest.xml | 23 + addons/account_voucher/__openerp__.py | 4 +- .../report/account_voucher.rml | 446 ------------ .../report/account_voucher_print.rml | 331 --------- addons/report/controllers/main.py | 9 +- addons/report/models/report.py | 26 +- addons/report/models/report_paperformat.py | 4 +- addons/report/views/layouts.xml | 6 +- addons/report_intrastat/__init__.py | 2 - addons/report_intrastat/__openerp__.py | 5 +- addons/report_intrastat/intrastat_report.xml | 20 +- addons/report_intrastat/report/__init__.py | 22 - addons/report_intrastat/report/invoice.py | 35 - addons/report_intrastat/report/invoice.rml | 401 ----------- .../views/report_intrastatinvoice.xml | 149 ++++ 115 files changed, 3172 insertions(+), 11514 deletions(-) delete mode 100644 addons/account/project/report/analytic_balance.rml delete mode 100644 addons/account/project/report/analytic_journal.rml delete mode 100644 addons/account/project/report/cost_ledger.rml delete mode 100644 addons/account/project/report/inverted_analytic_balance.rml delete mode 100644 addons/account/project/report/quantity_cost_ledger.rml create mode 100644 addons/account/project/views/report_analyticbalance.xml create mode 100644 addons/account/project/views/report_analyticcostledger.xml create mode 100644 addons/account/project/views/report_analyticcostledgerquantity.xml create mode 100644 addons/account/project/views/report_analyticjournal.xml create mode 100644 addons/account/project/views/report_invertedanalyticbalance.xml delete mode 100644 addons/account/report/account_aged_partner_balance.rml delete mode 100644 addons/account/report/account_balance.rml delete mode 100644 addons/account/report/account_central_journal.rml delete mode 100644 addons/account/report/account_financial_report.rml delete mode 100644 addons/account/report/account_general_journal.rml delete mode 100644 addons/account/report/account_general_ledger.rml delete mode 100644 addons/account/report/account_general_ledger_landscape.rml delete mode 100644 addons/account/report/account_journal.rml delete mode 100644 addons/account/report/account_journal_sale_purchase.rml delete mode 100644 addons/account/report/account_partner_balance.rml delete mode 100644 addons/account/report/account_partner_ledger.rml delete mode 100644 addons/account/report/account_partner_ledger_other.rml delete mode 100644 addons/account/report/account_print_invoice.py delete mode 100644 addons/account/report/account_print_invoice.rml delete mode 100644 addons/account/report/account_print_overdue.rml create mode 100644 addons/account/views/report_agedpartnerbalance.xml create mode 100644 addons/account/views/report_centraljournal.xml create mode 100644 addons/account/views/report_financial.xml create mode 100644 addons/account/views/report_generaljournal.xml create mode 100644 addons/account/views/report_generalledger.xml create mode 100644 addons/account/views/report_invoice.xml create mode 100644 addons/account/views/report_journal.xml create mode 100644 addons/account/views/report_overdue.xml create mode 100644 addons/account/views/report_partnerbalance.xml create mode 100644 addons/account/views/report_partnerledger.xml create mode 100644 addons/account/views/report_partnerledgerother.xml create mode 100644 addons/account/views/report_salepurchasejournal.xml create mode 100644 addons/account/views/report_trialbalance.xml delete mode 100644 addons/account_analytic_plans/report/crossovered_analytic.rml create mode 100644 addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml delete mode 100644 addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml create mode 100644 addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml delete mode 100644 addons/account_budget/report/analytic_account_budget_report.rml delete mode 100644 addons/account_budget/report/budget_report.rml delete mode 100644 addons/account_budget/report/crossovered_budget_report.rml create mode 100644 addons/account_budget/views/report_analyticaccountbudget.xml create mode 100644 addons/account_budget/views/report_budget.xml create mode 100644 addons/account_budget/views/report_crossoveredbudget.xml create mode 100644 addons/account_check_writing/data/report_paperformat.xml delete mode 100644 addons/account_check_writing/report/check_print_bottom.rml delete mode 100644 addons/account_check_writing/report/check_print_middle.rml delete mode 100644 addons/account_check_writing/report/check_print_top.rml create mode 100644 addons/account_check_writing/views/report_check.xml create mode 100644 addons/account_followup/account_followup_reports.xml delete mode 100644 addons/account_followup/report/account_followup_print.rml create mode 100644 addons/account_followup/views/report_followup.xml delete mode 100644 addons/account_payment/report/order.rml create mode 100644 addons/account_payment/views/report_paymentorder.xml delete mode 100644 addons/account_test/report/account_test.rml create mode 100644 addons/account_test/views/report_accounttest.xml delete mode 100644 addons/account_voucher/report/account_voucher.rml delete mode 100644 addons/account_voucher/report/account_voucher_print.rml delete mode 100644 addons/report_intrastat/report/__init__.py delete mode 100644 addons/report_intrastat/report/invoice.py delete mode 100644 addons/report_intrastat/report/invoice.rml create mode 100644 addons/report_intrastat/views/report_intrastatinvoice.xml diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 95ecdc8c35a..83434893ac7 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -126,6 +126,24 @@ for a particular financial year and for preparation of vouchers there is a modul 'account_pre_install.yml', 'views/report_vat.xml', + 'views/report_invoice.xml', + 'views/report_trialbalance.xml', + 'views/report_centraljournal.xml', + 'views/report_overdue.xml', + 'views/report_generaljournal.xml', + 'views/report_journal.xml', + 'views/report_salepurchasejournal.xml', + 'views/report_partnerbalance.xml', + 'views/report_agedpartnerbalance.xml', + 'views/report_partnerledger.xml', + 'views/report_partnerledgerother.xml', + 'views/report_financial.xml', + 'views/report_generalledger.xml', + 'project/views/report_analyticbalance.xml', + 'project/views/report_analyticjournal.xml', + 'project/views/report_analyticcostledgerquantity.xml', + 'project/views/report_analyticcostledger.xml', + 'project/views/report_invertedanalyticbalance.xml', ], 'js': [ 'static/src/js/account_move_reconciliation.js', @@ -157,8 +175,6 @@ for a particular financial year and for preparation of vouchers there is a modul 'test/account_period_close.yml', 'test/account_use_model.yml', 'test/account_validate_account_move.yml', - #'test/account_bank_statement.yml', - #'test/account_cash_statement.yml', 'test/test_edi_invoice.yml', 'test/account_report.yml', 'test/account_fiscalyear_close.yml', #last test, as it will definitively close the demo fiscalyear @@ -166,4 +182,5 @@ for a particular financial year and for preparation of vouchers there is a modul 'installable': True, 'auto_install': False, } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index 06e59232ac9..5f7c2b66400 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -409,17 +409,7 @@ class account_invoice(osv.osv): ''' assert len(ids) == 1, 'This option should only be used for a single id at a time.' self.write(cr, uid, ids, {'sent': True}, context=context) - datas = { - 'ids': ids, - 'model': 'account.invoice', - 'form': self.read(cr, uid, ids[0], context=context) - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.invoice', - 'datas': datas, - 'nodestroy' : True - } + return self.pool['report'].get_action(cr, uid, ids, 'account.report_invoice', context=context) def action_invoice_sent(self, cr, uid, ids, context=None): ''' diff --git a/addons/account/account_report.xml b/addons/account/account_report.xml index 4f9ad1b5c56..90d2c1637fb 100644 --- a/addons/account/account_report.xml +++ b/addons/account/account_report.xml @@ -1,45 +1,168 @@ - - - - - - - - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + parent="account.menu_finance_generic_reporting" + sequence="3" + /> diff --git a/addons/account/project/project_report.xml b/addons/account/project/project_report.xml index 3ee449e01b5..de2e2feee5a 100644 --- a/addons/account/project/project_report.xml +++ b/addons/account/project/project_report.xml @@ -1,29 +1,54 @@ - + - + - + - - - + + diff --git a/addons/account/project/report/analytic_balance.rml b/addons/account/project/report/analytic_balance.rml deleted file mode 100644 index 1754988f7d6..00000000000 --- a/addons/account/project/report/analytic_balance.rml +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - Account Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - - - Analytic Balance - [[ company.currency_id.name ]] - - - - - - - - - - Code - - - Account Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - Total - - - - - - - - [[ formatLang(sum_all(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2'],'debit')) ]] - - - [[ formatLang(sum_all(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2'],'credit')) ]] - - - [[ formatLang(sum_balance(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id)]] - - - [[ formatLang(sum_all(get_objects(data['form']['empty_acc']),data['form']['date1'],data['form']['date2'],'quantity')) ]] - - - -
    - [[ repeatIn(get_objects(data['form']['empty_acc']),'o') ]] - - - - [[ o['code'] ]] - - - [[ o['complete_name'] ]] - - - [[ formatLang(move_sum(o['id'],data['form']['date1'],data['form']['date2'],'debit')) ]] - - - [[ formatLang(move_sum(o['id'],data['form']['date1'],data['form']['date2'],'credit')) ]] - - - [[ formatLang(move_sum_balance(o['id'],data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id)]] - - - [[ formatLang(move_sum(o['id'],data['form']['date1'],data['form']['date2'],'quantity')) ]] - - - -
    - [[ repeatIn(lines_g(o['id'],data['form']['date1'],data['form']['date2']),'move_g') ]] - - - - [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang(move_g['debit'])]] - - - [[ formatLang(move_g['credit']) ]] - - - [[ formatLang(move_g['balance'], currency_obj = company.currency_id) ]] - - - [[ formatLang(move_g['quantity']) ]] - - - - - - -
    -
    - - - - - - -
    -
    -
    \ No newline at end of file diff --git a/addons/account/project/report/analytic_journal.rml b/addons/account/project/report/analytic_journal.rml deleted file mode 100644 index 719851252b5..00000000000 --- a/addons/account/project/report/analytic_journal.rml +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - - - - Analytic Journal - - - - - - - Period from - - - Period to - - - Currency - - - - - - - [[ formatLang(data['form']['date1'],date=True) ]] - - - [[ formatLang(data['form']['date2'],date=True) ]] - - - [[ company.currency_id.name ]] - - - - - - - - - - Date - - - Code - - - Move Name - - - Account n° - - - General - - - Analytic - - - - - - - - - - [[ o.code ]] - [[ o.name ]] - - - - - - - - - - - - - - - - - - [[ formatLang(sum_general(o.id,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang(sum_analytic(o.id,data['form']['date1'],data['form']['date2'])) ]] - - - - - - -
    - [[ repeatIn(lines(o.id,data['form']['date1'],data['form']['date2']), 'move') ]] - - - - - - - - - - - - - - [[ move.name ]] KI - - - [[ move.account_id.code ]] [[ move.account_id.name ]] - - - [[ formatLang(move.debit-move.credit) ]] - - - - - - - - - - - -
    - [[ repeatIn(lines_a(move.id,o.id,data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ (not move_a) and removeParentNode('blockTable') ]] [[ formatLang(move_a.date,date = True) ]] - - - [[ move_a.code ]] - - - [[ move_a.name ]] - - - [[ move_a.account_id.code ]] - [[ move_a.account_id.name ]] - - - - - - - - [[ formatLang( move_a.amount) ]] - - - - - - -
    - - - - - - -
    - - - -
    - [[ repeatIn(lines_a(False,o.id,data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ (not move_a) and removeParentNode('blockTable') ]] [[ formatLang(move_a.date,date = True) ]] - - - [[ move_a.code ]] - - - [[ move_a.name ]] - - - [[ move_a.account_id.code ]] - [[ move_a.account_id.name ]] - - - - - - - - [[ formatLang( move_a.amount) ]] - - - - - - -
    - - - -
    -
    diff --git a/addons/account/project/report/cost_ledger.rml b/addons/account/project/report/cost_ledger.rml deleted file mode 100644 index 1099a8b8b4e..00000000000 --- a/addons/account/project/report/cost_ledger.rml +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date/Code - - - J.C. /Move name - - - Debit - - - Credit - - - Balance - - - - - - - - - - - - - Cost Ledger - - - - - - - - - - - - Period from - - - Period to - - - Printing date - - - - - - - [[ formatLang(data['form']['date1'],date = True) ]] - - - [[ formatLang(data['form']['date2'],date = True) ]] - - - [[ formatLang(time.strftime('%Y-%m-%d %H:%M:%S'),date_time = True) ]] - - - - - - - - - - Date/Code - - - J.C. /Move name - - - Debit - - - Credit - - - Balance - - - - - - - Total: - - - - - - - - [[ formatLang (sum_debit(objects,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (sum_credit(objects,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (sum_balance(objects,data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id) ]] - - - -
    - [[ repeatIn(objects,'account') ]] - - - - [[ account.code ]] - - - [[ account.complete_name ]] - - - [[ formatLang (account_sum_debit(account,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (account_sum_credit(account,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang (account_sum_balance(account,data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id) ]] - - - -
    - [[ repeatIn(lines_g(account,data['form']['date1'],data['form']['date2']),'move_g') ]] - - - - [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang( move_g['debit']) ]] - - - [[ formatLang( move_g['credit']) ]] - - - [[ formatLang( move_g['balance'], currency_obj = company.currency_id) ]] - - - -
    - [[ repeatIn(lines_a(move_g,account,data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ formatLang(move_a['date'],date = True) ]] - - - [[ move_a['cj'] ]] - - - [[ move_a['name'] ]] - - - [[ formatLang( move_a['debit'] )]] - - - [[ formatLang( move_a['credit']) ]] - - - [[ formatLang( move_a['balance'], currency_obj = company.currency_id)]] - - - - - - -
    -
    -
    -
    -
    -
    diff --git a/addons/account/project/report/inverted_analytic_balance.rml b/addons/account/project/report/inverted_analytic_balance.rml deleted file mode 100644 index 54b6878c407..00000000000 --- a/addons/account/project/report/inverted_analytic_balance.rml +++ /dev/null @@ -1,229 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code - - - Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - - Inverted Analytic Balance - [[ company.currency_id.name ]] - - - - - - - - - - Code - - - Name - - - Debit - - - Credit - - - Balance - - - Quantity - - - - - - - - - - Total - - - - - - - - [[ formatLang(sum_debit(objects,data['form']['date1'],data['form']['date2'])) ]] - - - [[ formatLang(sum_credit(objects,data['form']['date1'],data['form']['date2']))]] - - - [[ formatLang(sum_balance(objects,data['form']['date1'],data['form']['date2']), currency_obj = company.currency_id)]] - - - [[ formatLang(sum_quantity(objects,data['form']['date1'],data['form']['date2'])) ]] - - - -
    - [[ repeatIn(lines_g(objects,data['form']['date1'],data['form']['date2']),'move_g') ]] - - - - [[ (not move_g) and removeParentNode('blockTable') ]] [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang(move_g['debit'])]] - - - [[formatLang(move_g['credit'])]] - - - [[ formatLang(move_g['balance'], currency_obj = company.currency_id)]] - - - [[formatLang(move_g['quantity']) ]] - - - -
    - [[ repeatIn(lines_a(objects,move_g['id'],data['form']['date1'],data['form']['date2']),'move_a') ]] - - - - [[ (not move_a) and removeParentNode('blockTable') ]] [[ move_a['code'] ]] - - - [[ move_a['complete_name'] ]] - - - [[ formatLang(move_a['debit']) ]] - - - [[ formatLang(move_a['credit']) ]] - - - [[ formatLang(move_a['balance'], currency_obj = company.currency_id)]] - - - [[ formatLang(move_a['quantity']) ]] - - - - - - -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/addons/account/project/report/quantity_cost_ledger.rml b/addons/account/project/report/quantity_cost_ledger.rml deleted file mode 100644 index 9f99f50ccc2..00000000000 --- a/addons/account/project/report/quantity_cost_ledger.rml +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Code/Date - - - J.C./Move name - - - Quantity - - - Total - - - - - - - - - - - - - Cost Ledger - - - - - - - - - - - - Period from - - - Period to - - - Printing date - - - - - - - [[ formatLang(data['form']['date1'],date = True) ]] - - - [[ formatLang(data['form']['date2'],date = True) ]] - - - [[ formatLang(time.strftime('%Y-%m-%d %H:%M:%S'),date_time = True) ]] - - - - - - - - - - - - - Code/Date - - - J.C./Move name - - - Quantity - - - Total - - - - - - - Total: - - - - - - - - - - - - - [[ formatLang (sum_quantity(objects,data['form']['date1'],data['form']['date2'], data['form']['journal']) ) ]] - - - -
    - [[ repeatIn(objects,'o') ]] - - - - [[ o.code ]] - - - [[ o.complete_name ]] - - - Max Qty: [[ formatLang (o.quantity_max )]] - - - [[ formatLang (account_sum_quantity(o.id,data['form']['date1'],data['form']['date2'], data['form']['journal']) )]] - - - -
    - [[ repeatIn(lines_g(o.id,data['form']['date1'],data['form']['date2'],data['form']['journal']),'move_g') ]] - - - - [[ move_g['code'] ]] - - - [[ move_g['name'] ]] - - - [[ formatLang (move_g['quantity']) ]] - - - - - - - [[ repeatIn(lines_a(move_g['id'],o.id,data['form']['date1'],data['form']['date2'],data['form']['journal']),'move_a') ]] - [[ formatLang(move_a['date'],date = True) ]] - - - [[ move_a['cj'] ]] - - - [[ move_a['name'] ]] - - - [[ formatLang (move_a['quantity'] )]] - - - - - - -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/addons/account/project/views/report_analyticbalance.xml b/addons/account/project/views/report_analyticbalance.xml new file mode 100644 index 00000000000..96f692eda3d --- /dev/null +++ b/addons/account/project/views/report_analyticbalance.xml @@ -0,0 +1,62 @@ + + + + + + diff --git a/addons/account/project/views/report_analyticcostledger.xml b/addons/account/project/views/report_analyticcostledger.xml new file mode 100644 index 00000000000..fd99c637411 --- /dev/null +++ b/addons/account/project/views/report_analyticcostledger.xml @@ -0,0 +1,90 @@ + + + + + + \ No newline at end of file diff --git a/addons/account/project/views/report_analyticcostledgerquantity.xml b/addons/account/project/views/report_analyticcostledgerquantity.xml new file mode 100644 index 00000000000..1098a7627f3 --- /dev/null +++ b/addons/account/project/views/report_analyticcostledgerquantity.xml @@ -0,0 +1,87 @@ + + + + + + \ No newline at end of file diff --git a/addons/account/project/views/report_analyticjournal.xml b/addons/account/project/views/report_analyticjournal.xml new file mode 100644 index 00000000000..ce2f216e419 --- /dev/null +++ b/addons/account/project/views/report_analyticjournal.xml @@ -0,0 +1,90 @@ + + + + + + diff --git a/addons/account/project/views/report_invertedanalyticbalance.xml b/addons/account/project/views/report_invertedanalyticbalance.xml new file mode 100644 index 00000000000..7ed8f4f84f3 --- /dev/null +++ b/addons/account/project/views/report_invertedanalyticbalance.xml @@ -0,0 +1,91 @@ + + + + + + diff --git a/addons/account/project/wizard/account_analytic_balance_report.py b/addons/account/project/wizard/account_analytic_balance_report.py index 02b2eb6e95d..3a3c301cffc 100644 --- a/addons/account/project/wizard/account_analytic_balance_report.py +++ b/addons/account/project/wizard/account_analytic_balance_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_balance(osv.osv_memory): _name = 'account.analytic.balance' _description = 'Account Analytic Balance' @@ -42,16 +43,13 @@ class account_analytic_balance(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.balance', - 'datas': datas, - } + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data + } + datas['form']['active_ids'] = context.get('active_ids', False) + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticbalance', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py index 814cbb8cacc..b3c2d1bec12 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_cost_ledger_journal_report(osv.osv_memory): _name = 'account.analytic.cost.ledger.journal.report' _description = 'Account Analytic Cost Ledger For Journal Report' @@ -42,14 +43,13 @@ class account_analytic_cost_ledger_journal_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.quantity_cost_ledger', - 'datas': datas, - } + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data + } + + datas['form']['active_ids'] = context.get('active_ids', False) + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticcostledgerquantity', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_report.py index ffd56352382..5f00c3c9ac5 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_report.py @@ -20,9 +20,9 @@ ############################################################################## import time - from openerp.osv import osv, fields + class account_analytic_cost_ledger(osv.osv_memory): _name = 'account.analytic.cost.ledger' _description = 'Account Analytic Cost Ledger' @@ -42,14 +42,13 @@ class account_analytic_cost_ledger(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.cost_ledger', - 'datas': datas, - } + 'ids': context.get('active_ids',[]), + 'model': 'account.analytic.account', + 'form': data + } + + datas['form']['active_ids'] = context.get('active_ids', False) + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticcostledger', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_inverted_balance_report.py b/addons/account/project/wizard/account_analytic_inverted_balance_report.py index 9e54f4f848d..3b03ad2da56 100644 --- a/addons/account/project/wizard/account_analytic_inverted_balance_report.py +++ b/addons/account/project/wizard/account_analytic_inverted_balance_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_inverted_balance(osv.osv_memory): _name = 'account.analytic.inverted.balance' _description = 'Account Analytic Inverted Balance' @@ -41,14 +42,13 @@ class account_analytic_inverted_balance(osv.osv_memory): context = {} data = self.read(cr, uid, ids)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.inverted.balance', - 'datas': datas, - } + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data + } + + datas['form']['active_ids'] = context.get('active_ids', False) + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_invertedanalyticbalance', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_journal_report.py b/addons/account/project/wizard/account_analytic_journal_report.py index 61fe2cd318a..ab7e553435d 100644 --- a/addons/account/project/wizard/account_analytic_journal_report.py +++ b/addons/account/project/wizard/account_analytic_journal_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_analytic_journal_report(osv.osv_memory): _name = 'account.analytic.journal.report' _description = 'Account Analytic Journal' @@ -49,16 +50,12 @@ class account_analytic_journal_report(osv.osv_memory): for analytic_record in record.analytic_account_journal_id: ids_list.append(analytic_record.id) datas = { - 'ids': ids_list, - 'model': 'account.analytic.journal', - 'form': data - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.journal', - 'datas': datas, - } - + 'ids': ids_list, + 'model': 'account.analytic.journal', + 'form': data + } + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticjournal', data=datas, context=context) + def default_get(self, cr, uid, fields, context=None): if context is None: context = {} diff --git a/addons/account/report/__init__.py b/addons/account/report/__init__.py index 544aa9e262e..ed8cc0aa8b3 100644 --- a/addons/account/report/__init__.py +++ b/addons/account/report/__init__.py @@ -26,12 +26,8 @@ import account_balance import account_partner_balance import account_general_ledger import account_partner_ledger -#import invoice -import account_print_invoice -#import overdue import account_print_overdue import account_aged_partner_balance -#import tax_report import report_vat import account_invoice_report import account_report diff --git a/addons/account/report/account_aged_partner_balance.rml b/addons/account/report/account_aged_partner_balance.rml deleted file mode 100644 index 5b5404e9c86..00000000000 --- a/addons/account/report/account_aged_partner_balance.rml +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Aged Trial Balance - - - - - - - Chart of Accounts - - - Fiscal Year - - - Start Date - - - Period Length(days) - - - Partner's - - - Analysis Direction - - - Target Moves - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[ formatLang(data['form']['date_from'],date=True) ]] - - - [[ data['form']['period_length'] ]] - - - Receivable Accounts[[ data['form']['result_selection'] == 'customer' or removeParentNode('para') ]] - Payable Accounts[[ data['form']['result_selection'] == 'supplier' or removeParentNode('para') ]] - Receivable and Payable Accounts[[ data['form']['result_selection'] == 'customer_supplier' or removeParentNode('para') ]] - - - [[ data['form']['direction_selection'] ]] - - - [[ get_target_move(data) ]] - - - - - - - - - - Partners - - - Due[[ data['form']['direction_selection'] == 'future' and ' ' or removeParentNode('para') ]] - Not due[[ data['form']['direction_selection'] != 'future' and ' ' or removeParentNode('para') ]] - - - [[ data['form']['4']['name'] ]] - - - [[ data['form']['3']['name'] ]] - - - [[ data['form']['2']['name'] ]] - - - [[ data['form']['1']['name'] ]] - - - [[ data['form']['0']['name'] ]] - - - Total - - - - - - - [[ (get_lines(data['form']), 'partner') == False or removeParentNode('para') ]] - [[ (get_lines_with_out_partner(data['form']), 'not_partner') == False or removeParentNode('para') ]] - Account Total - - - [[ formatLang(get_direction('6'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('4'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('3'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('2'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('1'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_for_period('0'), currency_obj=company.currency_id) ]] - - - [[ formatLang(get_total('5'), currency_obj=company.currency_id) ]] - - - - - - [[ repeatIn(get_lines(data['form']), 'partner') ]] - [[ partner['name'] ]] - - - [[ formatLang(partner['direction'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['4'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['3'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['2'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['1'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['0'], currency_obj=company.currency_id) ]] - - - [[ formatLang(partner['total'], currency_obj=company.currency_id) ]] - - - - - [[ repeatIn(get_lines_with_out_partner(data['form']), 'not_partner') ]] - [[ not_partner['name'] ]] - - - [[ formatLang(not_partner['direction'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['4'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['3'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['2'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['1'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['0'], currency_obj=company.currency_id) ]] - - - [[ formatLang(not_partner['total'], currency_obj=company.currency_id) ]] - - - - - - - - - - diff --git a/addons/account/report/account_balance.rml b/addons/account/report/account_balance.rml deleted file mode 100644 index 08c05c65fa8..00000000000 --- a/addons/account/report/account_balance.rml +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Trial Balance - - - - - - - - - - - - - Company[[ data['model']=='account.account' and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - - - Fiscal Year - - - Display Account - - - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - - - Target Moves - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - All[[ data['form']['display_account']=='all' and ' ' or removeParentNode('para') ]] - With movements[[ data['form']['display_account']=='movement' and ' ' or removeParentNode('para') ]] - With balance is not equal to 0[[ data['form']['display_account']=='not_zero' and ' ' or removeParentNode('para') ]] - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - [[ get_target_move(data) ]] - - - - - - - - - - - - Code - Account - Debit - Credit - Balance - - - [[ repeatIn(lines(data['form']), 'a') ]][[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['code'] or removeParentNode('tr') ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ '..'*(a['level']-1) ]][[ a['name'] ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['debit']) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[formatLang(a['debit']) ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font')]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['credit']) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['credit']) ]] - [[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['balance'], currency_obj=company.currency_id) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['balance'], currency_obj=company.currency_id) ]] - - - - - - - diff --git a/addons/account/report/account_central_journal.rml b/addons/account/report/account_central_journal.rml deleted file mode 100644 index 6d350b5fe8f..00000000000 --- a/addons/account/report/account_central_journal.rml +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects, 'o') ]] - - - - - Centralized Journal - - - - - - Chart of Accounts - Fiscal Year - Journal - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[o.journal_id.name ]] - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True) ]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - [[ get_target_move(data) ]] - - - - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - A/C No. - Account Name - Debit - Credit - Balance - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - A/C No. - Account Name - Debit - Credit - Balance - Currency - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - Total: - - [[ formatLang( sum_debit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)-sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id ) ]] - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - Total: - - [[ formatLang( sum_debit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)) ]] - [[ formatLang( sum_credit(o.period_id.id, o.journal_id.id)-sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id ) ]] - - - -
    - [[ repeatIn(lines(o.period_id.id,o.journal_id.id),'line') ]] - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - [[ line['code'] ]] - [[ line['name'] ]] - [[ formatLang(line['debit']) ]] - [[ formatLang(line['credit'])]] - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - [[ line['code'] ]] - [[ line['name'] ]] - [[ formatLang(line['debit']) ]] - [[ formatLang(line['credit'])]] - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - -
    - -
    -
    diff --git a/addons/account/report/account_financial_report.rml b/addons/account/report/account_financial_report.rml deleted file mode 100644 index 7949077e43f..00000000000 --- a/addons/account/report/account_financial_report.rml +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ data['form']['account_report_id'][1] ]] - - - - - - - - - - Chart of Accounts - Fiscal Year - Filter By [[ get_filter(data)!='No Filters' and get_filter(data) ]] - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[ get_filter(data)=='No Filters' and get_filter(data) or removeParentNode('para') ]] - [[ get_filter(data)=='Date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True) ]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ get_filter(data)=='Periods' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - [[ get_target_move(data) ]] - - - - - - - - - - - - - [[ data['form']['debit_credit'] == 1 or removeParentNode('blockTable') ]] - - - Name - - - Debit - - - Credit - - - Balance - - - - [[ repeatIn(get_lines(data), 'a') ]] - [[ (a.get('level') <> 0) or removeParentNode('tr') ]] - [[ setTag('tr','tr',{'style': 'Table'+str(min(3,'level' in a and a.get('level') or 1))}) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_name'}) ]][[ a.get('name') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('debit',0.0), currency_obj = company.currency_id) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('credit',0.0), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - - - - - - [[ (not data['form']['enable_filter'] and not data['form']['debit_credit']) or removeParentNode('blockTable') ]] - - - Name - - - Balance - - - - [[ repeatIn(get_lines(data), 'a') ]] - [[ (a.get('level') <> 0) or removeParentNode('tr') ]] - [[ setTag('tr','tr',{'style': 'Table'+str(min(3,'level' in a and a.get('level') or 1))}) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_name'}) ]][[ a.get('name') ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - - - - - - - - - [[ (data['form']['enable_filter'] == 1 and not data['form']['debit_credit']) or removeParentNode('blockTable') ]] - - - Name - - - Balance - - - [[ data['form']['label_filter'] ]] - - - - [[ repeatIn(get_lines(data), 'a') ]] - [[ (a.get('level') <> 0) or removeParentNode('tr') ]] - [[ setTag('tr','tr',{'style': 'Table'+str(min(3,'level' in a and a.get('level') or 1))}) ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_name'}) ]][[ a.get('name') ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') =='view' and a.get('level') <> 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance_cmp'), currency_obj = company.currency_id) ]] - [[ (a.get('account_type') <>'view' or a.get('level') == 1) or removeParentNode('td') ]] - [[ setTag('para','para',{'style': 'terp_level_'+str(min(6,a.get('level')))+'_balance'}) ]][[ formatLang(a.get('balance_cmp'), currency_obj = company.currency_id) ]] - - - - - - - diff --git a/addons/account/report/account_general_journal.rml b/addons/account/report/account_general_journal.rml deleted file mode 100644 index dce30e59918..00000000000 --- a/addons/account/report/account_general_journal.rml +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn( periods(objects), 'o') ]] - - - - - - - - - - General Journal - - - - - - - - - - - Company[[ data['model']=='account.journal.period' and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - Fiscal Year - Journals - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True)]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - [[ get_target_move(data) ]] - - - - - - - [[ display_currency(data)==False or removeParentNode('blockTable') ]] - - Code - Journal Name - Debit - Credit - Balance - - - Total: - - [[ formatLang(sum_debit()) ]] - [[ formatLang( sum_credit()) ]] - [[ formatLang( sum_debit()- sum_credit(), currency_obj=company.currency_id) ]] - - - [[ display_currency(data) or removeParentNode('blockTable') ]] - - Code - Journal Name - Debit - Credit - Balance - Currency - - - Total: - - [[ formatLang(sum_debit()) ]] - [[ formatLang( sum_credit()) ]] - [[ formatLang( sum_credit()- sum_debit(), currency_obj=company.currency_id) ]] - - - -
    - [[ display_currency(data) or removeParentNode('blockTable') ]] - - - [[ o.name ]] : - - - - - - - [[ formatLang(sum_debit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)-sum_debit_period(o.id), currency_obj=company.currency_id) ]] - - - - - - - - - - [[ display_currency(data)==False or removeParentNode('blockTable') ]] - - - [[ o.name ]] : - - - - - - - [[ formatLang(sum_debit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)) ]] - - - [[ formatLang(sum_credit_period(o.id)-sum_debit_period(o.id), currency_obj=company.currency_id) ]] - - - -
    - [[ repeatIn(lines(o.id),'line')]] - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - - [[ line['code'] ]] - - - [[ line['name'] ]] - - - [[ formatLang(line['debit'] )]] - - - [[ formatLang(line['credit']) ]] - - - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - - - -
    -
    - [[ repeatIn(lines(o.id),'line')]] - [[ display_currency(data) or removeParentNode('blockTable') ]] - - [[ line['code'] ]] - [[ line['name'] ]] - [[ formatLang(line['debit'] )]] - [[ formatLang(line['credit']) ]] - [[ formatLang(line['credit']-line['debit'], currency_obj=company.currency_id ) ]] - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - -
    - - - -
    - - - -
    -
    diff --git a/addons/account/report/account_general_ledger.rml b/addons/account/report/account_general_ledger.rml deleted file mode 100644 index 6897e15078d..00000000000 --- a/addons/account/report/account_general_ledger.rml +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - - - [[ repeatIn(objects, 'a') ]] - General Ledger - - - - - - - Chart of Accounts - - - Fiscal Year - - - Journals - - - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - - - Target Moves - - - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - - - - [[ get_target_move(data) ]] - - - - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - -
    - [[ repeatIn(get_children_accounts(a), 'o') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - [[ o.currency_id and formatLang(sum_currency_amount_account(o), digits=get_digits(dp='Account'),currency_obj=o.currency_id) or '' ]] - - - -
    - [[ repeatIn(lines(o), 'line') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],10) ]] - - - [[ line['lref'] and strip_name(line['lref'],9) ]] - - - [[ strip_name(line['move'],9) ]] - - - [[ strip_name(line['lname'],10) ]] - - - [[ strip_name(line['line_corresp'].replace(', ',','),10) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - [[ (line.has_key('currency_id') and line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'])]] [[ line['currency_code'] or '']] - - - -
    -
    - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - -
    - [[ repeatIn(get_children_accounts(a), 'o') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - -
    - [[ repeatIn(lines(o), 'line') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],20) ]] - - - [[ line['lref'] and strip_name(line['lref'],9) ]] - - - [[ strip_name(line['move'],9) ]] - - - [[ strip_name(line['lname'],18) ]] - - - [[ strip_name(line['line_corresp'].replace(', ',','),20) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - -
    -
    -
    -
    -
    diff --git a/addons/account/report/account_general_ledger_landscape.rml b/addons/account/report/account_general_ledger_landscape.rml deleted file mode 100644 index c5d24343148..00000000000 --- a/addons/account/report/account_general_ledger_landscape.rml +++ /dev/null @@ -1,658 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - - - [[ repeatIn(objects, 'a') ]] - General Ledger - - - - - - - Company[[ data['model']=='account.account' and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - - Fiscal Year - - - Journals - - - Display Account - - - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - - - Entries Sorted By - - - Target Moves - - - - - - - [[ get_account(data) or removeParentNode('para') ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - All[[ data['form']['display_account']=='all' and ' ' or removeParentNode('para') ]] - With movements[[ data['form']['display_account']=='movement' and ' ' or removeParentNode('para') ]] - With balance is not equal to 0[[ data['form']['display_account']=='not_zero' and ' ' or removeParentNode('para') ]] - - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - [[ get_sortby(data) ]] - - - [[ get_target_move(data) ]] - - - - - - - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - Currency - - - -
    - [[ repeatIn(get_children_accounts(a), 'o') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'), currency_obj= company.currency_id) ]] - - - [[ o.currency_id and formatLang(sum_currency_amount_account(o), digits=get_digits(dp='Account'),currency_obj=o.currency_id) or '' ]] - - - -
    - [[ repeatIn(lines(o), 'line') ]] - [[data['form']['amount_currency'] == True or removeParentNode('blockTable')]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['period_code'] ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],20) ]] - - - [[ line['lref'] and strip_name(line['lref'],17) ]] - - - [[ line['move'] ]] - - - [[ strip_name(line['lname'],22) ]] - - - [[ strip_name(line['line_corresp'],18) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (line.has_key('currency_id') and line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'])]] [[ line['currency_code'] or '']] - - - -
    -
    - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - Date - - - Period - - - JRNL - - - Partner - - - Ref - - - Move - - - Entry Label - - - Counterpart - - - Debit - - - Credit - - - Balance - - - -
    - [[ repeatIn(get_children_accounts(a), 'o') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ '..'*(o.level-1) ]][[ o.code ]] [[ o.name ]] - - - [[ formatLang(sum_debit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_credit_account(o), digits=get_digits(dp='Account')) ]] - - - [[ formatLang(sum_balance_account(o), digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - -
    - [[ repeatIn(lines(o), 'line') ]] - [[ data['form']['amount_currency'] == False or removeParentNode('blockTable') ]] - - - [[ formatLang(line['ldate'],date=True) ]] - - - [[ line['period_code'] ]] - - - [[ line['lcode'] ]] - - - [[ strip_name(line['partner_name'],24) ]] - - - [[ strip_name(line['lref'],21) ]] - - - [[ line['move'] ]] - - - [[ strip_name(line['lname'],28) ]] - - - [[ strip_name(line['line_corresp'],23) ]] - - - [[ formatLang(line['debit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['credit'], digits=get_digits(dp='Account')) ]] - - - [[ formatLang(line['progress'], digits=get_digits(dp='Account'),currency_obj=company.currency_id) ]] - - - -
    -
    -
    -
    -
    diff --git a/addons/account/report/account_journal.rml b/addons/account/report/account_journal.rml deleted file mode 100644 index 6d606ed1937..00000000000 --- a/addons/account/report/account_journal.rml +++ /dev/null @@ -1,311 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects, 'o') ]] - - - - Journal - - - - - - - - Company[[ data['model']=='account.journal.period'and ' ' or removeParentNode('para') ]] - Chart of Accounts[[ data['model']=='ir.ui.menu' and ' ' or removeParentNode('para') ]] - Fiscal Year - Journal - Period - Entries Sorted By - Target Moves - - - [[ get_account(data) or '' ]] - [[ get_fiscalyear(data) or '' ]] - [[ o.journal_id.name ]] - [[ o.period_id.name ]] - - Date[[ data['form'].get('sort_selection', 'date') == 'date' and ' ' or removeParentNode('para') ]] - Reference Number[[ data['form'].get('sort_selection', 'date') == 'ref' and ' ' or removeParentNode('para') ]] - - - - - - - - - - [[ set_last_move_id(False)]] -
    - [[ display_currency(data) == False or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Debit - Credit - - -
    - [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,23) ]] - [[ strip_name(line.name,35) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
    - - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - -
    - -
    - [[ display_currency(data) or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Debit - Credit - Currency - - -
    - [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,17) ]] - [[ strip_name(line.name,28) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - [[ line.currency_id and formatLang(line.amount_currency, currency_obj=line.currency_id) or '' ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
    - - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - - - -
    -
    -
    diff --git a/addons/account/report/account_journal_sale_purchase.rml b/addons/account/report/account_journal_sale_purchase.rml deleted file mode 100644 index 3ee0b484c9a..00000000000 --- a/addons/account/report/account_journal_sale_purchase.rml +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects, 'o') ]] - - - - Journal - - - - - - - - [[ data['model']=='account.journal.period'and 'Company' or removeParentNode('para') ]] - [[ data['model']=='ir.ui.menu' and 'Chart of Accounts' or removeParentNode('para') ]] - Fiscal Year - Journal - Period - Entries Sorted By - Target Moves - - - [[ get_account(data) or '' ]] - [[ get_fiscalyear(data) or '' ]] - [[ o.journal_id.name ]] - [[ o.period_id.name ]] - [[ get_sortby(data) ]] - [[ get_target_move(data) ]] - - - - - - - - - [[ set_last_move_id(False) ]] -
    - [[ display_currency(data) == False or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Tax - - Debit - Credit - - -
    - [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,15) ]] - [[ strip_name(line.name,25) ]] - [[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]] - [[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
    - - - - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - -
    - -
    - [[ display_currency(data) or removeParentNode('section') ]] - - - Move - Date - Account - Partner - Label - Tax - - Debit - Credit - Currency - - -
    - [[ repeatIn(lines(o.period_id.id, o.journal_id.id), 'line') ]] - - - [[ not check_last_move_id(line.move_id.id) and removeParentNode('blockTable') ]] - - - - - [[ line.move_id.name <> '/' and line.move_id.name or ('*'+str(line.move_id.id)) ]] - [[ formatLang(line.date,date=True) ]] - [[ line.account_id.code ]] - [[ line.partner_id and strip_name(line.partner_id.name,12) ]] - [[ strip_name(line.name,16) ]] - [[ line.tax_code_id and line.tax_code_id.code and (line.tax_code_id.code + ':') ]] - [[ line.tax_amount and formatLang(line.tax_amount, currency_obj=company.currency_id) ]] - [[ formatLang(line.debit, currency_obj=company.currency_id) ]] - [[ formatLang(line.credit, currency_obj=company.currency_id) ]] - [[ line.currency_id and formatLang(line.amount_currency, currency_obj=line.currency_id) or '' ]] - - - [[ set_last_move_id(line.move_id.id) ]] -
    - - - - - - - - - Total: - [[ formatLang(sum_debit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - [[ formatLang(sum_credit(o.period_id.id, o.journal_id.id), currency_obj=company.currency_id) ]] - - - - -
    - - - - - - - -
    - - - - - - Tax Declaration - - - - - [[ repeatIn(tax_codes(o.period_id.id,o.journal_id.id), 't') ]][[ t.code + ': ' ]] - [[ formatLang(sum_vat( o.period_id.id, o.journal_id.id, t.id)) ]] - - [[ t.name ]] - - -
    -
    -
    diff --git a/addons/account/report/account_partner_balance.rml b/addons/account/report/account_partner_balance.rml deleted file mode 100644 index a99a7f062ec..00000000000 --- a/addons/account/report/account_partner_balance.rml +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Partner Balance - - - - - - - - - Chart of Accounts - Fiscal Year - Journals - Filter By [[ data['form']['filter']!='filter_no' and get_filter(data) ]] - Partner's - Target Moves - - - [[ get_account(data) or removeParentNode('para') ]] - [[ get_fiscalyear(data) or '' ]] - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - [[ data['form']['filter']=='filter_no' and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - Start Date - End Date - - - [[ formatLang(get_start_date(data),date=True) ]] - [[ formatLang(get_end_date(data),date=True) ]] - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - Start Period - End Period - - - [[ get_start_period(data) or removeParentNode('para') ]] - [[ get_end_period(data) or removeParentNode('para') ]] - - - - [[ get_partners() ]] - [[ get_target_move(data) ]] - - - - - - - - - - Code - (Account/Partner) Name - Debit - Credit - Balance - In dispute - - - Total: - - [[ formatLang(sum_debit()) ]] - [[ formatLang(sum_credit()) ]] - [[ formatLang((sum_debit()-sum_credit()), currency_obj=company.currency_id) ]] - [[ formatLang(sum_litige(), currency_obj=company.currency_id) ]] - - - [[ repeatIn(lines(), 'a') ]][[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ a['ref'] ]] [[ a['type']==3 and a['code'] ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ a['name'] ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['debit']) ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['credit']) ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['balance'], currency_obj=company.currency_id) ]] - [[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['enlitige'] or 0.0, currency_obj=company.currency_id) ]] - - - - diff --git a/addons/account/report/account_partner_ledger.rml b/addons/account/report/account_partner_ledger.rml deleted file mode 100644 index 48ed6d4afe3..00000000000 --- a/addons/account/report/account_partner_ledger.rml +++ /dev/null @@ -1,658 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - - - [[ repeatIn(objects, 'p') ]] - [[ setLang(p.lang) ]] - - - - Partner Ledger - - - - - - - Chart of Accounts - - - Fiscal Year - - - Journals - - - Filters By [[ data['form']['filter'] not in ('filter_no','unreconciled') and get_filter(data) ]] - - - Partner's - - - Target Moves - - - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - [[ data['form']['filter'] in ('filter_no','unreconciled') and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - - - - Receivable Accounts[[ data['form'].get('result_selection', 'customer') == 'customer' or removeParentNode('para') ]] - Payable Accounts[[ data['form'].get('result_selection', 'customer') == 'supplier' or removeParentNode('para') ]] - Receivable and Payable Accounts[[ data['form'].get('result_selection', 'customer') == 'customer_supplier' or removeParentNode('para') ]] - - - [[ get_target_move(data) ]] - - - - - - -
    - - [[ display_currency(data) == False or removeParentNode('section') ]] - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - -
    - - [[data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - -
    -
    - [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ line['ref'] and strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - -
    -
    -
    - - [[ display_currency(data) == True or removeParentNode('section') ]] - - - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - - - - - - -
    - [[ data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - - - - - - -
    -
    - [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ strip_name(line['ref'],8) ]] - [[ strip_name(line['name'],7) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - - - -
    -
    -
    -
    -
    diff --git a/addons/account/report/account_partner_ledger_other.rml b/addons/account/report/account_partner_ledger_other.rml deleted file mode 100644 index b878ab44e47..00000000000 --- a/addons/account/report/account_partner_ledger_other.rml +++ /dev/null @@ -1,665 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - - - [[ display_currency(data) == True or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - - - - - - - Partner Ledger - - - - - - - Chart of Accounts - - - Fiscal Year - - - Journals - - - Filters By [[ data['form']['filter'] not in ('filter_no','unreconciled') and get_filter(data) ]] - - - Partner's - - - Target Moves - - - - - - - [[ get_account(data) or '' ]] - - - [[ get_fiscalyear(data) or '' ]] - - - [[', '.join([ lt or '' for lt in get_journal(data) ]) ]] - - - [[ data['form']['filter'] in ('filter_no','unreconciled') and get_filter(data) or removeParentNode('para') ]] - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - Start Date - - - End Date - - - - [[ data['form']['filter']=='filter_date' or removeParentNode('blockTable') ]] - - - [[ formatLang(get_start_date(data),date=True) ]] - - - [[ formatLang(get_end_date(data),date=True) ]] - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - Start Period - - - End Period - - - - [[ data['form']['filter']=='filter_period' or removeParentNode('blockTable') ]] - - - [[ get_start_period(data) or removeParentNode('para') ]] - - - [[ get_end_period(data) or removeParentNode('para') ]] - - - - - - - - - [[ get_partners() ]] - - - [[ get_target_move(data) ]] - - - - - - - - [[ display_currency(data) == False or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - -
    - [[ repeatIn(objects, 'p') ]] - [[ setLang(p.lang) ]] - - [[ display_currency(data) == False or removeParentNode('section') ]] - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - -
    - - [[data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - -
    -
    - [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ line['ref'] and strip_name(line['ref'],10) ]] - [[ strip_name(line['name'],15) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - -
    -
    - - [[ display_currency(data) == True or removeParentNode('blockTable') ]] - - - Date - - - JRNL - - - Ref - - - Account - - - Entry Label - - - Debit - - - Credit - - - Balance - - - Currency - - - -
    - [[ repeatIn(objects, 'p') ]] - [[ setLang(p.lang) ]] - - [[ display_currency(data) == True or removeParentNode('section') ]] - - - - - - [[ p.ref ]] - [[ p.name ]] - - - [[ formatLang((sum_debit_partner(p))) ]] - - - [[ formatLang((sum_credit_partner(p))) ]] - - - [[ formatLang((sum_debit_partner(p) - sum_credit_partner(p)), currency_obj=company.currency_id) ]] - - - - - - - - -
    - [[ data['form']['initial_balance']==True or removeParentNode('section') ]] - - - - Initial Balance - - - [[ formatLang(get_intial_balance(p)[0][0])]] - - - [[ formatLang(get_intial_balance(p)[0][1]) ]] - - - [[ formatLang(get_intial_balance(p)[0][2], currency_obj=company.currency_id) ]] - - - - - - - - -
    -
    - [[ repeatIn(lines(p), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['code'] ]] - - - [[ line['move_name'] ]] - - - [[ line['a_code'] ]] - - - [[ strip_name(line['ref'],8) ]] - [[ strip_name(line['name'],7) ]] - - - [[ formatLang((line['debit'])) ]] - - - [[ formatLang((line['credit'])) ]] - - - [[ formatLang((line['progress']), currency_obj=company.currency_id) ]] - - - - [[ (line['currency_id']==None or line['amount_currency']==None) and removeParentNode('font') ]] [[ formatLang(line['amount_currency'] ) ]] [[ line['currency_code'] or '' ]] - - - - -
    -
    -
    -
    -
    diff --git a/addons/account/report/account_print_invoice.py b/addons/account/report/account_print_invoice.py deleted file mode 100644 index 75680810254..00000000000 --- a/addons/account/report/account_print_invoice.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -import time -from openerp.report import report_sxw - -class account_invoice(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(account_invoice, self).__init__(cr, uid, name, context=context) - self.localcontext.update({ - 'time': time, - }) -report_sxw.report_sxw( - 'report.account.invoice', - 'account.invoice', - 'addons/account/report/account_print_invoice.rml', - parser=account_invoice -) -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_print_invoice.rml b/addons/account/report/account_print_invoice.rml deleted file mode 100644 index 6914adfaf20..00000000000 --- a/addons/account/report/account_print_invoice.rml +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - [[ setLang(o.partner_id.lang) ]] - - - - Description - Taxes - Quantity - Unit Price - Disc.(%) - Price - - - - - - - - - - - - [[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]] - [[ display_address(o.partner_id) ]] - - - - Tel. : [[ (o.partner_id.phone) or removeParentNode('para') ]] - Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]] - TIN : [[ (o.partner_id.vat) or removeParentNode('para') ]] - - - - Invoice [[ ((o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')) or removeParentNode('para')) and '' ]] [[ o.number ]] - PRO-FORMA [[ ((o.type == 'out_invoice' and o.state == 'proforma2') or removeParentNode('para')) and '' ]] - Draft Invoice [[ ((o.type == 'out_invoice' and o.state == 'draft') or removeParentNode('para')) and '' ]] - Cancelled Invoice [[ ((o.type == 'out_invoice' and o.state == 'cancel') or removeParentNode('para')) and '' ]] [[ o.number ]] - Refund [[ (o.type=='out_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Refund [[ (o.type=='in_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Invoice [[ (o.type=='in_invoice' or removeParentNode('para')) and '' ]] [[ o.number ]] - - - - - - - Description - - - Invoice Date - - - Source - - - Customer Code - - - - - - - [[ o.name or ' ' ]] - - - [[ formatLang(o.date_invoice,date=True) ]] - - - [[ o.origin or '' ]] - - - [[ (o.partner_id.ref) or ' ' ]] - - - - - - - - - - Description - - - Taxes - - - Quantity - - - Unit Price - - - Disc.(%) - - - Price - - - -
    - [[ repeatIn(o.invoice_line,'l') ]] - - - - [[ format(l.name) ]] - - - [[ ', '.join([ lt.name or '' for lt in l.invoice_line_tax_id ]) ]] - - - [[ formatLang(l.quantity)]] [[ (l.uos_id and l.uos_id.name) or '' ]] - - - [[ formatLang(l.price_unit) ]] - - - [[ formatLang(l.discount, dp='Account') ]] - - - [[ formatLang(l.price_subtotal, dp='Account', currency_obj=o.currency_id) ]] - - - -
    - - - - - - - - - Net Total: - - - [[ formatLang(o.amount_untaxed, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - - - Taxes: - - - [[ formatLang(o.amount_tax, dp='Account', currency_obj=o.currency_id) ]] - - - - - - - - - - Total: - - - [[ formatLang(o.amount_total, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - - - Tax [[ o.tax_line==[] and removeParentNode('blockTable') ]] - - - Base - - - Amount - - - - - - - - -
    - [[ repeatIn(o.tax_line,'t') ]] - - - - [[ t.name ]] - - - [[ formatLang(t.base, dp='Account', currency_obj=o.currency_id) ]] - - - [[ (t.tax_code_id and t.tax_code_id.notprintable) and removeParentNode('blockTable') or '' ]] [[ formatLang(t.amount, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - -
    - - - - [[ (o.comment and format(o.comment )) or removeParentNode('para') ]] - - - - [[ (o.payment_term and o.payment_term.note and format(o.payment_term and o.payment_term.note)) or removeParentNode('para') ]] - - - - - - - Fiscal Position Remark : - - - [[ (o.fiscal_position and o.fiscal_position.note and format(o.fiscal_position.note)) or removeParentNode('blockTable') ]] - - - - - - -
    -
    -
    diff --git a/addons/account/report/account_print_overdue.rml b/addons/account/report/account_print_overdue.rml deleted file mode 100644 index 9d1898572ba..00000000000 --- a/addons/account/report/account_print_overdue.rml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Date - - - Description - - - Ref - - - Maturity date - - - Due - - - Paid - - - Maturity - - - Li. - - - - - [[ repeatIn(objects,'o') ]] - [[ setLang(o.lang) ]] - - - - - - [[ o.title.name or '' ]] [[ o.name ]] - [[ display_address(o) ]] - - - - VAT: [[ o.vat or removeParentNode('para') ]] - - - - - - - - - - Document: Customer account statement - Date: [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] - Customer Ref: [[ o.ref or ' ']] - - - - - - -
    - [[ not getLines(o) and removeParentNode('section')]] -
    - [[repeatIn(message(o, company), 'message_line') ]] - [[ message_line ]] - - - -
    - - - - Date - - - Description - - - Ref - - - Maturity date - - - Due - - - Paid - - - Maturity - - - Li. - - - -
    [[repeatIn(getLines(o), 'line') ]] - - - - [[ formatLang(line['date'],date=True) ]] - - - [[ line['name'] ]] - - - [[ line['ref'] ]] - - - [[ line['date_maturity'] and formatLang(line['date_maturity'],date=True) or '' ]] - - - [[ (line['account_id']['type'] == 'receivable' and formatLang(line['debit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['credit'] * -1) or ' ') ]] - - - [[ (line['account_id']['type'] == 'receivable' and formatLang(line['credit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['debit'] * -1) or 0) ]] - - - [[ (time.strftime('%Y-%m-%d') > line['date_maturity']) and formatLang(line['debit'] - line['credit'], currency_obj = company.currency_id) ]] - - - [[ line['blocked'] and 'X' or '' ]] - - - -
    - - - - - - - - - Sub-Total : - - - [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), getLines(o), 0))) ]] - - - [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), getLines(o), 0))) ]] - - - [[ formatLang((reduce(lambda x, y: x + (y['debit'] - y['credit']), filter(lambda x: x['date_maturity'] < time.strftime('%Y-%m-%d'), getLines(o)), 0)), currency_obj=company.currency_id) ]] - - - - - - - - - - - - - - - - - Balance : - - - [[ formatLang((reduce(lambda x, y: x +(y['debit'] - y['credit']), getLines(o), 0)), currency_obj = company.currency_id) ]] - - - - - - - - - - - - - - - Total amount due: [[ formatLang((reduce(lambda x, y: x + (y['debit'] - y['credit']), getLines(o), 0)), currency_obj=company.currency_id) ]] -
    - - - -
    - [[ getLines(o) and removeParentNode('section')]]There is nothing due with this customer. -
    - - - - - - -
    -
    -
    diff --git a/addons/account/views/report_agedpartnerbalance.xml b/addons/account/views/report_agedpartnerbalance.xml new file mode 100644 index 00000000000..9ab05afa772 --- /dev/null +++ b/addons/account/views/report_agedpartnerbalance.xml @@ -0,0 +1,133 @@ + + + + + + diff --git a/addons/account/views/report_centraljournal.xml b/addons/account/views/report_centraljournal.xml new file mode 100644 index 00000000000..e939fa98fc3 --- /dev/null +++ b/addons/account/views/report_centraljournal.xml @@ -0,0 +1,93 @@ + + + + + + diff --git a/addons/account/views/report_financial.xml b/addons/account/views/report_financial.xml new file mode 100644 index 00000000000..69802331a5b --- /dev/null +++ b/addons/account/views/report_financial.xml @@ -0,0 +1,128 @@ + + + + + + diff --git a/addons/account/views/report_generaljournal.xml b/addons/account/views/report_generaljournal.xml new file mode 100644 index 00000000000..2dd07cf87fd --- /dev/null +++ b/addons/account/views/report_generaljournal.xml @@ -0,0 +1,98 @@ + + + + + + diff --git a/addons/account/views/report_generalledger.xml b/addons/account/views/report_generalledger.xml new file mode 100644 index 00000000000..d873571dee3 --- /dev/null +++ b/addons/account/views/report_generalledger.xml @@ -0,0 +1,133 @@ + + + + + + + diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml new file mode 100644 index 00000000000..bc0dc5e92a2 --- /dev/null +++ b/addons/account/views/report_invoice.xml @@ -0,0 +1,153 @@ + + + + + + + + diff --git a/addons/account/views/report_journal.xml b/addons/account/views/report_journal.xml new file mode 100644 index 00000000000..a9cd56b4109 --- /dev/null +++ b/addons/account/views/report_journal.xml @@ -0,0 +1,88 @@ + + + + + + diff --git a/addons/account/views/report_overdue.xml b/addons/account/views/report_overdue.xml new file mode 100644 index 00000000000..080de9a5615 --- /dev/null +++ b/addons/account/views/report_overdue.xml @@ -0,0 +1,113 @@ + + + + + + diff --git a/addons/account/views/report_partnerbalance.xml b/addons/account/views/report_partnerbalance.xml new file mode 100644 index 00000000000..11948905fe9 --- /dev/null +++ b/addons/account/views/report_partnerbalance.xml @@ -0,0 +1,125 @@ + + + + + + diff --git a/addons/account/views/report_partnerledger.xml b/addons/account/views/report_partnerledger.xml new file mode 100644 index 00000000000..333fab7aa5c --- /dev/null +++ b/addons/account/views/report_partnerledger.xml @@ -0,0 +1,131 @@ + + + + + + diff --git a/addons/account/views/report_partnerledgerother.xml b/addons/account/views/report_partnerledgerother.xml new file mode 100644 index 00000000000..b8f3d525f51 --- /dev/null +++ b/addons/account/views/report_partnerledgerother.xml @@ -0,0 +1,131 @@ + + + + + + diff --git a/addons/account/views/report_salepurchasejournal.xml b/addons/account/views/report_salepurchasejournal.xml new file mode 100644 index 00000000000..a6441122125 --- /dev/null +++ b/addons/account/views/report_salepurchasejournal.xml @@ -0,0 +1,107 @@ + + + + + + diff --git a/addons/account/views/report_trialbalance.xml b/addons/account/views/report_trialbalance.xml new file mode 100644 index 00000000000..6a27b957971 --- /dev/null +++ b/addons/account/views/report_trialbalance.xml @@ -0,0 +1,94 @@ + + + + + + diff --git a/addons/account/wizard/account_financial_report.py b/addons/account/wizard/account_financial_report.py index 48bdfd33081..df1fa94ae90 100644 --- a/addons/account/wizard/account_financial_report.py +++ b/addons/account/wizard/account_financial_report.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class accounting_report(osv.osv_memory): _name = "accounting.report" _inherit = "account.common.report" @@ -83,16 +84,13 @@ class accounting_report(osv.osv_memory): if isinstance(data['form'][field], tuple): data['form'][field] = data['form'][field][0] comparison_context = self._build_comparison_context(cr, uid, ids, data, context=context) - res['datas']['form']['comparison_context'] = comparison_context + res['data'] = {} + res['data']['form'] = data['form'] + res['data']['form']['comparison_context'] = comparison_context return res def _print_report(self, cr, uid, ids, data, context=None): data['form'].update(self.read(cr, uid, ids, ['date_from_cmp', 'debit_credit', 'date_to_cmp', 'fiscalyear_id_cmp', 'period_from_cmp', 'period_to_cmp', 'filter_cmp', 'account_report_id', 'enable_filter', 'label_filter','target_move'], context=context)[0]) - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.financial.report', - 'datas': data, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_financial', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_account_balance.py b/addons/account/wizard/account_report_account_balance.py index fd3c966e306..3b9d3c21777 100644 --- a/addons/account/wizard/account_report_account_balance.py +++ b/addons/account/wizard/account_report_account_balance.py @@ -36,7 +36,6 @@ class account_balance_report(osv.osv_memory): def _print_report(self, cr, uid, ids, data, context=None): data = self.pre_print_report(cr, uid, ids, data, context=context) - return {'type': 'ir.actions.report.xml', 'report_name': 'account.account.balance', 'datas': data} - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_trialbalance', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_aged_partner_balance.py b/addons/account/wizard/account_report_aged_partner_balance.py index c483487b78f..c918a1119fd 100644 --- a/addons/account/wizard/account_report_aged_partner_balance.py +++ b/addons/account/wizard/account_report_aged_partner_balance.py @@ -25,6 +25,7 @@ from dateutil.relativedelta import relativedelta from openerp.osv import fields, osv from openerp.tools.translate import _ + class account_aged_trial_balance(osv.osv_memory): _inherit = 'account.common.partner.report' _name = 'account.aged.trial.balance' @@ -80,11 +81,6 @@ class account_aged_trial_balance(osv.osv_memory): data['form'].update(res) if data.get('form',False): data['ids']=[data['form'].get('chart_account_id',False)] - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.aged_trial_balance', - 'datas': data - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_agedpartnerbalance', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_central_journal.py b/addons/account/wizard/account_report_central_journal.py index a6bc111fa35..9f22d49afac 100644 --- a/addons/account/wizard/account_report_central_journal.py +++ b/addons/account/wizard/account_report_central_journal.py @@ -32,13 +32,6 @@ class account_central_journal(osv.osv_memory): def _print_report(self, cr, uid, ids, data, context=None): data = self.pre_print_report(cr, uid, ids, data, context=context) - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.central.journal', - 'datas': data, - } - - -#vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_centraljournal', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_general_journal.py b/addons/account/wizard/account_report_general_journal.py index e5e516b1f38..3d9d55b19c1 100644 --- a/addons/account/wizard/account_report_general_journal.py +++ b/addons/account/wizard/account_report_general_journal.py @@ -32,9 +32,6 @@ class account_general_journal(osv.osv_memory): def _print_report(self, cr, uid, ids, data, context=None): data = self.pre_print_report(cr, uid, ids, data, context=context) - return {'type': 'ir.actions.report.xml', 'report_name': 'account.general.journal', 'datas': data} - - -#vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_generaljournal', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_general_ledger.py b/addons/account/wizard/account_report_general_ledger.py index fae60df63fb..c75477da40a 100644 --- a/addons/account/wizard/account_report_general_ledger.py +++ b/addons/account/wizard/account_report_general_ledger.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_report_general_ledger(osv.osv_memory): _inherit = "account.common.account.report" _name = "account.report.general.ledger" @@ -54,9 +55,10 @@ class account_report_general_ledger(osv.osv_memory): data['form'].update(self.read(cr, uid, ids, ['landscape', 'initial_balance', 'amount_currency', 'sortby'])[0]) if not data['form']['fiscalyear_id']:# GTK client problem onchange does not consider in save record data['form'].update({'initial_balance': False}) - if data['form']['landscape']: - return { 'type': 'ir.actions.report.xml', 'report_name': 'account.general.ledger_landscape', 'datas': data} - return { 'type': 'ir.actions.report.xml', 'report_name': 'account.general.ledger', 'datas': data} + if data['form']['landscape'] is False: + data['form'].pop('landscape') + + return self.pool['report'].get_action(cr, uid, ids, 'account.report_generalledger', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_partner_balance.py b/addons/account/wizard/account_report_partner_balance.py index fbe18f27d69..d4b5fb27d14 100644 --- a/addons/account/wizard/account_report_partner_balance.py +++ b/addons/account/wizard/account_report_partner_balance.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_partner_balance(osv.osv_memory): """ This wizard will provide the partner balance report by periods, between any two dates. @@ -35,7 +36,6 @@ class account_partner_balance(osv.osv_memory): } _defaults = { -# 'initial_balance': True, 'display_partner': 'non-zero_balance', } @@ -44,11 +44,6 @@ class account_partner_balance(osv.osv_memory): context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['display_partner'])[0]) - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.partner.balance', - 'datas': data, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerbalance', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_partner_ledger.py b/addons/account/wizard/account_report_partner_ledger.py index fdabe49ff17..75f79512603 100644 --- a/addons/account/wizard/account_report_partner_ledger.py +++ b/addons/account/wizard/account_report_partner_ledger.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_partner_ledger(osv.osv_memory): """ This wizard will provide the partner Ledger report by periods, between any two dates. @@ -37,6 +38,7 @@ class account_partner_ledger(osv.osv_memory): 'amount_currency': fields.boolean("With Currency", help="It adds the currency column on report if the currency differs from the company currency."), 'journal_ids': fields.many2many('account.journal', 'account_partner_ledger_journal_rel', 'account_id', 'journal_id', 'Journals', required=True), } + _defaults = { 'initial_balance': False, 'page_split': False, @@ -45,8 +47,8 @@ class account_partner_ledger(osv.osv_memory): def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): res = super(account_partner_ledger, self).onchange_filter(cr, uid, ids, filter=filter, fiscalyear_id=fiscalyear_id, context=context) if filter in ['filter_no', 'unreconciled']: - if filter == 'unreconciled': - res['value'].update({'fiscalyear_id': False}) + if filter == 'unreconciled': + res['value'].update({'fiscalyear_id': False}) res['value'].update({'initial_balance': False, 'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False}) return res @@ -55,17 +57,6 @@ class account_partner_ledger(osv.osv_memory): context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['initial_balance', 'filter', 'page_split', 'amount_currency'])[0]) - if data['form']['page_split']: - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.third_party_ledger', - 'datas': data, - } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.third_party_ledger_other', - 'datas': data, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerledger', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_report_print_journal.py b/addons/account/wizard/account_report_print_journal.py index 3ad45268248..3aafc63acf4 100644 --- a/addons/account/wizard/account_report_print_journal.py +++ b/addons/account/wizard/account_report_print_journal.py @@ -22,6 +22,7 @@ from openerp.osv import fields, osv from lxml import etree + class account_print_journal(osv.osv_memory): _inherit = "account.common.journal.report" _name = 'account.print.journal' @@ -60,19 +61,14 @@ class account_print_journal(osv.osv_memory): res['arch'] = etree.tostring(doc) return res - def _print_report(self, cr, uid, ids, data, context=None): if context is None: context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['sort_selection'], context=context)[0]) if context.get('sale_purchase_only'): - report_name = 'account.journal.period.print.sale.purchase' + return self.pool['report'].get_action(cr, uid, ids, 'account.report_salepurchasejournal', data=data, context=context) else: - report_name = 'account.journal.period.print' - return {'type': 'ir.actions.report.xml', 'report_name': report_name, 'datas': data} - - -#vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_journal', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/account_vat.py b/addons/account/wizard/account_vat.py index 6fbfcc9ddf5..5cc5c678df1 100644 --- a/addons/account/wizard/account_vat.py +++ b/addons/account/wizard/account_vat.py @@ -21,6 +21,7 @@ from openerp.osv import fields, osv + class account_vat_declaration(osv.osv_memory): _name = 'account.vat.declaration' _description = 'Account Vat Declaration' @@ -60,6 +61,6 @@ class account_vat_declaration(osv.osv_memory): taxcode = taxcode_obj.browse(cr, uid, [taxcode_id], context=context)[0] datas['form']['company_id'] = taxcode.company_id.id - return self.pool['report'].get_action(cr, uid, ids, 'account.report_vat', datas=datas, context=context) + return self.pool['report'].get_action(cr, uid, ids, 'account.report_vat', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_plans/__openerp__.py b/addons/account_analytic_plans/__openerp__.py index af5b5654b99..7c580bd14f2 100644 --- a/addons/account_analytic_plans/__openerp__.py +++ b/addons/account_analytic_plans/__openerp__.py @@ -19,7 +19,6 @@ # ############################################################################## - { 'name': 'Multiple Analytic Plans', 'version': '1.0', @@ -74,9 +73,10 @@ The analytic plan validates the minimum and maximum percentage at the time of cr 'account_analytic_plans_report.xml', 'wizard/analytic_plan_create_model_view.xml', 'wizard/account_crossovered_analytic_view.xml', + 'views/report_crossoveredanalyticplans.xml', ], 'demo': [], - 'test': ['test/acount_analytic_plans_report.yml'], + 'test': [], 'installable': True, 'auto_install': False, } diff --git a/addons/account_analytic_plans/account_analytic_plans_report.xml b/addons/account_analytic_plans/account_analytic_plans_report.xml index 05d4c5b445c..608a22d1d96 100644 --- a/addons/account_analytic_plans/account_analytic_plans_report.xml +++ b/addons/account_analytic_plans/account_analytic_plans_report.xml @@ -1,16 +1,15 @@ - - + report_type="qweb-pdf" + name="account_analytic_plans.report_crossoveredanalyticplans" + file="account_analytic_plans.report_crossoveredanalyticplans" + menu="False" + /> diff --git a/addons/account_analytic_plans/report/crossovered_analytic.rml b/addons/account_analytic_plans/report/crossovered_analytic.rml deleted file mode 100644 index 48e7c13b0a1..00000000000 --- a/addons/account_analytic_plans/report/crossovered_analytic.rml +++ /dev/null @@ -1,304 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Account Name - - - Code - - - Quantity - - - Amount - - - Perc(%) - - - - - - - - Crossovered Analytic - - - - - - - From Date - - - To Date - - - Company - - - Currency - - - Printing date - - - - - - - [[ formatLang(data['form']['date1'],date=True) ]] - - - [[ formatLang(data['form']['date2'],date=True) ]] - - - [[ company.name ]] - - - [[ company.currency_id.name ]] - - - [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] at [[ time.strftime('%H:%M:%S') ]] - - - - - - - Analytic Account Reference: - - - - - - - Account Name - - - Code - - - Quantity - - - Amount - - - Perc(%) - - - -
    - [[ repeatIn(ref_lines(data['form']),'a') ]] - - - - [[ a['ref_name'] ]] - - - [[ a['ref_code'] ]] - - - [[ a['ref_qty'] and formatLang(a['ref_qty']) ]] - - - [[ a['ref_amt'] and formatLang(a['ref_amt'], currency_obj=company.currency_id) ]] - - - 100.00% - - - -
    - - - - Analytic Account : - - - - - - - Account Name - - - Code - - - Quantity - - - Amount - - - Percentage - - - -
    - [[ repeatIn(lines(data['form']),'a') ]] - - - - [[ a['acc_name'] ]] - - - [[ a['code'] ]] - - - [[formatLang(a['qty']) ]] - - - [[ formatLang(a['amt'], currency_obj=company.currency_id) ]] - - - [[ formatLang(a['perc']) ]]% - - - - - - -
    -
    -
    -
    diff --git a/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml b/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml new file mode 100644 index 00000000000..bce3cccd5c7 --- /dev/null +++ b/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml @@ -0,0 +1,66 @@ + + + + + + diff --git a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py index d3581d6c457..ccac123c681 100644 --- a/addons/account_analytic_plans/wizard/account_crossovered_analytic.py +++ b/addons/account_analytic_plans/wizard/account_crossovered_analytic.py @@ -65,11 +65,6 @@ class account_crossovered_analytic(osv.osv_memory): 'model': 'account.analytic.account', 'form': data } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.crossovered.analytic', - 'datas': datas, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account_analytic_plans.report_crossoveredanalyticplans', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_bank_statement_extensions/__openerp__.py b/addons/account_bank_statement_extensions/__openerp__.py index 7571eef3e54..203011c46c5 100644 --- a/addons/account_bank_statement_extensions/__openerp__.py +++ b/addons/account_bank_statement_extensions/__openerp__.py @@ -50,6 +50,7 @@ This module adds: 'wizard/confirm_statement_line_wizard.xml', 'wizard/cancel_statement_line_wizard.xml', 'data/account_bank_statement_extensions_data.xml', + 'views/report_bankstatementbalance.xml', ], 'auto_install': False, 'installable': True, diff --git a/addons/account_bank_statement_extensions/account_bank_statement_report.xml b/addons/account_bank_statement_extensions/account_bank_statement_report.xml index b4dafbfd9a7..861c3822520 100644 --- a/addons/account_bank_statement_extensions/account_bank_statement_report.xml +++ b/addons/account_bank_statement_extensions/account_bank_statement_report.xml @@ -1,16 +1,13 @@ - - - - - + + + diff --git a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml deleted file mode 100644 index 963b5d9dd68..00000000000 --- a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ ]] - - - - - - - Bank Statement Balances Report - - - - - - - - - - - - - Name - - - Date - - - Journal - - - Closing Balance - - - - - - -
    - [[ repeatIn(lines, 'l') ]] - - - - [[ l['s_name'] ]] - - - [[ l['s_date'] ]] - - - [[ l['j_code'] ]] - - - [[ formatLang(l['s_balance']) ]] - - - - - - -
    - - - -
    -
    - diff --git a/addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml b/addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml new file mode 100644 index 00000000000..a8ca5f54d3a --- /dev/null +++ b/addons/account_bank_statement_extensions/views/report_bankstatementbalance.xml @@ -0,0 +1,35 @@ + + + + + + diff --git a/addons/account_budget/__openerp__.py b/addons/account_budget/__openerp__.py index 222178b940c..695fd794b9f 100644 --- a/addons/account_budget/__openerp__.py +++ b/addons/account_budget/__openerp__.py @@ -19,7 +19,6 @@ # ############################################################################## - { 'name': 'Budgets Management', 'version': '1.0', @@ -61,13 +60,18 @@ Three reports are available: 'wizard/account_budget_report_view.xml', 'wizard/account_budget_crossovered_summary_report_view.xml', 'wizard/account_budget_crossovered_report_view.xml', + + 'views/report_analyticaccountbudget.xml', + 'views/report_budget.xml', + 'views/report_crossoveredbudget.xml', ], 'demo': ['account_budget_demo.xml'], - 'test':[ + 'test': [ 'test/account_budget.yml', 'test/account_budget_report.yml', ], 'installable': True, 'auto_install': False, } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/account_budget_report.xml b/addons/account_budget/account_budget_report.xml index 9cc38154ef9..7855deb9ccc 100644 --- a/addons/account_budget/account_budget_report.xml +++ b/addons/account_budget/account_budget_report.xml @@ -1,24 +1,34 @@ - - - - - - - + /> + + + + - \ No newline at end of file + diff --git a/addons/account_budget/report/analytic_account_budget_report.rml b/addons/account_budget/report/analytic_account_budget_report.rml deleted file mode 100644 index 15fddebd02d..00000000000 --- a/addons/account_budget/report/analytic_account_budget_report.rml +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - - - [[repeatIn(objects,'o')]] - Analytic Budget - - - - - - - Analysis from - - - Analytic Account - - - Currency - - - - - - - [[ formatLang(data['form']['date_from'],date=True) ]] to [[ formatLang(data['form']['date_to'],date=True) ]] - - - [[ o.name ]] - - - [[ company.currency_id.name ]] - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - -
    - [[ repeatIn(funct(o,data['form']),'a') ]] - - - - [['.....' *(a['status']-1) ]] [[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ a['name'] ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['theo'], currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['pln'], currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['prac'], currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['perc']) ]]% - - - -
    - - - - [[ repeatIn(funct_total(data['form']),'b') ]] Total: - - - [[ formatLang(b['tot_theo'], currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_pln'], currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_prac'], currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_perc']) ]]% - - - - - - -
    -
    -
    diff --git a/addons/account_budget/report/budget_report.rml b/addons/account_budget/report/budget_report.rml deleted file mode 100644 index 789c3ed1ffb..00000000000 --- a/addons/account_budget/report/budget_report.rml +++ /dev/null @@ -1,188 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - - - - Budget - - - - - - - Currency: [[ company.currency_id.name ]] - - - Printed at: [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] at [[ time.strftime('%H:%M:%S')]] - - - - - Analysis from [[ formatLang(data['form']['date_from'],date=True) ]] to [[ formatLang(data['form']['date_to'],date=True) ]] - - - Budget : [[ o.name ]] - - - - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - -
    - [[ repeatIn(funct(o,data['form']),'a') ]] - - - - [['.....' *(a['status']-1) ]][[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ a['name'] ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['theo'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['pln'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['prac'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['perc'], digits=2) ]]% - - - -
    - - - - [[ repeatIn(funct_total(data['form']),'b') ]]Total: - - - [[ formatLang(b['tot_theo'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_pln'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_prac'], digits=get_digits(dp='Account'), currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_perc'], digits=2) ]]% - - - - - - -
    -
    diff --git a/addons/account_budget/report/crossovered_budget_report.rml b/addons/account_budget/report/crossovered_budget_report.rml deleted file mode 100644 index a63920a4c9f..00000000000 --- a/addons/account_budget/report/crossovered_budget_report.rml +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - Budget - - - - - - - Analysis from - - - Budget - - - Currency - - - - - - - [[ formatLang(data['form']['date_from'],date=True) ]] to [[ formatLang(data['form']['date_to'],date=True) ]] - - - [[ o.name ]] - - - [[ company.currency_id.name ]] - - - - - - - - - - Description - - - Theoretical Amt - - - Planned Amt - - - Practical Amt - - - Perc(%) - - - -
    - [[ repeatIn(funct(o,data['form']),'a') ]] - - - - [['.....' *(a['status']-1) ]][[ (a['status']==1 and (setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ a['name'] ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['theo'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['pln'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['prac'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ (a['status']==1 and ( setTag('para','para',{'fontName':'Helvetica-Bold'}))) or removeParentNode('font') ]] [[ formatLang(a['perc'],digits=2) ]]% - - - -
    - - - - [[ repeatIn(funct_total(data['form']),'b') ]] Total : - - - [[ formatLang(b['tot_theo'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_pln'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_prac'], dp='Account', currency_obj=company.currency_id) ]] - - - [[ formatLang(b['tot_perc'],digits=2) ]]% - - - - - - -
    -
    diff --git a/addons/account_budget/views/report_analyticaccountbudget.xml b/addons/account_budget/views/report_analyticaccountbudget.xml new file mode 100644 index 00000000000..dab987d6099 --- /dev/null +++ b/addons/account_budget/views/report_analyticaccountbudget.xml @@ -0,0 +1,69 @@ + + + + + + \ No newline at end of file diff --git a/addons/account_budget/views/report_budget.xml b/addons/account_budget/views/report_budget.xml new file mode 100644 index 00000000000..6bc72fc9dca --- /dev/null +++ b/addons/account_budget/views/report_budget.xml @@ -0,0 +1,77 @@ + + + + + + diff --git a/addons/account_budget/views/report_crossoveredbudget.xml b/addons/account_budget/views/report_crossoveredbudget.xml new file mode 100644 index 00000000000..412c2aac8ed --- /dev/null +++ b/addons/account_budget/views/report_crossoveredbudget.xml @@ -0,0 +1,81 @@ + + + + + + diff --git a/addons/account_budget/wizard/account_budget_analytic.py b/addons/account_budget/wizard/account_budget_analytic.py index 90285b90d1e..a58b804ebbf 100644 --- a/addons/account_budget/wizard/account_budget_analytic.py +++ b/addons/account_budget/wizard/account_budget_analytic.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + # -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_budget_analytic(osv.osv_memory): _name = 'account.budget.analytic' @@ -30,7 +31,7 @@ class account_budget_analytic(osv.osv_memory): 'date_from': fields.date('Start of period', required=True), 'date_to': fields.date('End of period', required=True), } - _defaults= { + _defaults = { 'date_from': lambda *a: time.strftime('%Y-01-01'), 'date_to': lambda *a: time.strftime('%Y-%m-%d'), } @@ -40,15 +41,11 @@ class account_budget_analytic(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.analytic.account', - 'form': data + 'ids': context.get('active_ids', []), + 'model': 'account.analytic.account', + 'form': data } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.analytic.account.budget', - 'datas': datas, - } - + datas['form']['ids'] = datas['ids'] + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_analyticaccountbudget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_crossovered_report.py b/addons/account_budget/wizard/account_budget_crossovered_report.py index 6f89a3cd95c..96561df5af0 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_budget_crossvered_report(osv.osv_memory): _name = "account.budget.crossvered.report" @@ -40,16 +41,12 @@ class account_budget_crossvered_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'crossovered.budget', - 'form': data + 'ids': context.get('active_ids', []), + 'model': 'crossovered.budget', + 'form': data } + datas['form']['ids'] = datas['ids'] datas['form']['report'] = 'analytic-full' - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'crossovered.budget.report', - 'datas': datas, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_crossoveredbudget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py index 6e3131b584c..6b676ecc684 100644 --- a/addons/account_budget/wizard/account_budget_crossovered_summary_report.py +++ b/addons/account_budget/wizard/account_budget_crossovered_summary_report.py @@ -18,10 +18,11 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv + class account_budget_crossvered_summary_report(osv.osv_memory): """ This wizard provides the crossovered budget summary report' @@ -32,7 +33,7 @@ class account_budget_crossvered_summary_report(osv.osv_memory): 'date_from': fields.date('Start of period', required=True), 'date_to': fields.date('End of period', required=True), } - _defaults= { + _defaults = { 'date_from': lambda *a: time.strftime('%Y-01-01'), 'date_to': lambda *a: time.strftime('%Y-%m-%d'), } @@ -42,17 +43,12 @@ class account_budget_crossvered_summary_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'crossovered.budge', - 'form': data + 'ids': context.get('active_ids',[]), + 'model': 'crossovered.budge', + 'form': data } + datas['form']['ids'] = datas['ids'] datas['form']['report'] = 'analytic-one' - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'crossovered.budget.report', - 'datas': datas, - } - + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_crossoveredbudget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account_budget/wizard/account_budget_report.py b/addons/account_budget/wizard/account_budget_report.py index 54c3180ee0d..2308b5ff9ac 100644 --- a/addons/account_budget/wizard/account_budget_report.py +++ b/addons/account_budget/wizard/account_budget_report.py @@ -18,8 +18,8 @@ # along with this program. If not, see . # ############################################################################## -import time +import time from openerp.osv import fields, osv @@ -31,7 +31,7 @@ class account_budget_report(osv.osv_memory): 'date_from': fields.date('Start of period', required=True), 'date_to': fields.date('End of period', required=True), } - _defaults= { + _defaults = { 'date_from': lambda *a: time.strftime('%Y-01-01'), 'date_to': lambda *a: time.strftime('%Y-%m-%d'), } @@ -41,16 +41,12 @@ class account_budget_report(osv.osv_memory): context = {} data = self.read(cr, uid, ids, context=context)[0] datas = { - 'ids': context.get('active_ids',[]), - 'model': 'account.budget.post', - 'form': data + 'ids': context.get('active_ids', []), + 'model': 'account.budget.post', + 'form': data } - datas['form']['report']='analytic-full' - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account.budget', - 'datas': datas, - } - + datas['form']['ids'] = datas['ids'] + datas['form']['report'] = 'analytic-full' + return self.pool['report'].get_action(cr, uid, ids, 'account_budget.report_budget', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_check_writing/__openerp__.py b/addons/account_check_writing/__openerp__.py index e01c17d66a7..3311a7c03b3 100644 --- a/addons/account_check_writing/__openerp__.py +++ b/addons/account_check_writing/__openerp__.py @@ -31,10 +31,12 @@ Module for the Check Writing and Check Printing. 'depends' : ['account_voucher'], 'data': [ 'wizard/account_check_batch_printing_view.xml', - 'account_check_writing_report.xml', 'account_view.xml', 'account_voucher_view.xml', 'account_check_writing_data.xml', + 'data/report_paperformat.xml', + 'views/report_check.xml', + 'account_check_writing_report.xml', ], 'demo': ['account_demo.xml'], 'test': [], diff --git a/addons/account_check_writing/account_check_writing_report.xml b/addons/account_check_writing/account_check_writing_report.xml index eece4e4a5da..d32dd77bc8f 100644 --- a/addons/account_check_writing/account_check_writing_report.xml +++ b/addons/account_check_writing/account_check_writing_report.xml @@ -1,29 +1,17 @@ - + - - - - - + + + + diff --git a/addons/account_check_writing/data/report_paperformat.xml b/addons/account_check_writing/data/report_paperformat.xml new file mode 100644 index 00000000000..3782b8bde40 --- /dev/null +++ b/addons/account_check_writing/data/report_paperformat.xml @@ -0,0 +1,20 @@ + + + + + French Bank Check + + custom + 80 + 175 + Portrait + 3 + 3 + 3 + 3 + + 3 + 80 + + + diff --git a/addons/account_check_writing/report/check_print_bottom.rml b/addons/account_check_writing/report/check_print_bottom.rml deleted file mode 100644 index f9add2fe60b..00000000000 --- a/addons/account_check_writing/report/check_print_bottom.rml +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[repeatIn(objects,'voucher')]] - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[formatLang( l['amount_original']) ]] - - - [[ formatLang( l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[ formatLang (l['amount_original']) ]] - - - [[ formatLang (l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - - - - - - - - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - [[ voucher.partner_id.name ]] - [[ display_address(voucher.partner_id) or removeParentNode('para') ]] - - - - - - - [[ fill_stars(voucher.amount_in_word) ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/account_check_writing/report/check_print_middle.rml b/addons/account_check_writing/report/check_print_middle.rml deleted file mode 100644 index b1fffca662d..00000000000 --- a/addons/account_check_writing/report/check_print_middle.rml +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[repeatIn(objects,'voucher')]] - - - - - - - - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[formatLang( l['amount_original']) ]] - - - [[ formatLang( l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - - - - - - - [[ str(fill_stars(voucher.amount_in_word)) ]] - - - - - - - - - - - - - - - - - - - - - - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - [[ voucher.partner_id.name ]] - [[ display_address(voucher.partner_id) or removeParentNode('para') ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Balance Due - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_original'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[ formatLang (l['amount_original']) ]] - - - [[ formatLang (l['amount_due']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - diff --git a/addons/account_check_writing/report/check_print_top.rml b/addons/account_check_writing/report/check_print_top.rml deleted file mode 100644 index 9a4d633e680..00000000000 --- a/addons/account_check_writing/report/check_print_top.rml +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[repeatIn(objects,'voucher')]] - - - - - - - - - - - - - - - - - - - - - - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - - - - - - [[ voucher.partner_id.name ]] - - - [[ formatLang (voucher.amount) ]] - - - - - - - [[ fill_stars(voucher.amount_in_word) ]] - - - - - - - - - - [[ voucher.partner_id.name ]] - [[ display_address(voucher.partner_id) or removeParentNode('para') ]] - - - - - - - - - - - - - - - [[ voucher.name ]] - - - - - - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Open Balance - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_due'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[formatLang( l['amount_original']) ]] - - - [[ formatLang( l['amount_unreconciled']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - - - [[voucher.partner_id.name]] - - - [[ formatLang(voucher.date , date=True) or '' ]] [[ voucher.journal_id.use_preprint_check and voucher.chk_seq or '' ]] - - - - - - - Due Date - - - Description - - - Original Amount - - - Open Balance - - - Discount - - - Payment - - - - - [[ repeatIn(get_lines(voucher.line_dr_ids),'l') ]] [[ formatLang(l['date_due'] ,date=True) or '' ]] - - - [[ l['name'] ]] - - - [[ formatLang (l['amount_original']) ]] - - - [[ formatLang (l['amount_unreconciled']) ]] - - - - - - - - [[ formatLang (l['amount']) ]] - - - - - - - Check Amount - - - [[ formatLang (voucher.amount) ]] - - - - - - - - - - - - - - diff --git a/addons/account_check_writing/views/report_check.xml b/addons/account_check_writing/views/report_check.xml new file mode 100644 index 00000000000..d740de1a0a4 --- /dev/null +++ b/addons/account_check_writing/views/report_check.xml @@ -0,0 +1,48 @@ + + + + + + diff --git a/addons/account_followup/__openerp__.py b/addons/account_followup/__openerp__.py index dbb4ea6583e..61e9ea2d4ae 100644 --- a/addons/account_followup/__openerp__.py +++ b/addons/account_followup/__openerp__.py @@ -55,11 +55,12 @@ Note that if you want to check the follow-up level for a given partner/account e 'account_followup_view.xml', 'account_followup_customers.xml', 'wizard/account_followup_print_view.xml', + 'views/report_followup.xml', + 'account_followup_reports.xml' ], 'demo': ['account_followup_demo.xml'], 'test': [ 'test/account_followup.yml', - #TODO 'test/account_followup_report.yml', --> Need to wait for second step in order to check report (expects after first) ], 'installable': True, 'auto_install': False, diff --git a/addons/account_followup/account_followup.py b/addons/account_followup/account_followup.py index 9237282ad80..5f912b61b37 100644 --- a/addons/account_followup/account_followup.py +++ b/addons/account_followup/account_followup.py @@ -21,7 +21,7 @@ from openerp.osv import fields, osv from lxml import etree - +import openerp.tools as tools from openerp.tools.translate import _ class followup(osv.osv): @@ -189,11 +189,7 @@ class res_partner(osv.osv): 'model': 'account_followup.followup', 'form': data } - return { - 'type': 'ir.actions.report.xml', - 'report_name': 'account_followup.followup.print', - 'datas': datas, - } + return self.pool['report'].get_action(cr, uid, wizard_partner_ids, 'account_followup.report_followup', data=datas, context=context) def do_partner_mail(self, cr, uid, partner_ids, context=None): if context is None: @@ -247,8 +243,7 @@ class res_partner(osv.osv): if partner.unreconciled_aml_ids: company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id current_date = fields.date.context_today(self, cr, uid, context=context) - rml_parse = account_followup_print.report_rappel(cr, uid, "followup_rml_parser") - final_res = rml_parse._lines_get_with_partner(partner, company.id) + final_res = self.pool['report.account_followup.report_followup']._lines_get_with_partner(partner, company.id, cr=cr, uid=uid) for currency_dict in final_res: currency = currency_dict.get('line', [{'currency_id': company.currency_id}])[0]['currency_id'] @@ -274,7 +269,11 @@ class res_partner(osv.osv): strbegin = "" strend = "" followup_table +="" + strbegin + str(aml['date']) + strend + strbegin + aml['name'] + strend + strbegin + aml['ref'] + strend + strbegin + str(date) + strend + strbegin + str(aml['balance']) + strend + strbegin + block + strend + "" - total = rml_parse.formatLang(total, dp='Account', currency_obj=currency) + + total = reduce(lambda x, y: x+y['balance'], currency_dict['line'], 0.00) + + report_obj = self.pool.get('report') + total = report_obj.formatLang(total, dp='Account', currency_obj=currency, cr=cr, uid=uid) followup_table += '''
    ''' + _("Amount due") + ''' : %s
    ''' % (total) diff --git a/addons/account_followup/account_followup_reports.xml b/addons/account_followup/account_followup_reports.xml new file mode 100644 index 00000000000..16149a5fd47 --- /dev/null +++ b/addons/account_followup/account_followup_reports.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/addons/account_followup/account_followup_view.xml b/addons/account_followup/account_followup_view.xml index e233feb489e..57f71566db0 100644 --- a/addons/account_followup/account_followup_view.xml +++ b/addons/account_followup/account_followup_view.xml @@ -132,7 +132,6 @@ id="menu_manual_reconcile_followup"/> - account.move.line.partner.tree diff --git a/addons/account_followup/report/account_followup_print.rml b/addons/account_followup/report/account_followup_print.rml deleted file mode 100644 index 6eadaed8675..00000000000 --- a/addons/account_followup/report/account_followup_print.rml +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(ids_to_objects(data['form']['partner_ids']),'o') ]] - [[ setLang(o.partner_id.lang) ]] - - - - - - - [[ o.partner_id.name or '' ]] - [[ display_address(o.partner_id) or '']] - - - - VAT: [[ o.partner_id.vat or removeParentNode('para') ]] - - - - - - - Document : Customer account statement - Date : [[ formatLang(data['form']['date'],date=True) ]] - Customer Ref : [[ o.partner_id.ref or '' ]] - - - -
    [[ format(get_text(o,data['form']['followup_id'])) ]]
    - - - -
    - - - [[repeatIn(getLines(o), 'cur_lines') ]] - - - Invoice Date - - - Description - - - Ref - - - Maturity Date - - - Amount - - - Li. - - - - - - [[repeatIn(cur_lines['line'], 'line') ]] - - [[ formatLang(line['date'],date = True) ]] - - - [[ line['name'] ]] - - - [[ line['ref'] ]] - - - [[ line['date_maturity'] and formatLang(line['date_maturity'], date=True) ]] - - - [[ formatLang(line['balance'], currency_obj=line['currency_id']) ]] - - - [[ line['blocked'] and 'X' or '' ]] - - - - - - - - - - - - Total: - - - [[formatLang(reduce(lambda x,y: x+y['balance'], cur_lines['line'], 0.00), currency_obj=line['currency_id']) ]] - - - - - - - - - - - - - - - - - - - -
    - -
    -
    diff --git a/addons/account_followup/tests/test_account_followup.py b/addons/account_followup/tests/test_account_followup.py index 9e70430c518..b3025021278 100644 --- a/addons/account_followup/tests/test_account_followup.py +++ b/addons/account_followup/tests/test_account_followup.py @@ -59,7 +59,6 @@ class TestAccountFollowup(TransactionCase): self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id}) self.assertFalse(self.partner.browse(cr, uid, self.partner_id).latest_followup_level_id) - def run_wizard_three_times(self): cr, uid = self.cr, self.uid current_date = datetime.datetime.utcnow() @@ -131,7 +130,7 @@ class TestAccountFollowup(TransactionCase): self.run_wizard_three_times() self.assertEqual(self.partner.browse(cr, uid, self.partner_id).latest_followup_level_id.id, self.last_followup_line_id, "Lines are not equal") - + def test_06_pay_the_invoice(self): """Run wizard until manual action, pay the invoice and check that partner has no follow-up level anymore and after running the wizard the action is empty""" cr, uid = self.cr, self.uid @@ -148,7 +147,6 @@ class TestAccountFollowup(TransactionCase): 'followup_id': self.followup_id }, context={"followup_id": self.followup_id}) self.wizard.do_process(cr, uid, [self.wizard_id], context={"followup_id": self.followup_id}) - partner_ref = self.partner.browse(cr, uid, self.partner_id) self.assertEqual(0, self.partner.browse(cr, uid, self.partner_id).payment_amount_due, "Amount Due != 0") self.assertFalse(self.partner.browse(cr, uid, self.partner_id).payment_next_action_date, "Next action date not cleared") diff --git a/addons/account_followup/views/report_followup.xml b/addons/account_followup/views/report_followup.xml new file mode 100644 index 00000000000..6c79fe4cc55 --- /dev/null +++ b/addons/account_followup/views/report_followup.xml @@ -0,0 +1,58 @@ + + + + + + diff --git a/addons/account_payment/__openerp__.py b/addons/account_payment/__openerp__.py index 4c3c8f045e3..c5cccc38c26 100644 --- a/addons/account_payment/__openerp__.py +++ b/addons/account_payment/__openerp__.py @@ -54,6 +54,8 @@ have a new option to import payment orders as bank statement lines. 'account_payment_workflow.xml', 'account_payment_sequence.xml', 'account_payment_report.xml', + + 'views/report_paymentorder.xml', ], 'demo': ['account_payment_demo.xml'], 'test': [ diff --git a/addons/account_payment/account_payment_report.xml b/addons/account_payment/account_payment_report.xml index 699207e1733..3a57abe901f 100644 --- a/addons/account_payment/account_payment_report.xml +++ b/addons/account_payment/account_payment_report.xml @@ -1,6 +1,13 @@ - + diff --git a/addons/account_payment/report/order.rml b/addons/account_payment/report/order.rml deleted file mode 100644 index 02675baf0b2..00000000000 --- a/addons/account_payment/report/order.rml +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Partner - - - Bank Account - - - Invoice Ref - - - Value Date - - - Amount - - - Currency - - - - - [[ repeatIn(objects, 'o') ]] - - - - - - - - - - - - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.name or '']] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.street or '']] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.street2 or removeParentNode('para')]] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.zip or '']] [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.city or '']] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.state and o.mode.bank_id.bank.state.name or removeParentNode('para') ]] - [[ o.mode and o.mode.bank_id.bank and o.mode.bank_id.bank.country and o.mode.bank_id.bank.country.name or '']] - - - - - - - Payment Order / Payment - - - - - - - Payment Type - - - Reference - - - Used Account - - - Execution Type - - - Company Currency - - - - - - - [[ o.mode and o.mode.name or '-' ]] - - - [[ o.reference or '-' ]] - - - [[get_account_name(o.mode.bank_id.id)]] - - - [[ o.date_prefered == 'now' and 'Now' or removeParentNode('para') ]] - [[ o.date_prefered == 'due' and 'Due date' or removeParentNode('para') ]] - [[ o.date_prefered == 'fixed' and 'Fixed date' or removeParentNode('para') ]] - - - [[ o.user_id and o.user_id.company_id and o.user_id.company_id.currency_id and o.user_id.company_id.currency_id.name or '' ]] - - - - - - - - - - Partner - - - Bank Account - - - Invoice Ref - - - Value Date - - - Amount - - - Currency - - - -
    - [[repeatIn(o.line_ids, 'line') ]] - - - - [[line.partner_id and line.partner_id.name or '-' ]] - - - [[get_account_name(line.bank_id.id) or '-']] - - - [[ get_invoice_name(line.ml_inv_ref.id) or '-' ]] - - - [[not line.date and '-' or formatLang(line.date,date=True) ]] - - - [[ formatLang(line.amount or 0.0, currency_obj=line.company_currency) ]] - - - [[ formatLang(line.amount_currency, currency_obj=line.currency) ]] - - - -
    - - - - - - - - - Total: - - - [[ formatLang(get_amount_total(o), currency_obj=o.company_id.currency_id) or '' ]] - - - [[ formatLang(get_amount_total_in_currency(o), currency_obj=(o.line_ids and o.line_ids[0].currency or None)) or '' ]] - - - - - - -
    -
    -
    diff --git a/addons/account_payment/views/report_paymentorder.xml b/addons/account_payment/views/report_paymentorder.xml new file mode 100644 index 00000000000..c2662b6aa77 --- /dev/null +++ b/addons/account_payment/views/report_paymentorder.xml @@ -0,0 +1,104 @@ + + + + + + diff --git a/addons/account_test/__openerp__.py b/addons/account_test/__openerp__.py index cfd4007fed0..51b47bace7a 100644 --- a/addons/account_test/__openerp__.py +++ b/addons/account_test/__openerp__.py @@ -19,11 +19,12 @@ # along with this program. If not, see . # ############################################################################## + { - 'name' : 'Accounting Consistency Tests', - 'version' : '1.0', - 'author' : 'OpenERP', - 'category' : 'Accounting & Finance', + 'name': 'Accounting Consistency Tests', + 'version': '1.0', + 'author': 'OpenERP', + 'category': 'Accounting & Finance', 'website': 'http://www.openerp.com', 'description': """ Asserts on accounting. @@ -34,14 +35,16 @@ You can write a query in order to create Consistency Test and you will get the r in PDF format which can be accessed by Menu Reporting -> Accounting Tests, then select the test and print the report from Print button in header area. """, - 'depends' : ['account'], - 'data' : [ + 'depends': ['account'], + 'data': [ 'security/ir.model.access.csv', 'account_test_view.xml', 'account_test_report.xml', 'account_test_data.xml', + 'views/report_accounttest.xml', ], 'active': False, 'installable': True } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_test/account_test_report.xml b/addons/account_test/account_test_report.xml index 480507b6072..732b9e9fbdb 100644 --- a/addons/account_test/account_test_report.xml +++ b/addons/account_test/account_test_report.xml @@ -1,14 +1,13 @@ - - - - - + + + diff --git a/addons/account_test/report/account_test.rml b/addons/account_test/report/account_test.rml deleted file mode 100644 index 1efa12fd5cb..00000000000 --- a/addons/account_test/report/account_test.rml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Accouting tests on [[ datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") ]] - - - -
    - [[repeatIn(objects,'o')]] - - - - [[ o.name ]] - - - - - [[ o.desc or '' ]] - - - - - - - [[ repeatIn(execute_code(o.code_exec), 'test_result') ]] - [[ test_result ]] - - - - - - -
    - -
    -
    diff --git a/addons/account_test/views/report_accounttest.xml b/addons/account_test/views/report_accounttest.xml new file mode 100644 index 00000000000..02ce82218dc --- /dev/null +++ b/addons/account_test/views/report_accounttest.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/addons/account_voucher/__openerp__.py b/addons/account_voucher/__openerp__.py index 0659e4f4bae..6a3b0ee81cd 100644 --- a/addons/account_voucher/__openerp__.py +++ b/addons/account_voucher/__openerp__.py @@ -49,7 +49,6 @@ This module manages: 'security/ir.model.access.csv', 'account_voucher_sequence.xml', 'account_voucher_workflow.xml', - 'account_voucher_report.xml', 'wizard/account_statement_from_invoice_view.xml', 'account_voucher_view.xml', 'voucher_payment_receipt_view.xml', @@ -59,6 +58,7 @@ This module manages: 'report/account_voucher_sales_receipt_view.xml', 'security/account_voucher_security.xml', 'account_voucher_data.xml', + 'account_voucher_report.xml', ], 'test' : [ 'test/account_voucher_users.yml', @@ -66,7 +66,6 @@ This module manages: 'test/account_voucher.yml', 'test/sales_receipt.yml', 'test/sales_payment.yml', - 'test/account_voucher_report.yml', 'test/case1_usd_usd.yml', 'test/case1_usd_usd_payment_rate.yml', 'test/case2_usd_eur_debtor_in_eur.yml', @@ -74,6 +73,7 @@ This module manages: 'test/case3_eur_eur.yml', 'test/case4_cad_chf.yml', 'test/case_eur_usd.yml', + 'account_voucher_report.yml', ], 'auto_install': False, 'application': True, diff --git a/addons/account_voucher/report/account_voucher.rml b/addons/account_voucher/report/account_voucher.rml deleted file mode 100644 index 6b3337aa64f..00000000000 --- a/addons/account_voucher/report/account_voucher.rml +++ /dev/null @@ -1,446 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'voucher') ]] - - - - [[ get_title(voucher.type) ]] - - - - - - - - - - Journal: - - - [[ voucher.type ]] - - - Number: - - - [[ voucher.number ]] - - - - - - - Status: - - - PRO-FORMA [[ ((voucher.state == 'proforma') or removeParentNode('para')) and '' ]] - Draft[[ ((voucher.state == 'draft') or removeParentNode('para')) and '' ]] - Canceled [[ ((voucher.state == 'cancel') or removeParentNode('para')) and '' ]] - Posted [[ ((voucher.state == 'posted') or removeParentNode('para')) and '' ]] - - - Ref. : - - - [[ voucher.reference or '' ]] - - - Date: - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - - - - - - - - Particulars - - - Debit - - - Credit - - - - - - -
    - [[ repeatIn(voucher.move_ids,'move_ids') ]] - - - - [[ (move_ids.partner_id and move_ids.partner_id.name) or 'Account']] - - - [[ formatLang(move_ids.debit) ]] - - - [[ formatLang(move_ids.credit) ]] - - - - - [[ move_ids.account_id.name ]] - - - - - - - - - - - - - - - [[ move_ids.name ]] - [[ get_ref(voucher.id,move_ids) ]] - - - - - - - - - - - - - - - - -
    - - - - - - - Through : - - - - - - - - - - - - - - - [[ voucher.narration or '']] - - - - - - - - - - - - - - - On Account of : - - - - - - - - - - - - - - - [[ voucher.name ]] - - - - - - - - - - - - - - - Amount (in words) : - - - - - - - - - - - - - - - [[ convert(voucher.amount,voucher.currency_id.name) ]] - - - - - - - - - - - - - - - - - - - - - - - - - [[ debit(voucher.move_ids)]] - - - [[ credit(voucher.move_ids) ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Receiver's Signature - - - - - - - - - - - - - Authorised Signatory - - - - - - -
    -
    diff --git a/addons/account_voucher/report/account_voucher_print.rml b/addons/account_voucher/report/account_voucher_print.rml deleted file mode 100644 index 9f0f2e1f07e..00000000000 --- a/addons/account_voucher/report/account_voucher_print.rml +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'voucher') ]] - - - - [[ get_title(voucher.type) ]] - - - - - - - - - - Number: - - - [[ voucher.number ]] - - - - - - - - - - - - - Date: - - - [[ formatLang(voucher.date , date=True) or '' ]] - - - - - - - Status: - - - PRO-FORMA [[ ((voucher.state == 'proforma') or removeParentNode('para')) and '' ]] - Draft[[ ((voucher.state == 'draft') or removeParentNode('para')) and '' ]] - Canceled [[ ((voucher.state == 'cancel') or removeParentNode('para')) and '' ]] - Posted [[ ((voucher.state == 'posted') or removeParentNode('para')) and '' ]] - - - - - - - - - - - - - Currency: - - - [[ voucher.currency_id.symbol ]] - - - - - - - - - - Particulars - - - Amount - - - - - - -
    - [[ repeatIn(get_lines(voucher),'p') ]] - - - - Account : - - - - - - - - - - [[ p['pname'] ]] - - - [[ formatLang(p['amount'], currency_obj=voucher.currency_id) ]] - - - - - [[ p['ref'] ]] - - - - - - - - - - Account : [[ p['aname'] ]] - - - - - - - - - - - -
    - - - - - - - Through : - - - - - - - - - - [[ voucher.journal_id.name or '' ]] - - - - - - - - - - On Account of : - - - - - - - - - - [[ get_on_account(voucher) ]] - - - - - - - - - - Amount (in words) : - - - - - - - - - - [[ convert(voucher.amount,voucher.currency_id.name) ]] - - - - - - - - - - - - - - - - - - - - [[ formatLang(voucher.amount, currency_obj=voucher.currency_id) ]] - - - -
    -
    diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py index 5cff7b4aae2..f8435ba8245 100644 --- a/addons/report/controllers/main.py +++ b/addons/report/controllers/main.py @@ -143,12 +143,17 @@ class ReportController(Controller): elif value.lower() == 'true': param[key] = True elif ',' in value: - param[key] = [int(i) for i in value.split(',')] + try: + param[key] = [int(i) for i in value.split(',')] + except ValueError: + param[key] = value.split(',') + if len(param[key]) == 1: + param[key] = value else: try: param[key] = int(value) except (ValueError, TypeError): - pass + continue else: if isinstance(param, (str, unicode)): param = [int(i) for i in param.split(',')] diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 8abe8e544eb..b93bbe09f89 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -74,7 +74,7 @@ class Report(osv.Model): # Extension of ir_ui_view.render with arguments frequently used in reports #-------------------------------------------------------------------------- - def _get_digits(self, cr, uid, obj=None, f=None, dp=None): + def _get_digits(self, cr=None, uid=None, obj=None, f=None, dp=None): d = DEFAULT_DIGITS = 2 if dp: decimal_precision_obj = self.pool['decimal.precision'] @@ -118,6 +118,14 @@ class Report(osv.Model): def get_date_length(date_format=DEFAULT_SERVER_DATE_FORMAT): return len((datetime.now()).strftime(date_format)) + # In case we use formatLang on the model (and not in the rendering environment). + if not hasattr(self, 'land_ditct'): + self.localcontext = {} + self.lang_dict = {} + self.default_lang = {} + self._get_lang_dict(cr, uid) + self.lang_dict_called = True + if digits is None: if dp: digits = self._get_digits(cr, uid, dp=dp) @@ -212,7 +220,7 @@ class Report(osv.Model): values.update({ 'time': time, 'formatLang': partial(self.formatLang, cr=cr, uid=uid), - 'get_digits': self._get_digits, + 'get_digits': partial(self._get_digits, cr=cr, uid=uid), 'render_doc': render_doc, 'editable': True, # Will active inherit_branding 'res_company': self.pool['res.users'].browse(cr, uid, uid).company_id, @@ -377,7 +385,7 @@ class Report(osv.Model): ) return pdf - def get_action(self, cr, uid, ids, report_name, datas=None, context=None): + def get_action(self, cr, uid, ids, report_name, data=None, context=None): """Return an action of type ir.actions.report.xml. :param report_name: Name of the template to generate an action for @@ -386,8 +394,8 @@ class Report(osv.Model): if context is None: context = {} - if datas is None: - datas = {} + if data is None: + data = {} report_obj = self.pool.get('ir.actions.report.xml') idreport = report_obj.search(cr, uid, [('report_name', '=', report_name)], context=context) @@ -405,8 +413,8 @@ class Report(osv.Model): 'report_file': report.report_file, } - if datas: - action['datas'] = datas + if data: + action['datas'] = data return action @@ -566,8 +574,8 @@ class Report(osv.Model): command_args.extend(['--page-size', paperformat.format]) if paperformat.page_height and paperformat.page_width and paperformat.format == 'custom': - command_args.extend(['--page-width', str(paperformat.page_width) + 'in']) - command_args.extend(['--page-height', str(paperformat.page_height) + 'in']) + command_args.extend(['--page-width', str(paperformat.page_width) + 'mm']) + command_args.extend(['--page-height', str(paperformat.page_height) + 'mm']) if specific_paperformat_args and specific_paperformat_args['data-report-margin-top']: command_args.extend(['--margin-top', diff --git a/addons/report/models/report_paperformat.py b/addons/report/models/report_paperformat.py index e3e747b81a4..6b84f3d3363 100644 --- a/addons/report/models/report_paperformat.py +++ b/addons/report/models/report_paperformat.py @@ -69,8 +69,8 @@ class report_paperformat(osv.Model): 'margin_bottom': fields.integer('Bottom Margin (mm)'), 'margin_left': fields.integer('Left Margin (mm)'), 'margin_right': fields.integer('Right Margin (mm)'), - 'page_height': fields.integer('Page height (in)'), - 'page_width': fields.integer('Page width (in)'), + 'page_height': fields.integer('Page height (mm)'), + 'page_width': fields.integer('Page width (mm)'), 'orientation': fields.selection([('Landscape', 'Landscape'), ('Portrait', 'Portrait')], 'Orientation'), diff --git a/addons/report/views/layouts.xml b/addons/report/views/layouts.xml index 588775fc41e..721176738cb 100644 --- a/addons/report/views/layouts.xml +++ b/addons/report/views/layouts.xml @@ -6,7 +6,10 @@ + t-att-data-main-object="repr(main_object) if editable else None" + t-att-data-report-margin-top="data_report_margin_top if data_report_margin_top else None" + t-att-data-report-header-spacing="data_report_header_spacing if t_att_data_report_header_spacing else None" + t-att-data-report-dpi="data_report_dpi if data_report_dpi else None"> @@ -158,5 +161,6 @@
    + diff --git a/addons/report_intrastat/__init__.py b/addons/report_intrastat/__init__.py index d2f598434a2..119777f2c70 100644 --- a/addons/report_intrastat/__init__.py +++ b/addons/report_intrastat/__init__.py @@ -20,7 +20,5 @@ ############################################################################## import report_intrastat -import report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/report_intrastat/__openerp__.py b/addons/report_intrastat/__openerp__.py index 0fa57977db1..4682a777ccc 100644 --- a/addons/report_intrastat/__openerp__.py +++ b/addons/report_intrastat/__openerp__.py @@ -19,7 +19,6 @@ # ############################################################################## - { 'name': 'Intrastat Reporting', 'version': '1.0', @@ -37,7 +36,8 @@ European Union.""", 'security/ir.model.access.csv', 'report_intrastat_view.xml', 'intrastat_report.xml', - 'report_intrastat_data.xml' + 'report_intrastat_data.xml', + 'views/report_intrastatinvoice.xml' ], 'demo': [], 'test': ['test/report_intrastat_report.yml'], @@ -45,4 +45,5 @@ European Union.""", 'auto_install': False, 'images': ['images/country_intrastat_code.jpeg','images/intrastat_code.jpeg'], } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/intrastat_report.xml b/addons/report_intrastat/intrastat_report.xml index 124cf899efb..c5a8e9e7f84 100644 --- a/addons/report_intrastat/intrastat_report.xml +++ b/addons/report_intrastat/intrastat_report.xml @@ -1,13 +1,13 @@ - - - + + + - - diff --git a/addons/report_intrastat/report/__init__.py b/addons/report_intrastat/report/__init__.py deleted file mode 100644 index 64e530bc278..00000000000 --- a/addons/report_intrastat/report/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## -import invoice -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/report/invoice.py b/addons/report_intrastat/report/invoice.py deleted file mode 100644 index c38a62774ac..00000000000 --- a/addons/report_intrastat/report/invoice.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -import time -from openerp.report import report_sxw - -class account_invoice_intrastat(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(account_invoice_intrastat, self).__init__(cr, uid, name, context=context) - self.total=0 - self.localcontext.update({ - 'time': time, - }) - -report_sxw.report_sxw('report.account.invoice.intrastat', 'account.invoice', 'addons/report_intrastat/report/invoice.rml', parser=account_invoice_intrastat) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/report/invoice.rml b/addons/report_intrastat/report/invoice.rml deleted file mode 100644 index fc410e04ce0..00000000000 --- a/addons/report_intrastat/report/invoice.rml +++ /dev/null @@ -1,401 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [[ repeatIn(objects,'o') ]] - [[ setLang(o.partner_id.lang) ]] - - - - - - - - - [[ (o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]] - [[ o.partner_id and display_address(o.partner_id) ]] - - - - Tel. : [[ (o.partner_id.phone) or removeParentNode('para') ]] - Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]] - VAT : [[ (o.partner_id.vat) or removeParentNode('para') ]] - - - - Invoice [[ ((o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')) or removeParentNode('para')) and '' ]] [[ o.number ]] - PRO-FORMA [[ ((o.type == 'out_invoice' and o.state == 'proforma2') or removeParentNode('para')) and '' ]] - Draft Invoice [[ ((o.type == 'out_invoice' and o.state == 'draft') or removeParentNode('para')) and '' ]] - Cancelled Invoice [[ ((o.type == 'out_invoice' and o.state == 'cancel') or removeParentNode('para')) and '' ]] [[ o.number ]] - Refund [[ (o.type=='out_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Refund [[ (o.type=='in_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] - Supplier Invoice [[ (o.type=='in_invoice' or removeParentNode('para')) and '' ]] [[ o.number ]] - - - - - - - Document - - - Invoice Date - - - Partner Ref. - - - - - - - [[ o.name or ' ' ]] - - - [[ formatLang(o.date_invoice,date=True) ]] - - - [[ (o.partner_id.ref) or ' ' ]] - - - - - - - - - - Description - - - Taxes - - - Intrastat - - - Weight - - - Quantity - - - Unit Price - - - Disc. (%) - - - Price - - - -
    - [[ repeatIn(o.invoice_line,'l') ]] - - - - [[ l.name ]] - - - [[ ', '.join([lt.name for lt in l.invoice_line_tax_id]) ]] - - - [[l.product_id and l.product_id.intrastat_id and l.product_id.intrastat_id.name or '']] - - - [[ l.product_id and l.product_id.weight or '']] - - - [[ formatLang(l.quantity) ]] [[ (l.uos_id and l.uos_id.name) or '' ]] - - - [[ formatLang(l.price_unit) ]] - - - [[ l.discount and formatLang (l.discount) or '' ]] - - - [[ formatLang(l.price_subtotal, currency_obj=o.currency_id) ]] - - - - - [[ format(l.note or removeParentNode('tr')) ]] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - - - - - - - - Total (excl. taxes): - - - [[ formatLang(o.amount_untaxed, currency_obj=o.currency_id) ]] - - - - - - - - - - Taxes: - - - [[ formatLang(o.amount_tax, currency_obj=o.currency_id) ]] - - - - - - - - - - Total (inclu. taxes): - - - [[ formatLang(o.amount_total, currency_obj=o.currency_id) ]] - - - - - - - - - - Tax [[ o.tax_line==[] and removeParentNode('blockTable') ]] - - - Base - - - Amount - - - - - - - - -
    - [[ repeatIn(o.tax_line,'t') ]] - - - - [[ t.name ]] - - - [[ formatLang(t.base, digits=get_digits(dp='Account'), currency_obj = o.currency_id) ]] - - - [[ (t.tax_code_id and t.tax_code_id.notprintable) and removeParentNode('blockTable') or '' ]] [[ formatLang(t.amount, digits=get_digits(dp='Account'), currency_obj=o.currency_id) ]] - - - - - - - - -
    - - - - [[ (o.comment and format(o.comment )) or removeParentNode('para') ]] - - - - [[ (o.payment_term and o.payment_term.note and format(o.payment_term and o.payment_term.note)) or removeParentNode('para') ]] - - - - - - - Fiscal Position Remark : - - - [[ (o.fiscal_position and o.fiscal_position.note and format(o.fiscal_position.note)) or removeParentNode('blockTable') ]] - - - - - - -
    -
    diff --git a/addons/report_intrastat/views/report_intrastatinvoice.xml b/addons/report_intrastat/views/report_intrastatinvoice.xml new file mode 100644 index 00000000000..e8bce6e952d --- /dev/null +++ b/addons/report_intrastat/views/report_intrastatinvoice.xml @@ -0,0 +1,149 @@ + + + + + + + + From 9379dc0312ef4597e72d6429079791c02a6884ab Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 28 Mar 2014 15:23:09 +0100 Subject: [PATCH 018/140] [FIX] chrome.js: detect correct error type for session expired bzr revid: odo@openerp.com-20140328142309-apraiq42f3xavqda --- addons/web/static/src/js/chrome.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index 19981069cd9..add30866111 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -256,7 +256,7 @@ instance.web.CrashManager = instance.web.Class.extend({ new (handler)(this, error).display(); return; } - if (error.data.name === "openerp.http.SessionExpiredException") { + if (error.data.name === "openerp.http.SessionExpiredException" || error.data.name === "werkzeug.exceptions.Forbidden") { this.show_warning({type: "Session Expired", data: { message: _t("Your OpenERP session expired. Please refresh the current web page.") }}); return; } From 8809c77f6088c140355fba5f862c0335b1d90c4e Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Fri, 28 Mar 2014 15:27:48 +0100 Subject: [PATCH 019/140] [FIX] http,ir.http: refactor exception handling to allow request-specific handling Typically an exception during a JSON-RPC request must be handled specifically and return a JSON-RPC error in all cases. Previously the _authenticate() step could fail during ir_http.dispatch() and bubble up to werkzeug, yielding a dumb "Internal Server Error 500" even for a JSON-RPC request. bzr revid: odo@openerp.com-20140328142748-00haplmkc3fv6f9y --- openerp/addons/base/ir/ir_http.py | 4 +- openerp/http.py | 79 ++++++++++++++++++------------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/openerp/addons/base/ir/ir_http.py b/openerp/addons/base/ir/ir_http.py index 93dc4d84e76..bd211d14cb8 100644 --- a/openerp/addons/base/ir/ir_http.py +++ b/openerp/addons/base/ir/ir_http.py @@ -85,8 +85,8 @@ class ir_http(osv.AbstractModel): return auth_method def _handle_exception(self, exception): - # If handle exception return something different than None, it will be used as a response - raise + # If handle_exception returns something different than None, it will be used as a response + return request._handle_exception(exception) def _dispatch(self): # locate the controller method diff --git a/openerp/http.py b/openerp/http.py index 61c90929aa2..24f538f3828 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -202,6 +202,13 @@ class WebRequest(object): self.func_arguments = arguments self.auth_method = auth + + def _handle_exception(self, exception): + """Called within an except block to allow converting exceptions + to abitrary responses. Anything returned (except None) will + be used as response.""" + raise + def _call_function(self, *args, **kwargs): request = self if self.func_request_type != self._request_type: @@ -338,37 +345,15 @@ class JsonRequest(WebRequest): self.params = dict(self.jsonrequest.get("params", {})) self.context = self.params.pop('context', dict(self.session.context)) - def dispatch(self): - """ Calls the method asked for by the JSON-RPC2 or JSONP request - """ - if self.jsonp_handler: - return self.jsonp_handler() - response = {"jsonrpc": "2.0" } - error = None - - try: - response['id'] = self.jsonrequest.get('id') - response["result"] = self._call_function(**self.params) - except AuthenticationError, e: - _logger.exception("Exception during JSON request handling.") - se = serialize_exception(e) - error = { - 'code': 100, - 'message': "OpenERP Session Invalid", - 'data': se - } - self._failed = e # prevent tx commit - except Exception, e: - _logger.exception("Exception during JSON request handling.") - se = serialize_exception(e) - error = { - 'code': 200, - 'message': "OpenERP Server Error", - 'data': se - } - self._failed = e # prevent tx commit - if error: - response["error"] = error + def _json_response(self, result=None, error=None): + response = { + 'jsonrpc': '2.0', + 'id': self.jsonrequest.get('id') + } + if error is not None: + response['error'] = error + if result is not None: + response['result'] = result if self.jsonp: # If we use jsonp, that's mean we are called from another host @@ -381,8 +366,36 @@ class JsonRequest(WebRequest): mime = 'application/json' body = simplejson.dumps(response) - r = werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))]) - return r + return werkzeug.wrappers.Response( + body, headers=[('Content-Type', mime), + ('Content-Length', len(body))]) + + def _handle_exception(self, exception): + """Called within an except block to allow converting exceptions + to abitrary responses. Anything returned (except None) will + be used as response.""" + _logger.exception("Exception during JSON request handling.") + self._failed = exception # prevent tx commit + error = { + 'code': 200, + 'message': "OpenERP Server Error", + 'data': serialize_exception(exception) + } + if isinstance(exception, AuthenticationError): + error['code'] = 100 + error['message'] = "OpenERP Session Invalid" + return self._json_response(error=error) + + def dispatch(self): + """ Calls the method asked for by the JSON-RPC2 or JSONP request + """ + if self.jsonp_handler: + return self.jsonp_handler() + try: + result = self._call_function(**self.params) + return self._json_response(result) + except Exception, e: + return self._handle_exception(e) def serialize_exception(e): tmp = { From 2d0d19849848dfe8c4988e6bab5200dd4bb815e4 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Fri, 28 Mar 2014 16:47:04 +0100 Subject: [PATCH 020/140] [TYPO] Remove duplicated field "supplier" from view view_partner_form bzr revid: jke@openerp.com-20140328154704-88nph9tlkd48kd1y --- openerp/addons/base/res/res_partner_view.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index a0e32ab83bd..5880b91e259 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -287,7 +287,6 @@
    - From 37c469c5cd4f49c4f816db190caf6e64b19a4222 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Sat, 29 Mar 2014 15:41:46 +0100 Subject: [PATCH 021/140] [FIX] hw_{scanner,escpos}: ensure we always release the lock. [FIX] hw_scanner: mark the thread as deamon. bzr revid: chs@openerp.com-20140329144146-utr8gexna4un65u1 --- addons/hw_escpos/controllers/main.py | 9 ++++----- addons/hw_scanner/controllers/main.py | 8 ++++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/addons/hw_escpos/controllers/main.py b/addons/hw_escpos/controllers/main.py index 58c02ebf59f..886b3a96431 100644 --- a/addons/hw_escpos/controllers/main.py +++ b/addons/hw_escpos/controllers/main.py @@ -51,11 +51,10 @@ class EscposDriver(Thread): return connected def lockedstart(self): - self.lock.acquire() - if not self.isAlive(): - self.daemon = True - self.start() - self.lock.release() + with self.lock: + if not self.isAlive(): + self.daemon = True + self.start() def get_escpos_printer(self): try: diff --git a/addons/hw_scanner/controllers/main.py b/addons/hw_scanner/controllers/main.py index 8fbdae62db6..5c9cb50e906 100644 --- a/addons/hw_scanner/controllers/main.py +++ b/addons/hw_scanner/controllers/main.py @@ -88,10 +88,10 @@ class Scanner(Thread): } def lockedstart(self): - self.lock.acquire() - if not self.isAlive(): - self.start() - self.lock.release() + with self.lock: + if not self.isAlive(): + self.daemon = True + self.start() def set_status(self, status, message = None): if status == self.status['status']: From ad2984f5640d59124fadcfd1b33f9c6429f0d4bd Mon Sep 17 00:00:00 2001 From: "Darshan Kalola (OpenERP)" Date: Mon, 31 Mar 2014 13:01:00 +0530 Subject: [PATCH 022/140] [IMP]disabled dropdown button when there is no item in dropdown. bzr revid: dka@tinyerp.com-20140331073100-qexuumfnynssfto1 --- addons/mail/static/src/js/mail_followers.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 955049f2e25..04f01efb8af 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -255,7 +255,13 @@ openerp_mail_followers = function(session, mail) { dialog = true; } else { var subtype_list_ul = this.$('.oe_subtype_list ul').empty(); - if (! this.message_is_follower) return; + if (! this.message_is_follower) { + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true); + return; + } + else { + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false); + } } var id = this.view.datarecord.id; this.ds_model.call('message_get_subscription_data', [[id], user_pid, new session.web.CompoundContext(this.build_context(), {})]) @@ -291,6 +297,7 @@ openerp_mail_followers = function(session, mail) { do_follow: function () { var context = new session.web.CompoundContext(this.build_context(), {}); + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', false); this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context]) .then(this.proxy('read_value')); @@ -306,6 +313,7 @@ openerp_mail_followers = function(session, mail) { $(record).attr('checked',false); }); var action_unsubscribe = 'message_unsubscribe_users'; + this.$('.oe_subtype_list > .dropdown-toggle').attr('disabled', true); var follower_ids = [this.session.uid]; if (user_pid) { action_unsubscribe = 'message_unsubscribe'; From 328ea1762504507fcdf2860be721d532ad2eb28f Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Tue, 1 Apr 2014 11:22:54 +0200 Subject: [PATCH 023/140] [REVERT] rev. 5097 jke@openerp.com-20140328154704-88nph9tlkd48kd1y: This field has been removed from the view because was suspected to be twice included in the view, while it isnt, this is a form view inside an other formview bzr revid: dle@openerp.com-20140401092254-tyu2040tf90ijc49 --- openerp/addons/base/res/res_partner_view.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index 5880b91e259..a0e32ab83bd 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -287,6 +287,7 @@ + From c65ae9f055e33199fc5369da4cc0f4d605f4bc1a Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 1 Apr 2014 11:45:56 +0200 Subject: [PATCH 024/140] [FIX] rml2pdf : fix loading of font where mode are not strict. Now we compare always a lower and with serveral mode similar. That fix the usage of some font in report where accent and bold was ignored bzr revid: jke@openerp.com-20140401094556-h1ybpqf989qt5h60 --- openerp/report/render/rml2pdf/trml2pdf.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index 21a20031a04..87ec7fae3ef 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -283,6 +283,9 @@ class _rml_doc(object): from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont + if mode: + mode = mode.lower() + if fontname not in pdfmetrics._fonts: pdfmetrics.registerFont(TTFont(fontname, filename)) if mode == 'all': @@ -290,14 +293,14 @@ class _rml_doc(object): addMapping(face, 0, 1, fontname) #italic addMapping(face, 1, 0, fontname) #bold addMapping(face, 1, 1, fontname) #italic and bold - elif (mode== 'normal') or (mode == 'regular') or (mode == 'book'): - addMapping(face, 0, 0, fontname) #normal - elif mode == 'italic': + elif mode in ['italic', 'oblique']: addMapping(face, 0, 1, fontname) #italic elif mode == 'bold': addMapping(face, 1, 0, fontname) #bold - elif mode == 'bolditalic': + elif mode in ('bolditalic', 'bold italic','boldoblique', 'bold oblique'): addMapping(face, 1, 1, fontname) #italic and bold + else: + addMapping(face, 0, 0, fontname) #normal def _textual_image(self, node): rc = '' From 43beb0e75294a8a321c791840a26830b3f05a7c0 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Tue, 1 Apr 2014 17:31:14 +0200 Subject: [PATCH 025/140] [FIX] ir_qweb groups: in order to compute the groups of a user, we are using cr and uid from request. In case we are rendering the template in a non-request context (for instance, automated tests), we have no cr and uid ; do not compute the user groups in this case. bzr revid: sle@openerp.com-20140401153114-blxgbyp8zgx120r3 --- openerp/addons/base/ir/ir_qweb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index f19a1fa6746..84551186f05 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -241,7 +241,7 @@ class QWeb(orm.AbstractModel): if attribute_name == "groups": cr = qwebcontext.get('request') and qwebcontext['request'].cr or None uid = qwebcontext.get('request') and qwebcontext['request'].uid or None - can_see = self.user_has_groups(cr, uid, groups=attribute_value) + can_see = self.user_has_groups(cr, uid, groups=attribute_value) if cr and uid else False if not can_see: return '' continue From c8aa0cc7f15c28c0aa1132e74fc676a45177fb5a Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Tue, 1 Apr 2014 17:33:39 +0200 Subject: [PATCH 026/140] [FIX] Adapted the render_report and try_report_action methods used in yml test to work with qweb reports bzr revid: sle@openerp.com-20140401153339-3n0xw5whx82uu0pu --- openerp/addons/base/ir/ir_actions.py | 10 ++++++++-- openerp/tools/test_reports.py | 17 +++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 4cd0492d95c..61c7a1d525b 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -104,7 +104,9 @@ class ir_actions_report_xml(osv.osv): cr.execute("SELECT * FROM ir_act_report_xml WHERE report_name=%s", (name,)) r = cr.dictfetchone() if r: - if r['report_rml'] or r['report_rml_content_data']: + if r['report_type'] in ['qweb-pdf', 'qweb-html']: + return r['report_name'] + elif r['report_rml'] or r['report_rml_content_data']: if r['parser']: kwargs = { 'parser': operator.attrgetter(r['parser'])(openerp.addons) } else: @@ -127,7 +129,11 @@ class ir_actions_report_xml(osv.osv): Look up a report definition and render the report for the provided IDs. """ new_report = self._lookup_report(cr, name) - return new_report.create(cr, uid, res_ids, data, context) + # in order to use current yml test files with qweb reports + if isinstance(new_report, (str, unicode)): + return self.pool['report'].get_pdf(cr, uid, res_ids, new_report, data=data, context=context), 'pdf' + else: + return new_report.create(cr, uid, res_ids, data, context) _name = 'ir.actions.report.xml' _inherit = 'ir.actions.actions' diff --git a/openerp/tools/test_reports.py b/openerp/tools/test_reports.py index 874a8cced61..9aa55233a27 100644 --- a/openerp/tools/test_reports.py +++ b/openerp/tools/test_reports.py @@ -114,7 +114,6 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, Eg. 'OK' or 'gtk-print' :param our_module: the name of the calling module (string), like 'account' """ - if not our_module and isinstance(action_id, basestring): if '.' in action_id: our_module = action_id.split('.', 1)[0] @@ -161,7 +160,10 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, # Updating the context : Adding the context of action in order to use it on Views called from buttons if datas.get('id',False): context.update( {'active_id': datas.get('id',False), 'active_ids': datas.get('ids',[]), 'active_model': datas.get('model',False)}) - context.update(safe_eval(action.get('context','{}'), context.copy())) + context1 = action.get('context', {}) + if isinstance(context1, basestring): + context1 = safe_eval(context1, context.copy()) + context.update(context1) if action['type'] in ['ir.actions.act_window', 'ir.actions.submenu']: for key in ('res_id', 'res_model', 'view_type', 'view_mode', 'limit', 'auto_refresh', 'search_view', 'auto_search', 'search_view_id'): @@ -272,12 +274,17 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, if 'window' in datas: del datas['window'] if not datas: - datas = action.get('datas',{}) + datas = action.get('datas') + if not datas: + datas = action.get('data') datas = datas.copy() ids = datas.get('ids') if 'ids' in datas: del datas['ids'] - res = try_report(cr, uid, 'report.'+action['report_name'], ids, datas, context, our_module=our_module) + if action.get('report_type') in ['qweb-pdf', 'qweb-html']: + res = registry['report'].get_html(cr, uid, [], action.get('report_name'), data=datas, context=context) + else: + res = try_report(cr, uid, 'report.'+action['report_name'], ids, datas, context, our_module=our_module) return res else: raise Exception("Cannot handle action of type %s" % act_model) @@ -303,6 +310,4 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, return True -#eof - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 11af46b2b13bd3c2c3f343b005c391cdb40a8665 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 1 Apr 2014 17:44:17 +0200 Subject: [PATCH 027/140] [FIX] resize_image: auto convert BMP images to PNG bzr revid: chs@openerp.com-20140401154417-c8buuqybdsihn3om --- openerp/tools/image.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openerp/tools/image.py b/openerp/tools/image.py index 08c2fd91f21..93458fb9408 100644 --- a/openerp/tools/image.py +++ b/openerp/tools/image.py @@ -70,7 +70,11 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file image_stream = StringIO.StringIO(base64_source.decode(encoding)) image = Image.open(image_stream) # store filetype here, as Image.new below will lose image.format - filetype = filetype or image.format + filetype = (filetype or image.format).upper() + + filetype = { + 'BMP': 'PNG', + }.get(filetype, filetype) asked_width, asked_height = size if asked_width is None: From f22169ebfb3ba1c76cfd2685299f756948648afa Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 11:37:21 +0200 Subject: [PATCH 028/140] [FIX] website_mail: overwritten _search method created domains syntactically not correct + security rule was applied on superuser bzr revid: dle@openerp.com-20140402093721-hwcdwltbkict4oz4 --- addons/website_mail/models/mail_message.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/addons/website_mail/models/mail_message.py b/addons/website_mail/models/mail_message.py index 12c35f3e83f..e9e06794523 100644 --- a/addons/website_mail/models/mail_message.py +++ b/addons/website_mail/models/mail_message.py @@ -19,9 +19,9 @@ # ############################################################################## +from openerp import SUPERUSER_ID from openerp.tools.translate import _ -from openerp.osv import osv, fields - +from openerp.osv import osv, fields, expression class MailMessage(osv.Model): _inherit = 'mail.message' @@ -48,10 +48,11 @@ class MailMessage(osv.Model): context=None, count=False, access_rights_uid=None): """ Override that adds specific access rights of mail.message, to restrict messages to published messages for public users. """ - group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id - group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_public')[1] - if group_user_id in [group.id for group in group_ids]: - args = ['&', ('website_published', '=', True)] + list(args) + if uid != SUPERUSER_ID: + group_ids = self.pool.get('res.users').browse(cr, uid, uid, context=context).groups_id + group_user_id = self.pool.get("ir.model.data").get_object_reference(cr, uid, 'base', 'group_public')[1] + if group_user_id in [group.id for group in group_ids]: + args = expression.AND([[('website_published', '=', True)], list(args)]) return super(MailMessage, self)._search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count, access_rights_uid=access_rights_uid) From 166c4d2751b2fffbe4ba344172d63dbf81697cbb Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 13:48:15 +0200 Subject: [PATCH 029/140] [FIX] website_sale_delivery: avoid displaying or choosing non available delivery methods for torder bzr revid: dle@openerp.com-20140402114815-b42pvgk914r0at1d --- addons/website_sale_delivery/controllers/main.py | 3 ++- addons/website_sale_delivery/models/sale_order.py | 8 ++++++++ addons/website_sale_delivery/models/website.py | 9 ++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index 73da87b549d..5be0fcfd00a 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -10,10 +10,11 @@ class Ecommerce(Ecommerce): @http.route(['/shop/payment/'], type='http', auth="public", website=True, multilang=True) def payment(self, **post): cr, uid, context = request.cr, request.uid, request.context + carrier_obj = request.registry.get('delivery.carrier') order = self.get_order() carrier_id = post.get('carrier_id') - if order and carrier_id: + if order and carrier_id or not carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id): # recompute delivery costs request.registry['website']._check_carrier_quotation(cr,uid,order,carrier_id,context=context) return request.redirect("/shop/payment/") diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 9074e6768ea..b935e728412 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -69,6 +69,14 @@ class SaleOrder(orm.Model): delivery_ctx = dict(context, order_id=order.id) DeliveryCarrier = self.pool.get('delivery.carrier') + carrier_obj = self.pool.get('delivery.carrier') delivery_ids = DeliveryCarrier.search(cr, uid, [('website_published','=',True)], context=context) + # Following loop is done to avoid displaying delivery methods who are not available for this order + # This can surely be done in a more efficient way, but at the moment, it mimics the way it's + # done in delivery_set method of sale.py, from delivery module + for delivery_id in delivery_ids: + grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) + if not grid_id: + delivery_ids.remove(delivery_id) values['deliveries'] = DeliveryCarrier.browse(cr, SUPERUSER_ID, delivery_ids, context=delivery_ctx) return values diff --git a/addons/website_sale_delivery/models/website.py b/addons/website_sale_delivery/models/website.py index 5c4585de17f..50ee038ed4b 100644 --- a/addons/website_sale_delivery/models/website.py +++ b/addons/website_sale_delivery/models/website.py @@ -21,6 +21,7 @@ class Website(orm.Model): def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): # check to add or remove carrier_id + carrier_obj = self.pool.get('delivery.carrier') carrier_id = False for line in order.website_order_line: if line.product_id.type != "service": @@ -36,7 +37,13 @@ class Website(orm.Model): self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [('website_published','=',True)], context=context) - carrier_id = force_carrier_id or (carrier_ids and carrier_ids[0]) + if force_carrier_id: + carrier_ids.insert(0, force_carrier_id) + for delivery_id in set(carrier_ids): + grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) + if grid_id: + carrier_id = delivery_id + break order.write({'carrier_id': carrier_id}, context=context) #If carrier_id have no grid, we don't have delivery ! if carrier_id: From 9553c48a8ba682b20ffc7091f57123dcc263ef96 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 2 Apr 2014 14:37:07 +0200 Subject: [PATCH 030/140] [FIX] website_mail: force the copy method not to copy website_message_ids field, we do not want duplicated emails (opw 605975). bzr revid: mat@openerp.com-20140402123707-r3e38b64zsheq0tn --- addons/website_mail/models/mail_thread.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/website_mail/models/mail_thread.py b/addons/website_mail/models/mail_thread.py index c88fd032271..d7f750872ca 100644 --- a/addons/website_mail/models/mail_thread.py +++ b/addons/website_mail/models/mail_thread.py @@ -21,7 +21,7 @@ from openerp.osv import osv, fields - +# TODO for trunk, remove me class MailThread(osv.Model): _inherit = 'mail.thread' @@ -35,3 +35,7 @@ class MailThread(osv.Model): help="Website communication history", ), } + + def copy(self, cr, uid, id, default=None, context=None): + default['website_message_ids'] = [] + return super(MailThread, self).copy(cr, uid, id, default=default, context=context) \ No newline at end of file From ad680380b8833ffff65ec4d9877afb283b9f608b Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 16:45:20 +0200 Subject: [PATCH 031/140] [FIX] website_sale*: not possible to process order if no delivery methods available bzr revid: dle@openerp.com-20140402144520-ulfex2r3q9wwd3ig --- addons/website_sale/controllers/main.py | 45 ++++++++------- addons/website_sale/models/sale_order.py | 3 + addons/website_sale/views/website_sale.xml | 8 ++- .../website_sale_delivery/controllers/main.py | 8 +-- .../models/sale_order.py | 55 ++++++++++++++++--- .../website_sale_delivery/models/website.py | 38 +------------ 6 files changed, 86 insertions(+), 71 deletions(-) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index b345b810e32..94f0577abb7 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -584,6 +584,7 @@ class Ecommerce(http.Controller): """ cr, uid, context = request.cr, request.uid, request.context payment_obj = request.registry.get('payment.acquirer') + sale_order_obj = request.registry['sale.order'] # if no sale order at this stage: back to checkout beginning order = self.get_order() @@ -603,29 +604,31 @@ class Ecommerce(http.Controller): shipping_partner_id = order.partner_invoice_id.id values = { - 'order': request.registry['sale.order'].browse(cr, SUPERUSER_ID, order.id, context=context) + 'order': sale_order_obj.browse(cr, SUPERUSER_ID, order.id, context=context) } - values.update(request.registry.get('sale.order')._get_website_data(cr, uid, order, context)) + values['errors'] = sale_order_obj._get_errors(cr, uid, order, context=context) + values.update(sale_order_obj._get_website_data(cr, uid, order, context=context)) - # fetch all registered payment means - if tx: - acquirer_ids = [tx.acquirer_id.id] - else: - acquirer_ids = payment_obj.search(cr, SUPERUSER_ID, [('website_published', '=', True), '|', ('company_id', '=', order.company_id.id), ('company_id', '=', False)], context=context) - values['acquirers'] = payment_obj.browse(cr, uid, acquirer_ids, context=context) - render_ctx = dict(context, submit_class='btn btn-primary', submit_txt='Pay Now') - for acquirer in values['acquirers']: - render_ctx['tx_url'] = '/shop/payment/transaction/%s' % acquirer.id - acquirer.button = payment_obj.render( - cr, SUPERUSER_ID, acquirer.id, - order.name, - order.amount_total, - order.pricelist_id.currency_id.id, - partner_id=shipping_partner_id, - tx_values={ - 'return_url': '/shop/payment/validate', - }, - context=render_ctx) + if not values['errors']: + # fetch all registered payment means + if tx: + acquirer_ids = [tx.acquirer_id.id] + else: + acquirer_ids = payment_obj.search(cr, SUPERUSER_ID, [('website_published', '=', True), '|', ('company_id', '=', order.company_id.id), ('company_id', '=', False)], context=context) + values['acquirers'] = payment_obj.browse(cr, uid, acquirer_ids, context=context) + render_ctx = dict(context, submit_class='btn btn-primary', submit_txt='Pay Now') + for acquirer in values['acquirers']: + render_ctx['tx_url'] = '/shop/payment/transaction/%s' % acquirer.id + acquirer.button = payment_obj.render( + cr, SUPERUSER_ID, acquirer.id, + order.name, + order.amount_total, + order.pricelist_id.currency_id.id, + partner_id=shipping_partner_id, + tx_values={ + 'return_url': '/shop/payment/validate', + }, + context=render_ctx) return request.website.render("website_sale.payment", values) diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 577005212c3..af5ff650ab2 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -16,6 +16,9 @@ class SaleOrder(osv.Model): ), } + def _get_errors(self, cr, uid, order, context=None): + return [] + def _get_website_data(self, cr, uid, order, context): return { 'partner': order.partner_id.id, diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index 599b7e556d9..446dfb4567e 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -883,6 +883,12 @@
  • Confirmation
  • Validate Order

    + +
    +

    + +
    +
    @@ -970,7 +976,7 @@ -
    +
    diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index 5be0fcfd00a..e096cd12c79 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -10,13 +10,13 @@ class Ecommerce(Ecommerce): @http.route(['/shop/payment/'], type='http', auth="public", website=True, multilang=True) def payment(self, **post): cr, uid, context = request.cr, request.uid, request.context - carrier_obj = request.registry.get('delivery.carrier') order = self.get_order() carrier_id = post.get('carrier_id') + if carrier_id: + carrier_id = int(carrier_id) - if order and carrier_id or not carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id): - # recompute delivery costs - request.registry['website']._check_carrier_quotation(cr,uid,order,carrier_id,context=context) + request.registry['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=carrier_id, context=context) + if order and carrier_id: return request.redirect("/shop/payment/") res = super(Ecommerce, self).payment(**post) diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index b935e728412..2ebe3d7fbd5 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -56,6 +56,50 @@ class SaleOrder(orm.Model): ), } + def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): + carrier_obj = self.pool.get('delivery.carrier') + + # check to add or remove carrier_id + if all(line.product_id.type == "service" for line in order.website_order_line): + order.write({'carrier_id': None}, context=context) + self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) + return True + else: + carrier_id = force_carrier_id or order.carrier_id.id + if force_carrier_id or not carrier_id or not carrier_id in self._get_delivery_methods(cr, uid, order, context=context): + self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) + carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [('website_published','=',True)], context=context) + if force_carrier_id: + carrier_ids.insert(0, force_carrier_id) + for delivery_id in carrier_ids: + grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) + if grid_id: + carrier_id = delivery_id + break + order.write({'carrier_id': carrier_id}, context=context) + if carrier_id: + order.delivery_set(context=context) + + return bool(carrier_id) + + def _get_delivery_methods(self, cr, uid, order, context=None): + carrier_obj = self.pool.get('delivery.carrier') + delivery_ids = carrier_obj.search(cr, uid, [('website_published','=',True)], context=context) + # Following loop is done to avoid displaying delivery methods who are not available for this order + # This can surely be done in a more efficient way, but at the moment, it mimics the way it's + # done in delivery_set method of sale.py, from delivery module + for delivery_id in list(delivery_ids): + grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) + if not grid_id: + delivery_ids.remove(delivery_id) + return delivery_ids + + def _get_errors(self, cr, uid, order, context=None): + errors = super(SaleOrder, self)._get_errors(cr, uid, order, context=context) + if not self._get_delivery_methods(cr, uid, order, context=context): + errors.append(('No delivery method available', 'There is no available delivery method for your order')) + return errors + def _get_website_data(self, cr, uid, order, context=None): """ Override to add delivery-related website data. """ values = super(SaleOrder, self)._get_website_data(cr, uid, order, context=context) @@ -69,14 +113,7 @@ class SaleOrder(orm.Model): delivery_ctx = dict(context, order_id=order.id) DeliveryCarrier = self.pool.get('delivery.carrier') - carrier_obj = self.pool.get('delivery.carrier') - delivery_ids = DeliveryCarrier.search(cr, uid, [('website_published','=',True)], context=context) - # Following loop is done to avoid displaying delivery methods who are not available for this order - # This can surely be done in a more efficient way, but at the moment, it mimics the way it's - # done in delivery_set method of sale.py, from delivery module - for delivery_id in delivery_ids: - grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) - if not grid_id: - delivery_ids.remove(delivery_id) + delivery_ids = self._get_delivery_methods(cr, uid, order, context=context) + values['deliveries'] = DeliveryCarrier.browse(cr, SUPERUSER_ID, delivery_ids, context=delivery_ctx) return values diff --git a/addons/website_sale_delivery/models/website.py b/addons/website_sale_delivery/models/website.py index 50ee038ed4b..efd8b2233d2 100644 --- a/addons/website_sale_delivery/models/website.py +++ b/addons/website_sale_delivery/models/website.py @@ -9,7 +9,7 @@ class Website(orm.Model): def _ecommerce_create_quotation(self, cr, uid, context=None): order_id = super(Website, self)._ecommerce_create_quotation(cr, uid, context=context) order = self.pool['sale.order'].browse(cr, SUPERUSER_ID, order_id, context=context) - self._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) + self.pool['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) return order_id def _ecommerce_add_product_to_cart(self, cr, uid, product_id=0, order_line_id=0, number=1, set_number=-1, context=None): @@ -17,38 +17,4 @@ class Website(orm.Model): product_id=product_id, order_line_id=order_line_id, number=number, set_number=set_number, context=context) order = self.ecommerce_get_current_order(cr, uid, context=context) - return self._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) and quantity or None - - def _check_carrier_quotation(self, cr, uid, order, force_carrier_id=None, context=None): - # check to add or remove carrier_id - carrier_obj = self.pool.get('delivery.carrier') - carrier_id = False - for line in order.website_order_line: - if line.product_id.type != "service": - carrier_id = True - break - - if not carrier_id: - order.write({'carrier_id': None}, context=context) - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - return True - else: - if order.carrier_id: - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - - carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [('website_published','=',True)], context=context) - if force_carrier_id: - carrier_ids.insert(0, force_carrier_id) - for delivery_id in set(carrier_ids): - grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) - if grid_id: - carrier_id = delivery_id - break - order.write({'carrier_id': carrier_id}, context=context) - #If carrier_id have no grid, we don't have delivery ! - if carrier_id: - order.delivery_set(context=context) - else: - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - - return bool(carrier_id) + return self.pool['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=None, context=context) and quantity or None From 39633b3933c60a4755eb5beba7db2530c95cc844 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Wed, 2 Apr 2014 16:28:23 +0200 Subject: [PATCH 032/140] [FIX] website_quote: skip onchange method when specify no sale.quote.template (opw 605992) bzr revid: mat@openerp.com-20140402142823-btyutrctuc3jh8l3 --- addons/website_quote/models/order.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/website_quote/models/order.py b/addons/website_quote/models/order.py index f515ef0fd05..3614fd63919 100644 --- a/addons/website_quote/models/order.py +++ b/addons/website_quote/models/order.py @@ -131,6 +131,8 @@ class sale_order(osv.osv): } def onchange_template_id(self, cr, uid, ids, template_id, partner=False, fiscal_position=False, context=None): + if not template_id: + return True lines = [] quote_template = self.pool.get('sale.quote.template').browse(cr, uid, template_id, context=context) for line in quote_template.quote_line: From e3f90b739911e8556c4a0d90a66408a58de65621 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 17:20:43 +0200 Subject: [PATCH 033/140] [FIX] website_sale: do not try to check order if order is nontype bzr revid: dle@openerp.com-20140402152043-2vl7pwlwso4tf2dp --- addons/website_sale_delivery/controllers/main.py | 8 ++++---- addons/website_sale_delivery/models/sale_order.py | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addons/website_sale_delivery/controllers/main.py b/addons/website_sale_delivery/controllers/main.py index e096cd12c79..9f77d7f67b3 100644 --- a/addons/website_sale_delivery/controllers/main.py +++ b/addons/website_sale_delivery/controllers/main.py @@ -14,10 +14,10 @@ class Ecommerce(Ecommerce): carrier_id = post.get('carrier_id') if carrier_id: carrier_id = int(carrier_id) - - request.registry['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=carrier_id, context=context) - if order and carrier_id: - return request.redirect("/shop/payment/") + if order: + request.registry['sale.order']._check_carrier_quotation(cr, uid, order, force_carrier_id=carrier_id, context=context) + if carrier_id: + return request.redirect("/shop/payment/") res = super(Ecommerce, self).payment(**post) return res diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 2ebe3d7fbd5..964fce6346e 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -60,6 +60,8 @@ class SaleOrder(orm.Model): carrier_obj = self.pool.get('delivery.carrier') # check to add or remove carrier_id + if not order: + return False if all(line.product_id.type == "service" for line in order.website_order_line): order.write({'carrier_id': None}, context=context) self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) From 9e92e40da3323147fa4b8136973b197418461138 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 17:28:14 +0200 Subject: [PATCH 034/140] [FIX] websit_sale: checking grid need some more access rights, therefore need to using superuser_id bzr revid: dle@openerp.com-20140402152814-0x90lrp05houblqh --- addons/website_sale_delivery/models/sale_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 964fce6346e..9826d2105f6 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -74,7 +74,7 @@ class SaleOrder(orm.Model): if force_carrier_id: carrier_ids.insert(0, force_carrier_id) for delivery_id in carrier_ids: - grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) + grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) if grid_id: carrier_id = delivery_id break @@ -91,7 +91,7 @@ class SaleOrder(orm.Model): # This can surely be done in a more efficient way, but at the moment, it mimics the way it's # done in delivery_set method of sale.py, from delivery module for delivery_id in list(delivery_ids): - grid_id = carrier_obj.grid_get(cr, uid, [delivery_id], order.partner_shipping_id.id) + grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) if not grid_id: delivery_ids.remove(delivery_id) return delivery_ids From 9b19c1a33733eedc20e73b5f8621ae447b1cea6b Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 3 Apr 2014 09:41:34 +0200 Subject: [PATCH 035/140] [FIX] orm: add missing pooler in call bzr revid: mat@openerp.com-20140403074134-fav63w1k6hm1b8ar --- openerp/osv/orm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index b862a6670c3..5413570930d 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -1903,7 +1903,7 @@ class BaseModel(object): return result def _view_look_dom_arch(self, cr, uid, node, view_id, context=None): - return self['ir.ui.view'].postprocess_and_fields( + return self.pool['ir.ui.view'].postprocess_and_fields( cr, uid, self._name, node, view_id, context=context) def search_count(self, cr, user, args, context=None): From 0a80f598538e2a73a083956a726a174efd06476f Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 3 Apr 2014 11:23:55 +0200 Subject: [PATCH 036/140] [FIX] calendar: render template even if context values are not set bzr revid: dle@openerp.com-20140403092355-cmnt5cv1ffdv19o8 --- addons/calendar/calendar_data.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/calendar/calendar_data.xml b/addons/calendar/calendar_data.xml index 4435e8a4324..e1aad240292 100644 --- a/addons/calendar/calendar_data.xml +++ b/addons/calendar/calendar_data.xml @@ -212,7 +212,7 @@
    : % for attendee in object.event_id.attendee_ids: -
    +
    % if attendee.cn != object.cn: ${attendee.cn} % else: @@ -227,9 +227,9 @@
    @@ -345,7 +345,7 @@ : % for attendee in object.event_id.attendee_ids: -
    +
    % if attendee.cn != object.cn: ${attendee.cn} % else: @@ -360,9 +360,9 @@ @@ -477,7 +477,7 @@ : % for attendee in object.event_id.attendee_ids: -
    +
    % if attendee.cn != object.cn: ${attendee.cn} % else: From b5c0c3a5d2657136793a7bba841ee6d2142360d4 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 3 Apr 2014 13:25:11 +0200 Subject: [PATCH 037/140] [FIX] website_sale: order categories according to their sequence bzr revid: dle@openerp.com-20140403112511-h4yi8jimf9hjucyl --- addons/website_sale/controllers/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 94f0577abb7..99f39a3c921 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -275,6 +275,7 @@ class Ecommerce(http.Controller): all_categories.add(parent) parent = parent.parent_id categories = list(all_categories) + categories.sort(key=lambda x: x.sequence) values = { 'products': products, From f120d6ffb77e08985de7b646f343f6bbb0073e02 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Tue, 1 Apr 2014 18:06:23 +0200 Subject: [PATCH 038/140] [FIX] ir.qweb: avoid errors with function fields of type datetime bzr revid: odo@openerp.com-20140401160623-loj5nsph7tfnn1us --- addons/website/models/ir_qweb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website/models/ir_qweb.py b/addons/website/models/ir_qweb.py index 64aad94c83e..55c42d2253f 100644 --- a/addons/website/models/ir_qweb.py +++ b/addons/website/models/ir_qweb.py @@ -157,7 +157,7 @@ class DateTime(orm.AbstractModel): value = datetime.datetime.strptime( value, DEFAULT_SERVER_DATETIME_FORMAT) if value: - value = column.context_timestamp( + value = fields.datetime.context_timestamp( cr, uid, timestamp=value, context=context) value = value.strftime(openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT) From 9f7ba142538fb3ab73691db0970b4348f66cbf93 Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Tue, 1 Apr 2014 18:14:40 +0200 Subject: [PATCH 039/140] [FIX] Calendar mail_message : check context before to use it bzr revid: jke@openerp.com-20140401161440-w2jjr0a5u49lwnsj --- addons/calendar/calendar.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 3dc1fa75b8d..12a1cec79f4 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -1582,6 +1582,8 @@ class mail_message(osv.Model): return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) def _find_allowed_model_wise(self, cr, uid, doc_model, doc_dict, context=None): + if context is None: + context = {} if doc_model == 'calendar.event': order = context.get('order', self._order) for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], order=order, context=context): From 0f5c2bda4aa99ef51a3480b6918a73b3b324a24a Mon Sep 17 00:00:00 2001 From: Kersten Jeremy Date: Wed, 2 Apr 2014 09:15:42 +0200 Subject: [PATCH 040/140] [FIX] Calendar - revert commit from forward port 9354. This has been already fixed in 9322. bzr revid: jke@openerp.com-20140402071542-cv7zz4t1t26riuuu --- addons/calendar/calendar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index db37a7ac505..12a1cec79f4 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -1123,7 +1123,7 @@ class calendar_event(osv.Model): def get_end_date(data): if data.get('end_date'): - data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959' + data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z' return (data.get('end_type') == 'count' and (';COUNT=' + str(data.get('count'))) or '') +\ ((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '') From 8c93dcbf62f918c10d01a62db6c04d5c173e8761 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 2 Apr 2014 09:38:00 +0200 Subject: [PATCH 041/140] [IMP] refactoring of readgroup method. The work is pretty much complete with this commit. Now, it correctly fills in empty group using _read_group_fill_results (orm.py) bzr revid: ged@openerp.com-20140402073800-0ggxqfpyo2in8ozt --- openerp/osv/orm.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index ac07a6f5bca..45dc264c67c 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2115,7 +2115,7 @@ class BaseModel(object): pass - def _read_group_fill_results(self, cr, uid, domain, groupby, groupby_list, aggregated_fields, + def _read_group_fill_results(self, cr, uid, domain, groupby, remaining_groupbys, aggregated_fields, read_group_result, read_group_order=None, context=None): """Helper method for filling in empty groups for all possible values of the field being grouped by""" @@ -2135,8 +2135,8 @@ class BaseModel(object): result_template = dict.fromkeys(aggregated_fields, False) result_template[groupby + '_count'] = 0 - if groupby_list and len(groupby_list) > 1: - result_template['__context'] = {'group_by': groupby_list[1:]} + if remaining_groupbys: + result_template['__context'] = {'group_by': remaining_groupbys} # Merge the left_side (current results as dicts) with the right_side (all # possible values as m2o pairs). Both lists are supposed to be using the @@ -2396,10 +2396,9 @@ class BaseModel(object): def format_result (fromquery): domain_group = [dom for gb in annotated_groupbys for dom in get_domain(gb, fromquery[gb['field']])] - result = { - '__domain': domain_group + domain, - '__context': {'group_by': groupby[len(annotated_groupbys):]} - } + result = { '__domain': domain_group + domain } + if len(groupby) - len(annotated_groupbys) >= 1: + result['__context'] = { 'group_by': groupby[len(annotated_groupbys):]} result.update(fromquery) for k,v in result.iteritems(): gb = groupby_dict.get(k) @@ -2408,16 +2407,13 @@ class BaseModel(object): del result['id'] return result + result = map(format_result, data) + for gb in groupby_fields: if gb in self._group_by_full: - print "DING" - result = map(format_result, data) - - # TO DO!!!!!!!!!!!! - # if first_groupby in self._group_by_full: - # result = self._read_group_fill_results(cr, uid, domain, first_groupby, groupby, - # aggregated_fields, result, read_group_order=order, - # context=context) + result = self._read_group_fill_results(cr, uid, domain, gb, groupby[len(annotated_groupbys):], + aggregated_fields, result, read_group_order=order, + context=context) return result def _inherits_join_add(self, current_model, parent_model_name, query): From 95b2daf17b9f3301095851e855b85dcbe6fa955f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 2 Apr 2014 09:41:22 +0200 Subject: [PATCH 042/140] [IMP] modifies the web client to be able to use the new 'lazy' parameter of the method readgroup (so now the client can requires a readgroup to be eager/lazy) (addon web) bzr revid: ged@openerp.com-20140402074122-sf52hult1qkqos81 --- addons/web/static/src/js/data.js | 44 ++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 517afa7f5c2..413d0621011 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -27,6 +27,7 @@ instance.web.Query = instance.web.Class.extend({ this._fields = fields; this._filter = []; this._context = {}; + this._lazy = true; this._limit = false; this._offset = 0; this._order_by = []; @@ -36,6 +37,7 @@ instance.web.Query = instance.web.Class.extend({ var q = new instance.web.Query(this._model, this._fields); q._context = this._context; q._filter = this._filter; + q._lazy = this._lazy; q._limit = this._limit; q._offset = this._offset; q._order_by = this._order_by; @@ -51,6 +53,7 @@ instance.web.Query = instance.web.Class.extend({ q._context = new instance.web.CompoundContext( q._context, to_set.context); break; + case 'lazy': case 'limit': case 'offset': case 'order_by': @@ -140,6 +143,7 @@ instance.web.Query = instance.web.Class.extend({ domain: this._model.domain(this._filter), context: ctx, offset: this._offset, + lazy: this._lazy, limit: this._limit, orderby: instance.web.serialize_sort(this._order_by) || false }).then(function (results) { @@ -148,8 +152,9 @@ instance.web.Query = instance.web.Class.extend({ result.__context = result.__context || {}; result.__context.group_by = result.__context.group_by || []; _.defaults(result.__context, ctx); + var grouping_fields = self._lazy ? [grouping[0]] : grouping; return new instance.web.QueryGroup( - self._model.name, grouping[0], result); + self._model.name, grouping_fields, result); }); }); }, @@ -175,6 +180,18 @@ instance.web.Query = instance.web.Class.extend({ if (!domain) { return this; } return this.clone({filter: domain}); }, + /** + * Creates a new query with the provided parameter lazy replacing the current + * query's own. + * + * @param {Boolean} lazy indicates if the read_group should return only the + * first level of groupby records, or should return the records grouped by + * all levels at once (so, it makes only 1 db request). + * @returns {openerp.web.Query} + */ + lazy: function (lazy) { + return this.clone({lazy: lazy}); + }, /** * Creates a new query with the provided limit replacing the current * query's own limit @@ -213,7 +230,7 @@ instance.web.Query = instance.web.Class.extend({ }); instance.web.QueryGroup = instance.web.Class.extend({ - init: function (model, grouping_field, read_group_group) { + init: function (model, grouping_fields, read_group_group) { // In cases where group_by_no_leaf and no group_by, the result of // read_group has aggregate fields but no __context or __domain. // Create default (empty) values for those so that things don't break @@ -221,29 +238,40 @@ instance.web.QueryGroup = instance.web.Class.extend({ {__context: {group_by: []}, __domain: []}, read_group_group); - var raw_field = grouping_field && grouping_field.split(':')[0]; + var raw_fields = _.map(grouping_fields, function (field) { + return field && field.split(':')[0]; + }); + + var aggregates = {}; _(fixed_group).each(function (value, key) { if (key.indexOf('__') === 0 - || key === raw_field - || key === raw_field + '_count') { + || _.contains(raw_fields, key) + || (key === raw_fields[0] + '_count')) { return; } aggregates[key] = value || 0; }); + this.model = new instance.web.Model( model, fixed_group.__context, fixed_group.__domain); - var group_size = fixed_group[raw_field + '_count'] || fixed_group.__count || 0; + var group_size = fixed_group[raw_fields[0] + '_count'] || fixed_group.__count || 0; var leaf_group = fixed_group.__context.group_by.length === 0; + var value = (grouping_fields.length === 1) + ? fixed_group[raw_fields[0]] + : _.map(raw_fields, function (field) { return fixed_group[field]; }); + var grouped_on = (grouping_fields.length === 1) + ? grouping_fields[0] + : grouping_fields; this.attributes = { folded: !!(fixed_group.__fold), - grouped_on: grouping_field, + grouped_on: grouped_on, // if terminal group (or no group) and group_by_no_leaf => use group.__count length: group_size, - value: fixed_group[raw_field], + value: value, // A group is open-able if it's not a leaf in group_by_no_leaf mode has_children: !(leaf_group && fixed_group.__context['group_by_no_leaf']), From c4d0299eca6941e4f38f86c7e8c4a3e9a5cf84a7 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 2 Apr 2014 09:43:41 +0200 Subject: [PATCH 043/140] [IMP] complete rewrite of the data loading code in the graph view, using the lazy/eager feature of readgroup. The code is simpler and more efficient: it only performs a fixed number of requests (well, the number is 'fixed' in the sense that it does not depend of the size of the data being displayed, but it still depends on the number of dimensions) (addon web_graph) bzr revid: ged@openerp.com-20140402074341-8cleqizqculxmkys --- addons/web_graph/static/src/js/pivot_table.js | 406 ++++++++---------- 1 file changed, 182 insertions(+), 224 deletions(-) diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index f77d49f9a1a..e8a438b3fe5 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -82,7 +82,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ get_values: function (id1, id2, default_values) { var cell = _.findWhere(this.cells, {x: Math.min(id1, id2), y: Math.max(id1, id2)}); - return (cell !== undefined) ? cell.values : (default_values || new Array(this.measures.length)); + return (cell !== undefined) ? + cell.values : + (default_values || new Array(this.measures.length)); }, // ---------------------------------------------------------------------- @@ -144,12 +146,16 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ get_ancestors: function (header) { var self = this; if (!header.children) return []; - return [].concat.apply([], _.map(header.children, function (c) {return self.get_ancestors_and_self(c); })); + return [].concat.apply([], _.map(header.children, function (c) { + return self.get_ancestors_and_self(c); + })); }, get_ancestors_and_self: function (header) { var self = this; - return [].concat.apply([header], _.map(header.children, function (c) { return self.get_ancestors_and_self(c); })); + return [].concat.apply([header], _.map(header.children, function (c) { + return self.get_ancestors_and_self(c); + })); }, get_total: function (header) { @@ -205,54 +211,28 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ expand: function (header_id, groupby) { var self = this, header = this.get_header(header_id), - otherRoot = this.get_other_root(header), - fields = otherRoot.groupby.concat(this.measures); + other_root = this.get_other_root(header), + this_gb = [groupby.field], + other_gbs = _.pluck(other_root.groupby, 'field'); if (header.path.length === header.root.groupby.length) { header.root.groupby.push(groupby); } - groupby = [groupby].concat(otherRoot.groupby); - - return this.get_groups(groupby, fields, header.domain).then(function (groups) { - _.each(groups.reverse(), function (group) { - // make header - var child = self.make_header(group, header); - child.expanded = false; - header.children.splice(0,0, child); - header.root.headers.splice(header.root.headers.indexOf(header) + 1, 0, child); - // make cells - _.each(self.get_ancestors_and_self(group), function (data) { - var values = _.map(self.measures, function (m) { - return data.attributes.aggregates[m.field]; - }); - var other = _.find(otherRoot.headers, function (h) { - if (header.root === self.cols) { - return _.isEqual(data.path.slice(1), h.path); - } else { - return _.isEqual(_.rest(data.path), h.path); - } - }); - if (other) { - self.add_cell(child.id, other.id, values); - } - }); + return this.perform_requests(this_gb, other_gbs, header.domain).then(function () { + var data = Array.prototype.slice.call(arguments); + data = data.slice(other_gbs.length + 1, data.length); + _.each(data, function (data_pt) { + self.make_headers_and_cell( + data_pt, header.root.headers, other_root.headers, 1, header.path); }); header.expanded = true; + header.children.forEach(function (child) { + child.expanded = false; + child.root = header.root; + }); }); }, - make_header: function (group, parent) { - var title = parent ? group.attributes.value : _t('Total'); - return { - id: _.uniqueId(), - path: parent ? parent.path.concat(title) : [], - title: title, - children: [], - domain: parent ? group.model._domain : this.domain, - root: parent ? parent.root : undefined, - }; - }, - swap_axis: function () { var temp = this.rows; this.rows = this.cols; @@ -262,206 +242,184 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ // ---------------------------------------------------------------------- // Data updating methods // ---------------------------------------------------------------------- - // Load the data from the db, using the method this.load_data // update_data will try to preserve the expand/not expanded status of each // column/row. If you want to expand all, then set this.cols.headers/this.rows.headers // to null before calling update_data. - update_data: function () { - var self = this; + update_data: function () { + var self = this; + return this.perform_requests().then (function () { + var data = Array.prototype.slice.call(arguments); + self.no_data = !data[0][0].attributes.length; + if (self.no_data) { + return; + } + var row_headers = [], + col_headers = []; + self.cells = []; - return this.load_data().then (function (result) { - if (result) { - self.no_data = false; - self[self.cols.headers ? 'update_headers' : 'expand_headers'](self.cols, result.col_headers); - self[self.rows.headers ? 'update_headers' : 'expand_headers'](self.rows, result.row_headers); - } else { - self.no_data = true; - } - }); - }, + var dim_col = self.cols.groupby.length, + i, j, index; - expand_headers: function (root, new_headers) { - root.headers = new_headers; - _.each(root.headers, function (header) { - header.root = root; - header.expanded = (header.children.length > 0); - }); - }, - - update_headers: function (root, new_headers) { - _.each(root.headers, function (header) { - var corresponding_header = _.find(new_headers, function (h) { - return _.isEqual(h.path, header.path); - }); - if (corresponding_header && header.expanded) { - corresponding_header.expanded = true; - _.each(corresponding_header.children, function (c) { - c.expanded = false; - }); - } - if (corresponding_header && (!header.expanded)) { - corresponding_header.expanded = false; - } - }); - var updated_headers = _.filter(new_headers, function (header) { - return (header.expanded !== undefined); - }); - _.each(updated_headers, function (header) { - if (!header.expanded) { - header.children = []; - } - header.root = root; - }); - root.headers = updated_headers; - }, - - // ---------------------------------------------------------------------- - // Data loading methods - // ---------------------------------------------------------------------- - - // To obtain all the values required to draw the full table, we have to do - // at least 2 + min(row.groupby.length, col.groupby.length) - // calls to readgroup. To simplify the code, we will always do - // 2 + row.groupby.length calls. For example, if row.groupby = [r1, r2, r3] - // and col.groupby = [c1, c2], then we will make the call with the following - // groupbys: [r1,r2,r3], [c1,r1,r2,r3], [c1,c2,r1,r2,r3], []. - load_data: function () { - var self = this, - cols = this.cols.groupby, - rows = this.rows.groupby, - visible_fields = rows.concat(cols, self.measures); - - if (this.measures.length === 0) { - return $.Deferred.resolve().promise(); - } - - var groupbys = _.map(_.range(cols.length + 1), function (i) { - return cols.slice(0, i).concat(rows); - }); - groupbys.push([]); - - var get_data_requests = _.map(groupbys, function (groupby) { - return self.get_groups(groupby, visible_fields, self.domain); - }); - - return $.when.apply(null, get_data_requests).then(function () { - var data = Array.prototype.slice.call(arguments), - row_data = data[0], - col_data = (cols.length !== 0) ? data[data.length - 2] : [], - has_data = data[data.length - 1][0]; - - return has_data && self.format_data(col_data, row_data, data); + for (i = 0; i < self.rows.groupby.length + 1; i++) { + for (j = 0; j < dim_col + 1; j++) { + index = i*(dim_col + 1) + j; + self.make_headers_and_cell(data[index], row_headers, col_headers, i); + } + } + self.set_headers(row_headers, self.rows); + self.set_headers(col_headers, self.cols); }); }, - get_groups: function (groupbys, fields, domain, path) { - var self = this, - groupby = (groupbys.length) ? groupbys[0] : []; - path = path || []; + make_headers_and_cell: function (data_pts, row_headers, col_headers, index, prefix) { + var self = this; + data_pts.forEach(function (data_pt) { + var row_value = (prefix || []).concat(data_pt.attributes.value.slice(0,index)); + var col_value = data_pt.attributes.value.slice(index); + + var row = self.find_or_create_header(row_headers, row_value, data_pt); + var col = self.find_or_create_header(col_headers, col_value, data_pt); - return this._query_db(groupby, fields, domain, path).then(function (groups) { - if (groupbys.length > 1) { - var get_subgroups = $.when.apply(null, _.map(groups, function (group) { - return self.get_groups(_.rest(groupbys), fields, group.model._domain, path.concat(group.attributes.value)).then(function (subgroups) { - group.children = subgroups; - }); - })); - return get_subgroups.then(function () { - return groups; - }); - } else { - return groups; + var cell_value = _.map(self.measures, function (m) { + return data_pt.attributes.aggregates[m.field]; + }); + self.cells.push({ + x: Math.min(row.id, col.id), + y: Math.max(row.id, col.id), + values: cell_value + }); + }); + }, + + make_header: function (values) { + return _.extend({ + children: [], + domain: this.domain, + expanded: undefined, + id: _.uniqueId(), + path: [], + root: undefined, + title: undefined + }, values || {}); + }, + + find_or_create_header: function (headers, path, data_pt) { + var hdr = _.find(headers, function (header) { + return _.isEqual(path, header.path); + }); + if (hdr) { + return hdr; + } + if (!path.length) { + hdr = this.make_header({title: _t('Total')}); + headers.push(hdr); + return hdr; + } + hdr = this.make_header({ + path:path, + domain:data_pt.model._domain, + title: _t(_.last(path)) + }); + parent = _.find(headers, function (header) { + return _.isEqual(header.path, _.initial(path, 1)); + }); + + var previous = parent.children.length ? _.last(parent.children) : parent; + headers.splice(headers.indexOf(previous) + 1, 0, hdr); + parent.children.push(hdr); + return hdr; + }, + + perform_requests: function (group1, group2, domain) { + var self = this, + requests = [], + row_gbs = _.pluck(this.rows.groupby, 'field'), + col_gbs = _.pluck(this.cols.groupby, 'field'), + field_list = row_gbs.concat(col_gbs, _.pluck(this.measures, 'field')), + fields = field_list.map(function (f) { return self.raw_field(f); }); + + group1 = group1 || row_gbs; + group2 = group2 || col_gbs; + + var i,j, groupbys; + for (i = 0; i < group1.length + 1; i++) { + for (j = 0; j < group2.length + 1; j++) { + groupbys = group1.slice(0,i).concat(group2.slice(0,j)); + requests.push(self.get_groups(groupbys, fields, domain || self.domain)); } - }); + } + return $.when.apply(null, requests); + }, - }, + // set the 'expanded' status of new_headers more or less like root.headers, with root as root + set_headers: function(new_headers, root) { + if (root.headers) { + _.each(root.headers, function (header) { + var corresponding_header = _.find(new_headers, function (h) { + return _.isEqual(h.path, header.path); + }); + if (corresponding_header && header.expanded) { + corresponding_header.expanded = true; + _.each(corresponding_header.children, function (c) { + c.expanded = false; + }); + } + if (corresponding_header && (!header.expanded)) { + corresponding_header.expanded = false; + } + }); + var updated_headers = _.filter(new_headers, function (header) { + return (header.expanded !== undefined); + }); + _.each(updated_headers, function (header) { + header.root = root; + }); + root.headers = updated_headers; + } else { + root.headers = new_headers; + _.each(root.headers, function (header) { + header.root = root; + header.expanded = (header.children.length > 0); + }); + } + return new_headers; + }, - _query_db: function (groupby, fields, domain, path) { - var self = this, - field_ids = _.without(_.pluck(fields, 'field'), '__count'), - fields = _.map(field_ids, function(f) { return self.raw_field(f); }); - - return this.model.query(field_ids) - .filter(domain) - .group_by(groupby.field) - .then(function (results) { - var groups = _.filter(results, function (group) { - return group.attributes.length > 0; - }); - return _.map(groups, function (g) { return self.format_group(g, path); }); - }); - }, + get_groups: function (groupbys, fields, domain) { + var self = this; + return this.model.query(_.without(fields, '__count')) + .filter(domain) + .lazy(false) + .group_by(groupbys) + .then(function (groups) { + return groups.map(function (group) { + var attrs = group.attributes, + grouped_on = attrs.grouped_on instanceof Array + ? attrs.grouped_on : [attrs.grouped_on], + raw_grouped_on = grouped_on.map(function (f) { + return self.raw_field(f); + }); + if (grouped_on.length === 1) { attrs.value = [attrs.value]} + attrs.value = _.range(grouped_on.length).map(function (i) { + if (attrs.value[i] === false) { + return _t('Undefined'); + } else if (attrs.value[i] instanceof Array) { + return attrs.value[i][1]; + } + return attrs.value[i] + }); + attrs.aggregates.__count = group.attributes.length; + attrs.grouped_on = raw_grouped_on; + return group; + }); + }); + }, // if field is a fieldname, returns field, if field is field_id:interval, retuns field_id raw_field: function (field) { return field.split(':')[0]; }, - // add the path to the group and sanitize the value... - format_group: function (group, current_path) { - var attrs = group.attributes, - value = attrs.value, - grouped_on = attrs.grouped_on ? this.raw_field(attrs.grouped_on) : false; - - if (value === false) { - group.attributes.value = _t('Undefined'); - } else if (grouped_on && this.fields[grouped_on].type === 'selection') { - var selection = this.fields[grouped_on].selection, - value_lookup = _.where(selection, {0:value}); - group.attributes.value = value_lookup ? value_lookup[0][1] : _t('Undefined'); - } else if (value instanceof Array) { - group.attributes.value = value[1]; - } - - group.path = (value !== undefined) ? (current_path || []).concat(group.attributes.value) : []; - group.attributes.aggregates.__count = group.attributes.length; - - return group; - }, - - format_data: function (col_data, row_data, cell_data) { - var self = this, - dim_row = this.rows.groupby.length, - dim_col = this.cols.groupby.length, - col_headers = this.get_ancestors_and_self(this.make_headers(col_data, dim_col)), - row_headers = this.get_ancestors_and_self(this.make_headers(row_data, dim_row)); - - this.cells = []; - _.each(cell_data, function (data, index) { - self.make_cells(data, index, [], row_headers, col_headers); - }); // not pretty. make it more functional? - - return {col_headers: col_headers, row_headers: row_headers}; - }, - - make_headers: function (data, depth, parent) { - var self = this, - main = this.make_header(data, parent); - - if (main.path.length < depth) { - main.children = _.map(data.children || data, function (data_pt) { - return self.make_headers (data_pt, depth, main); - }); - } - return main; - }, - - make_cells: function (data, index, current_path, rows, cols) { - var self = this; - _.each(data, function (group) { - var attr = group.attributes, - path = attr.grouped_on ? current_path.concat(attr.value) : current_path, - values = _.map(self.measures, function (measure) { return attr.aggregates[measure.field]; }), - row = _.find(rows, function (header) { return _.isEqual(header.path, path.slice(index)); }), - col = _.find(cols, function (header) { return _.isEqual(header.path, path.slice(0, index)); }); - - self.add_cell(row.id, col.id, values); - if (group.children) { - self.make_cells (group.children, index, path, rows, cols); - } - }); - }, - }); })(); From 0aba30cbaa7406d55ab220d24eb34567239e9f53 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 10:53:59 +0200 Subject: [PATCH 044/140] [FIX] web: data, read_ids, active_test false was mislocated. The context is no more altered, a new one is created bzr revid: dle@openerp.com-20140402085359-k7e9iy1vqcpgvcqu --- addons/web/static/src/js/data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index b31de507be4..73f244bc6a3 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -463,7 +463,7 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, if (options.check_access_rule === true){ method = 'search_read'; ids_arg = [['id', 'in', ids]]; - context.active_test = false; + context = new instance.web.CompoundContext(context, {active_test: false}); } return this._model.call(method, [ids_arg, fields || false], From a6ed98c4c405647a747b4bf29bf61da5ea6756ac Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 2 Apr 2014 11:18:04 +0200 Subject: [PATCH 045/140] [FIX] res_partner: missing index on `display_name` bzr revid: odo@openerp.com-20140402091804-v5g7g8ys4zv562uk --- openerp/addons/base/res/res_partner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_partner.py b/openerp/addons/base/res/res_partner.py index 46f0218e21f..65ade8aee90 100644 --- a/openerp/addons/base/res/res_partner.py +++ b/openerp/addons/base/res/res_partner.py @@ -228,7 +228,7 @@ class res_partner(osv.osv, format_address): _order = "display_name" _columns = { 'name': fields.char('Name', size=128, required=True, select=True), - 'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers), + 'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers, select=True), 'date': fields.date('Date', select=1), 'title': fields.many2one('res.partner.title', 'Title'), 'parent_id': fields.many2one('res.partner', 'Related Company'), From c138b778df3055dad9e1add03deaf5b519e7581f Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 2 Apr 2014 13:47:58 +0200 Subject: [PATCH 046/140] [FIX] correctly filters out empty groups in read_group results in the data loading code of graph view (addon web_graph) bzr revid: ged@openerp.com-20140402114758-8qfdz8j76t2p2juo --- addons/web_graph/static/src/js/pivot_table.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index e8a438b3fe5..824b41a6b25 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -392,7 +392,9 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ .lazy(false) .group_by(groupbys) .then(function (groups) { - return groups.map(function (group) { + return groups.filter(function (group) { + return group.attributes.length > 0; + }).map(function (group) { var attrs = group.attributes, grouped_on = attrs.grouped_on instanceof Array ? attrs.grouped_on : [attrs.grouped_on], From 590fe996ad8bfad6e6c52217604fece0243535c6 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 2 Apr 2014 14:12:37 +0200 Subject: [PATCH 047/140] [FIX] as render_report is adapted to qweb, no need to filter in _exec_action bzr revid: sle@openerp.com-20140402121237-t9tsnm9birhekj0b --- openerp/tools/test_reports.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/openerp/tools/test_reports.py b/openerp/tools/test_reports.py index 9aa55233a27..c008c20ae29 100644 --- a/openerp/tools/test_reports.py +++ b/openerp/tools/test_reports.py @@ -38,7 +38,7 @@ _logger = logging.getLogger(__name__) _test_logger = logging.getLogger('openerp.tests') -def try_report(cr, uid, rname, ids, data=None, context=None, our_module=None): +def try_report(cr, uid, rname, ids, data=None, context=None, our_module=None, report_type=None): """ Try to render a report with contents of ids This function should also check for common pitfalls of reports. @@ -281,10 +281,7 @@ def try_report_action(cr, uid, action_id, active_model=None, active_ids=None, ids = datas.get('ids') if 'ids' in datas: del datas['ids'] - if action.get('report_type') in ['qweb-pdf', 'qweb-html']: - res = registry['report'].get_html(cr, uid, [], action.get('report_name'), data=datas, context=context) - else: - res = try_report(cr, uid, 'report.'+action['report_name'], ids, datas, context, our_module=our_module) + res = try_report(cr, uid, 'report.'+action['report_name'], ids, datas, context, our_module=our_module) return res else: raise Exception("Cannot handle action of type %s" % act_model) From 9d8fa4d7201b5cc48d97b4eefa1610b7f6a63596 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 2 Apr 2014 15:57:04 +0200 Subject: [PATCH 048/140] [FIX] only fills groups with empty groups in read_group when in lazy mode to prevent weird stuff happening with the read_group_fill_result algorithm. bzr revid: ged@openerp.com-20140402135704-3d71gczgg362cezl --- openerp/osv/orm.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index f9ab9f423ef..9d267816ad5 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2417,9 +2417,12 @@ class BaseModel(object): result = map(format_result, data) - for gb in groupby_fields: - if gb in self._group_by_full: - result = self._read_group_fill_results(cr, uid, domain, gb, groupby[len(annotated_groupbys):], + if lazy and groupby_fields[0] in self._group_by_full: + # Right now, read_group only fill results in lazy mode (by default). + # If you need to have the empty groups in 'eager' mode, then the + # method _read_group_fill_results need to be completely reimplemented + # in a sane way + result = self._read_group_fill_results(cr, uid, domain, groupby_fields[0], groupby[len(annotated_groupbys):], aggregated_fields, result, read_group_order=order, context=context) return result From 729cd2ce023d8919aa1b250a4b51bf416cc12117 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Wed, 2 Apr 2014 17:08:17 +0200 Subject: [PATCH 049/140] [FIX] correct the expand functionality to avoid creating rows/cols in the other dimension of an unfolding action (addon web_graph) bzr revid: ged@openerp.com-20140402150817-5s8drvhbznxq0hh9 --- addons/web_graph/static/src/js/pivot_table.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index 824b41a6b25..9231765c485 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -223,7 +223,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ data = data.slice(other_gbs.length + 1, data.length); _.each(data, function (data_pt) { self.make_headers_and_cell( - data_pt, header.root.headers, other_root.headers, 1, header.path); + data_pt, header.root.headers, other_root.headers, 1, header.path, true); }); header.expanded = true; header.children.forEach(function (child) { @@ -271,12 +271,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ }); }, - make_headers_and_cell: function (data_pts, row_headers, col_headers, index, prefix) { + make_headers_and_cell: function (data_pts, row_headers, col_headers, index, prefix, expand) { var self = this; data_pts.forEach(function (data_pt) { var row_value = (prefix || []).concat(data_pt.attributes.value.slice(0,index)); var col_value = data_pt.attributes.value.slice(index); + if (expand && !_.find(col_headers, function (hdr) {return _.isEqual(col_value, hdr.path);})) { + return; + } var row = self.find_or_create_header(row_headers, row_value, data_pt); var col = self.find_or_create_header(col_headers, col_value, data_pt); From 8bf8e8a01c96106b59793c0baef6875ee1ceee17 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 2 Apr 2014 18:13:49 +0200 Subject: [PATCH 050/140] [FIX] website ir_qweb: do not crash if request is not bound when rendering a template bzr revid: sle@openerp.com-20140402161349-ecm6pit20j44taf1 --- addons/website/models/ir_ui_view.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py index 67781cc02a0..c9fadade6ed 100644 --- a/addons/website/models/ir_ui_view.py +++ b/addons/website/models/ir_ui_view.py @@ -123,7 +123,7 @@ class view(osv.osv): return arch def render(self, cr, uid, id_or_xml_id, values=None, engine='ir.qweb', context=None): - if getattr(request, 'website_enabled', False): + if request and getattr(request, 'website_enabled', False): engine='website.qweb' if isinstance(id_or_xml_id, list): From 2c90fad7ac735a71b65c905ad6489906a33a3575 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 2 Apr 2014 18:23:44 +0200 Subject: [PATCH 051/140] [REF][IMP] report module: merge the four report's routes into one; extra report arguments are passed json encoded (therefore removed the _eval_params method); added an abstract_report model to wrap old-style report without touching them; Removed formatLang method from report as it is embeded in the old-style report localcontext; moved the save_in_attachment logic in a method for readability; adapted the action manager to encode data and context of action if needed; fixed the post install test to test the generic report bzr revid: sle@openerp.com-20140402162344-3lrako0jepmhasvl --- addons/report/controllers/main.py | 115 +++----- addons/report/models/__init__.py | 1 + addons/report/models/abstract_report.py | 60 ++++ addons/report/models/report.py | 268 +++++------------- .../report/static/src/js/qwebactionmanager.js | 52 ++-- addons/report/tests/test_reports.py | 50 ++-- 6 files changed, 227 insertions(+), 319 deletions(-) create mode 100644 addons/report/models/abstract_report.py diff --git a/addons/report/controllers/main.py b/addons/report/controllers/main.py index f8435ba8245..d3a683cccdc 100644 --- a/addons/report/controllers/main.py +++ b/addons/report/controllers/main.py @@ -22,48 +22,43 @@ from openerp.addons.web.http import Controller, route, request import simplejson -import urlparse -from werkzeug import exceptions +from werkzeug import exceptions, url_decode +from werkzeug.test import Client +from werkzeug.wrappers import BaseResponse +from werkzeug.datastructures import Headers from reportlab.graphics.barcode import createBarcodeDrawing class ReportController(Controller): #------------------------------------------------------ - # Generic reports controller + # Report controllers #------------------------------------------------------ - @route('/report//', type='http', auth='user', website=True, multilang=True) - def report_html(self, reportname, docids): - cr, uid, context = request.cr, request.uid, request.context - docids = self._eval_params(docids) - return request.registry['report'].get_html(cr, uid, docids, reportname, context=context) - - @route('/report/pdf/report//', type='http', auth="user", website=True) - def report_pdf(self, reportname, docids): - cr, uid, context = request.cr, request.uid, request.context - docids = self._eval_params(docids) - pdf = request.registry['report'].get_pdf(cr, uid, docids, reportname, context=context) - pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] - return request.make_response(pdf, headers=pdfhttpheaders) - - #------------------------------------------------------ - # Particular reports controller - #------------------------------------------------------ - @route('/report/', type='http', auth='user', website=True, multilang=True) - def report_html_particular(self, reportname, **data): - cr, uid, context = request.cr, request.uid, request.context + @route([ + '/report//', + '/report///', + ], type='http', auth='user', website=True, multilang=True) + def report_routes(self, reportname, docids=None, converter=None, **data): report_obj = request.registry['report'] - data = self._eval_params(data) # Sanitizing - return report_obj.get_html(cr, uid, [], reportname, data=data, context=context) - - @route('/report/pdf/report/', type='http', auth='user', website=True, multilang=True) - def report_pdf_particular(self, reportname, **data): cr, uid, context = request.cr, request.uid, request.context - report_obj = request.registry['report'] - data = self._eval_params(data) # Sanitizing - pdf = report_obj.get_pdf(cr, uid, [], reportname, data=data, context=context) - pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] - return request.make_response(pdf, headers=pdfhttpheaders) + + if docids: + docids = [int(i) for i in docids.split(',')] + options_data = None + if data.get('options'): + options_data = simplejson.loads(data['options']) + if data.get('context'): + context.update(simplejson.loads(data['context'])) + + if converter == 'html': + html = report_obj.get_html(cr, uid, docids, reportname, data=options_data, context=context) + return request.make_response(html) + elif converter == 'pdf': + pdf = report_obj.get_pdf(cr, uid, docids, reportname, data=options_data, context=context) + pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))] + return request.make_response(pdf, headers=pdfhttpheaders) + else: + raise exceptions.HTTPException(description='Converter %s not implemented.' % converter) #------------------------------------------------------ # Misc. route utils @@ -94,7 +89,7 @@ class ReportController(Controller): @route(['/report/download'], type='http', auth="user", website=True) def report_download(self, data, token): """This function is used by 'qwebactionmanager.js' in order to trigger the download of - a pdf report. + a pdf/controller report. :param data: a javascript array JSON.stringified containg report internal url ([0]) and type [1] @@ -102,26 +97,26 @@ class ReportController(Controller): """ requestcontent = simplejson.loads(data) url, type = requestcontent[0], requestcontent[1] - if type == 'qweb-pdf': - reportname = url.split('/report/pdf/report/')[1].split('?')[0].split('/')[0] - if '?' not in url: + if type == 'qweb-pdf': + reportname = url.split('/report/pdf/')[1].split('?')[0] + + docids = None + if '/' in reportname: + reportname, docids = reportname.split('/') + + if docids: # Generic report: - docids = url.split('/')[-1] - response = self.report_pdf(reportname, docids) + response = self.report_routes(reportname, docids=docids, converter='pdf') else: # Particular report: - querystring = url.split('?')[1] - querystring = dict(urlparse.parse_qsl(querystring)) - response = self.report_pdf_particular(reportname, **querystring) + data = url_decode(url.split('?')[1]).items() # decoding the args represented in JSON + response = self.report_routes(reportname, converter='pdf', **dict(data)) response.headers.add('Content-Disposition', 'attachment; filename=%s.pdf;' % reportname) response.set_cookie('fileToken', token) return response elif type =='controller': - from werkzeug.test import Client - from werkzeug.wrappers import BaseResponse - from werkzeug.datastructures import Headers reqheaders = Headers(request.httprequest.headers) response = Client(request.httprequest.app, BaseResponse).get(url, headers=reqheaders, follow_redirects=True) response.set_cookie('fileToken', token) @@ -132,33 +127,3 @@ class ReportController(Controller): @route(['/report/check_wkhtmltopdf'], type='json', auth="user") def check_wkhtmltopdf(self): return request.registry['report']._check_wkhtmltopdf() - - def _eval_params(self, param): - """Parse a dict generated by the webclient (javascript) into a python dict. - """ - if isinstance(param, dict): - for key, value in param.iteritems(): - if value.lower() == 'false': - param[key] = False - elif value.lower() == 'true': - param[key] = True - elif ',' in value: - try: - param[key] = [int(i) for i in value.split(',')] - except ValueError: - param[key] = value.split(',') - if len(param[key]) == 1: - param[key] = value - else: - try: - param[key] = int(value) - except (ValueError, TypeError): - continue - else: - if isinstance(param, (str, unicode)): - param = [int(i) for i in param.split(',')] - if isinstance(param, list): - param = list(set(param)) - if isinstance(param, int): - param = [param] - return param diff --git a/addons/report/models/__init__.py b/addons/report/models/__init__.py index e048e10eb91..d21f03e5bcb 100644 --- a/addons/report/models/__init__.py +++ b/addons/report/models/__init__.py @@ -1,2 +1,3 @@ import report import report_paperformat +import abstract_report diff --git a/addons/report/models/abstract_report.py b/addons/report/models/abstract_report.py new file mode 100644 index 00000000000..c84ce1cac50 --- /dev/null +++ b/addons/report/models/abstract_report.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# 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 . +# +############################################################################## + +from openerp.osv import osv + + +class AbstractReport(osv.AbstractModel): + """Model used to embed old style reports""" + _name = 'report.abstract_report' + _template = None + _wrapped_report_class = None + + def render_html(self, cr, uid, ids, data=None, context=None): + if context is None: + context = {} + + # If the key 'landscape' is present in data['form'], passing it into the context + if data and data.get('form', {}).get('landscape'): + context['landscape'] = True + + if context and context.get('active_ids'): + # Browse the selected objects via their reference in context + model = context.get('active_model') or context.get('model') + objects_model = self.pool[model] + objects = objects_model.browse(cr, uid, context['active_ids'], context=context) + else: + # If no context is set (for instance, during test execution), build one + model = self.pool['report']._get_report_from_name(cr, uid, self._template).model + objects_model = self.pool[model] + objects = objects_model.browse(cr, uid, ids, context=context) + context['active_model'] = model + context['active_ids'] = ids + + # Generate the old style report + wrapped_report = self._wrapped_report_class(cr, uid, '', context=context) + wrapped_report.set_context(objects, data, ids) + + # Rendering self._template with the wrapped report instance localcontext as + # rendering environment + docargs = wrapped_report.localcontext + docargs['docs'] = docargs.get('objects') + return self.pool['report'].render(cr, uid, [], self._template, docargs, context=context) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index b93bbe09f89..992842ffacd 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -20,9 +20,8 @@ ############################################################################## from openerp.osv import osv +from openerp.tools import config from openerp.tools.translate import _ -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, config -from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field import os import time @@ -34,8 +33,6 @@ import tempfile import lxml.html import cStringIO import subprocess -from datetime import datetime -from functools import partial from distutils.version import LooseVersion try: from pyPdf import PdfFileWriter, PdfFileReader @@ -46,7 +43,7 @@ except ImportError: _logger = logging.getLogger(__name__) -"""Check the presence of wkhtmltopdf and return its version.""" +"""Check the presence of wkhtmltopdf and return its version at OpnerERP start-up.""" wkhtmltopdf_state = 'install' try: process = subprocess.Popen( @@ -70,106 +67,26 @@ class Report(osv.Model): public_user = None + MINIMAL_HTML_PAGE = """ + + + + + + + + + + {subst} + + + {body} + +""" + #-------------------------------------------------------------------------- # Extension of ir_ui_view.render with arguments frequently used in reports #-------------------------------------------------------------------------- - - def _get_digits(self, cr=None, uid=None, obj=None, f=None, dp=None): - d = DEFAULT_DIGITS = 2 - if dp: - decimal_precision_obj = self.pool['decimal.precision'] - ids = decimal_precision_obj.search(cr, uid, [('name', '=', dp)]) - if ids: - d = decimal_precision_obj.browse(cr, uid, ids)[0].digits - elif obj and f: - res_digits = getattr(obj._columns[f], 'digits', lambda x: ((16, DEFAULT_DIGITS))) - if isinstance(res_digits, tuple): - d = res_digits[1] - else: - d = res_digits(cr)[1] - elif (hasattr(obj, '_field') and - isinstance(obj._field, (float_field, function_field)) and - obj._field.digits): - d = obj._field.digits[1] or DEFAULT_DIGITS - return d - - def _get_lang_dict(self, cr, uid): - pool_lang = self.pool['res.lang'] - lang = self.localcontext.get('lang', 'en_US') or 'en_US' - lang_ids = pool_lang.search(cr, uid, [('code', '=', lang)])[0] - lang_obj = pool_lang.browse(cr, uid, lang_ids) - lang_dict = { - 'lang_obj': lang_obj, - 'date_format': lang_obj.date_format, - 'time_format': lang_obj.time_format - } - self.lang_dict.update(lang_dict) - self.default_lang[lang] = self.lang_dict.copy() - return True - - def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False, dp=False, currency_obj=False, cr=None, uid=None): - """ - Assuming 'Account' decimal.precision=3: - formatLang(value) -> digits=2 (default) - formatLang(value, digits=4) -> digits=4 - formatLang(value, dp='Account') -> digits=3 - formatLang(value, digits=5, dp='Account') -> digits=5 - """ - def get_date_length(date_format=DEFAULT_SERVER_DATE_FORMAT): - return len((datetime.now()).strftime(date_format)) - - # In case we use formatLang on the model (and not in the rendering environment). - if not hasattr(self, 'land_ditct'): - self.localcontext = {} - self.lang_dict = {} - self.default_lang = {} - self._get_lang_dict(cr, uid) - self.lang_dict_called = True - - if digits is None: - if dp: - digits = self._get_digits(cr, uid, dp=dp) - else: - digits = self._get_digits(cr, uid, value) - - if isinstance(value, (str, unicode)) and not value: - return '' - - if not self.lang_dict_called: - self._get_lang_dict(cr, uid) - self.lang_dict_called = True - - if date or date_time: - if not str(value): - return '' - - date_format = self.lang_dict['date_format'] - parse_format = DEFAULT_SERVER_DATE_FORMAT - if date_time: - value = value.split('.')[0] - date_format = date_format + " " + self.lang_dict['time_format'] - parse_format = DEFAULT_SERVER_DATETIME_FORMAT - if isinstance(value, basestring): - # FIXME: the trimming is probably unreliable if format includes day/month names - # and those would need to be translated anyway. - date = datetime.strptime(value[:get_date_length(parse_format)], parse_format) - elif isinstance(value, time.struct_time): - date = datetime(*value[:6]) - else: - date = datetime(*value.timetuple()[:6]) - if date_time: - # Convert datetime values to the expected client/context timezone - date = datetime_field.context_timestamp(cr, uid, timestamp=date, context=self.localcontext) - return date.strftime(date_format.encode('utf-8')) - - res = self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary) - if currency_obj: - if currency_obj.position == 'after': - res = '%s %s' % (res, currency_obj.symbol) - elif currency_obj and currency_obj.position == 'before': - res = '%s %s' % (currency_obj.symbol, res) - return res - def render(self, cr, uid, ids, template, values=None, context=None): """Allow to render a QWeb template python-side. This function returns the 'ir.ui.view' render but embellish it with some variables/methods used in reports. @@ -183,15 +100,6 @@ class Report(osv.Model): if context is None: context = {} - self.lang_dict = self.default_lang = {} - self.lang_dict_called = False - self.localcontext = { - 'lang': context.get('lang'), - 'tz': context.get('tz'), - 'uid': context.get('uid'), - } - self._get_lang_dict(cr, uid) - view_obj = self.pool['ir.ui.view'] def render_doc(doc_id, model, template): @@ -217,22 +125,20 @@ class Report(osv.Model): qcontext['o'] = self.pool[model].browse(cr, uid, doc_id, context=ctx) return view_obj.render(cr, uid, template, qcontext, context=ctx) + user = self.pool['res.users'].browse(cr, uid, uid) values.update({ 'time': time, - 'formatLang': partial(self.formatLang, cr=cr, uid=uid), - 'get_digits': partial(self._get_digits, cr=cr, uid=uid), 'render_doc': render_doc, 'editable': True, # Will active inherit_branding - 'res_company': self.pool['res.users'].browse(cr, uid, uid).company_id, + 'user': user, + 'res_company': user.company_id, 'website': False, # Will be overidden by ir.ui.view if the request has website enabled }) - return view_obj.render(cr, uid, template, values, context=context) #-------------------------------------------------------------------------- - # Main reports methods + # Main report methods #-------------------------------------------------------------------------- - def get_html(self, cr, uid, ids, report_name, data=None, context=None): """This method generates and returns html version of a report. """ @@ -241,7 +147,7 @@ class Report(osv.Model): try: report_model_name = 'report.%s' % report_name particularreport_obj = self.pool[report_model_name] - return particularreport_obj.render_html(cr, uid, ids, data={'form': data}, context=context) + return particularreport_obj.render_html(cr, uid, ids, data=data, context=context) except KeyError: report = self._get_report_from_name(cr, uid, report_name) report_obj = self.pool[report.model] @@ -262,41 +168,12 @@ class Report(osv.Model): if html is None: html = self.get_html(cr, uid, ids, report_name, data=data, context=context) - html = html.decode('utf-8') + html = html.decode('utf-8') # Ensure the current document is utf-8 encoded. # Get the ir.actions.report.xml record we are working on. report = self._get_report_from_name(cr, uid, report_name) - - # Check attachment_use field. If set to true and an existing pdf is already saved, load - # this one now. Else, mark save it. - save_in_attachment = {} - - if report.attachment_use is True: - save_in_attachment['model'] = report.model - save_in_attachment['loaded_documents'] = {} - - for record_id in ids: - obj = self.pool[report.model].browse(cr, uid, record_id) - filename = eval(report.attachment, {'object': obj, 'time': time}) - - if filename is False: # May be false if, for instance, the record is in draft state - continue - else: - alreadyindb = [('datas_fname', '=', filename), - ('res_model', '=', report.model), - ('res_id', '=', record_id)] - - attach_ids = self.pool['ir.attachment'].search(cr, uid, alreadyindb) - if attach_ids: - # Add the loaded pdf in the loaded_documents list - pdf = self.pool['ir.attachment'].browse(cr, uid, attach_ids[0]).datas - pdf = base64.decodestring(pdf) - save_in_attachment['loaded_documents'][record_id] = pdf - _logger.info('The PDF document %s was loaded from the database' % filename) - else: - # Mark current document to be saved - save_in_attachment[id] = filename - + # Check if we have to save the report or if we have to get one from the db. + save_in_attachment = self._check_attachment_use(cr, uid, ids, report) # Get the paperformat associated to the report, otherwise fallback on the company one. if not report.paperformat_id: user = self.pool['res.users'].browse(cr, uid, uid) @@ -305,34 +182,15 @@ class Report(osv.Model): paperformat = report.paperformat_id # Preparing the minimal html pages - #subst = self._get_url_content('/report/static/src/js/subst.js')[0] # Used in age numbering subst = " " css = '' # Will contain local css - headerhtml = [] contenthtml = [] footerhtml = [] base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url') - minimalhtml = """ - - - - - - - - - - {subst} - - - {body} - -""" - - # The retrieved html report must be simplified. We convert it into a xml tree - # via lxml in order to extract headers, footers and content. + # The received html report must be simplified. We convert it in a xml tree + # in order to extract headers, bodies and footers. try: root = lxml.html.fromstring(html) @@ -341,12 +199,12 @@ class Report(osv.Model): for node in root.xpath("//div[@class='header']"): body = lxml.html.tostring(node) - header = minimalhtml.format(css=css, subst=subst, body=body, base_url=base_url) + header = self.MINIMAL_HTML_PAGE.format(css=css, subst=subst, body=body, base_url=base_url) headerhtml.append(header) for node in root.xpath("//div[@class='footer']"): body = lxml.html.tostring(node) - footer = minimalhtml.format(css=css, subst=subst, body=body, base_url=base_url) + footer = self.MINIMAL_HTML_PAGE.format(css=css, subst=subst, body=body, base_url=base_url) footerhtml.append(footer) for node in root.xpath("//div[@class='page']"): @@ -363,7 +221,7 @@ class Report(osv.Model): reportid = False body = lxml.html.tostring(node) - reportcontent = minimalhtml.format(css=css, subst='', body=body, base_url=base_url) + reportcontent = self.MINIMAL_HTML_PAGE.format(css=css, subst='', body=body, base_url=base_url) contenthtml.append(tuple([reportid, reportcontent])) except lxml.etree.XMLSyntaxError: @@ -390,37 +248,60 @@ class Report(osv.Model): :param report_name: Name of the template to generate an action for """ - # TODO: return the action for the ids passed in args if context is None: context = {} - if data is None: - data = {} - - report_obj = self.pool.get('ir.actions.report.xml') + report_obj = self.pool['ir.actions.report.xml'] idreport = report_obj.search(cr, uid, [('report_name', '=', report_name)], context=context) - try: report = report_obj.browse(cr, uid, idreport[0], context=context) except IndexError: - raise osv.except_osv(_('Bad Report'), - _('This report is not loaded into the database.')) + raise osv.except_osv(_('Bad Report'), _('This report is not loaded into the database.')) action = { + 'context': context, + 'data': data, 'type': 'ir.actions.report.xml', 'report_name': report.report_name, 'report_type': report.report_type, 'report_file': report.report_file, } - - if data: - action['datas'] = data - return action #-------------------------------------------------------------------------- # Report generation helpers #-------------------------------------------------------------------------- + def _check_attachment_use(self, cr, uid, ids, report): + """ Check attachment_use field. If set to true and an existing pdf is already saved, load + this one now. Else, mark save it. + """ + save_in_attachment = {} + if report.attachment_use is True: + save_in_attachment['model'] = report.model + save_in_attachment['loaded_documents'] = {} + + for record_id in ids: + obj = self.pool[report.model].browse(cr, uid, record_id) + filename = eval(report.attachment, {'object': obj, 'time': time}) + + if filename is False: # May be false if, for instance, the record is in draft state + continue + else: + alreadyindb = [('datas_fname', '=', filename), + ('res_model', '=', report.model), + ('res_id', '=', record_id)] + + attach_ids = self.pool['ir.attachment'].search(cr, uid, alreadyindb) + if attach_ids: + # Add the loaded pdf in the loaded_documents list + pdf = self.pool['ir.attachment'].browse(cr, uid, attach_ids[0]).datas + pdf = base64.decodestring(pdf) + save_in_attachment['loaded_documents'][record_id] = pdf + _logger.info('The PDF document %s was loaded from the database' % filename) + else: + # Mark current document to be saved + save_in_attachment[record_id] = filename + return save_in_attachment def _check_wkhtmltopdf(self): return wkhtmltopdf_state @@ -445,7 +326,8 @@ class Report(osv.Model): # Passing the cookie to wkhtmltopdf in order to resolve URL. try: from openerp.addons.web.http import request - command_args.extend(['--cookie', 'session_id', request.session.sid]) + if request: + command_args.extend(['--cookie', 'session_id', request.session.sid]) except AttributeError: pass @@ -453,6 +335,8 @@ class Report(osv.Model): if paperformat: command_args.extend(self._build_wkhtmltopdf_args(paperformat, spec_paperformat_args)) + command_args.extend(['--load-error-handling', 'ignore']) + if landscape and '--orientation' in command_args: command_args_copy = list(command_args) for index, elem in enumerate(command_args_copy): @@ -472,7 +356,7 @@ class Report(osv.Model): # Directly load the document if we have it if save_in_attachment and save_in_attachment['loaded_documents'].get(reporthtml[0]): pdfreport.write(save_in_attachment['loaded_documents'].get(reporthtml[0])) - pdfreport.flush() + pdfreport.seek(0) pdfdocuments.append(pdfreport) continue @@ -481,7 +365,7 @@ class Report(osv.Model): head_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.header.tmp.', dir=tmp_dir, mode='w+') head_file.write(headers[index]) - head_file.flush() + head_file.seek(0) command_arg_local.extend(['--header-html', head_file.name]) # Footer stuff @@ -489,14 +373,14 @@ class Report(osv.Model): foot_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.footer.tmp.', dir=tmp_dir, mode='w+') foot_file.write(footers[index]) - foot_file.flush() + foot_file.seek(0) command_arg_local.extend(['--footer-html', foot_file.name]) # Body stuff content_file = tempfile.NamedTemporaryFile(suffix='.html', prefix='report.body.tmp.', dir=tmp_dir, mode='w+') content_file.write(reporthtml[1]) - content_file.flush() + content_file.seek(0) try: # If the server is running with only one worker, ask to create a secund to be able @@ -533,7 +417,7 @@ class Report(osv.Model): _logger.info('The PDF document %s is now saved in the ' 'database' % attachment['name']) - pdfreport.flush() + pdfreport.seek(0) pdfdocuments.append(pdfreport) if headers: diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js index b75003942d2..aa98b2c9c52 100644 --- a/addons/report/static/src/js/qwebactionmanager.js +++ b/addons/report/static/src/js/qwebactionmanager.js @@ -6,8 +6,6 @@ openerp.report = function(instance) { var self = this; instance.web.blockUI(); action = _.clone(action); - var eval_contexts = ([instance.session.user_context] || []).concat([action.context]); - action.context = instance.web.pyeval.eval('contexts',eval_contexts); _t = instance.web._t; // QWeb reports @@ -15,43 +13,33 @@ openerp.report = function(instance) { var report_url = ''; switch (action.report_type) { case 'qweb-html': - report_url = '/report/' + action.report_name; + report_url = '/report/html/' + action.report_name; break; case 'qweb-pdf': - report_url = '/report/pdf/report/' + action.report_name; + report_url = '/report/pdf/' + action.report_name; break; case 'controller': report_url = action.report_file; break; default: - report_url = '/report/' + action.report_name; + report_url = '/report/html/' + action.report_name; break; } - // single/multiple id(s): no query string - // wizard: query string of action.datas.form - if (!('datas' in action)) { + // generic report: no query string + // particular: query string of action.data.form and context + if (!('data' in action) || !(action.data)) { if ('active_ids' in action.context) { report_url += "/" + action.context.active_ids.join(','); } } else { - _.each(action.datas.form, function(value, key) { - // will be erased when all wizards are rewritten - if (key.substring(0, 12) === 'used_context') { - delete action.datas.form[key]; - } - - if ($.type(value) === 'array') { - action.datas.form[key] = value.join(','); - } - }); - report_url += "?" + $.param(action.datas.form); + report_url += "?options=" + encodeURI(JSON.stringify(action.data)); + report_url += "&context=" + encodeURI(JSON.stringify(action.context)); } + if (action.report_type == 'qweb-html') { - // Open the html report in a popup window.open(report_url, '_blank', 'height=900,width=1280'); instance.web.unblockUI(); - return; } else { // Trigger the download of the pdf/controller report var c = openerp.webclient.crashmanager; @@ -68,6 +56,7 @@ openerp.report = function(instance) { wkhtmltopdf.org'), true); window.open(report_url.substring(12), '_blank', 'height=768,width=1024'); instance.web.unblockUI(); + return; } else { if (presence == 'upgrade') { self.do_notify(_t('Report'), _t('You should upgrade your version of\ @@ -75,22 +64,15 @@ openerp.report = function(instance) { support for table-breaking between pages.

    wkhtmltopdf.org'), true); } - self.session.get_file({ - url: '/report/download', - data: {data: JSON.stringify(response)}, - complete: openerp.web.unblockUI, - error: c.rpc_error.bind(c) - }); } }); - } else { - self.session.get_file({ - url: '/report/download', - data: {data: JSON.stringify(response)}, - complete: openerp.web.unblockUI, - error: c.rpc_error.bind(c) - }); - } + } + self.session.get_file({ + url: '/report/download', + data: {data: JSON.stringify(response)}, + complete: openerp.web.unblockUI, + error: c.rpc_error.bind(c) + }); } } else { return self._super(action, options); diff --git a/addons/report/tests/test_reports.py b/addons/report/tests/test_reports.py index dda14442709..b1853489573 100644 --- a/addons/report/tests/test_reports.py +++ b/addons/report/tests/test_reports.py @@ -1,5 +1,23 @@ # -*- coding: utf-8 -*- - +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# 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 . +# +############################################################################## import logging import openerp @@ -11,26 +29,24 @@ _logger = logging.getLogger(__name__) @openerp.tests.common.post_install(True) class TestReports(openerp.tests.TransactionCase): def test_reports(self): - return # commented out until post_install tests are working - registry, cr, uid = self.registry, self.cr, self.uid r_model = registry('ir.actions.report.xml') domain = [('report_type', 'like', 'qweb')] for r in r_model.browse(cr, uid, r_model.search(cr, uid, domain)): report_model = 'report.%s' % r.report_name - particular_model = registry('ir.model').search(cr, uid, [('model', '=', report_model)]) - + try: + registry(report_model) + except KeyError: # Only test the generic reports here - if particular_model: + _logger.info("testing report %s", r.report_name) + report_model = registry(r.model) + report_model_ids = report_model.search(cr, uid, [], limit=10) + if not report_model_ids: + _logger.info("no record found skipping report %s", r.report_name) + if not r.multi: + report_model_ids = report_model_ids[:1] + + # Test report generation + registry('report').get_html(cr, uid, report_model_ids, r.report_name) + else: continue - - _logger.info("testing report %s", r.report_name) - report_model = registry(r.model) - report_model_ids = report_model.search(cr, uid, [], limit=10) - if not report_model_ids: - _logger.info("no record found skipping report %s", r.report_name) - if not r.multi: - report_model_ids = report_model_ids[:1] - - # Test report generation - registry('report').get_html(cr, uid, report_model_ids, r.report_name) From 106d06ce5d14f5d3cad573d95ad8ed8dc19eb5b6 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Wed, 2 Apr 2014 18:40:53 +0200 Subject: [PATCH 052/140] [IMP] account* reports: removed unused class/report/commented code/test, added the abstract_report wrapper on all old style report classes + some fixes on views and wizards in order to use these classes to render the qweb reports bzr revid: sle@openerp.com-20140402164053-gry12scy8zca68lv --- .../account/project/report/account_journal.py | 49 ------- .../project/report/analytic_balance.py | 15 +- .../project/report/analytic_journal.py | 10 +- addons/account/project/report/cost_ledger.py | 10 +- .../report/inverted_analytic_balance.py | 9 +- .../project/report/quantity_cost_ledger.py | 13 +- .../project/views/report_analyticbalance.xml | 20 +-- .../views/report_analyticcostledger.xml | 20 +-- .../report_analyticcostledgerquantity.xml | 12 +- .../project/views/report_analyticjournal.xml | 16 +-- .../views/report_invertedanalyticbalance.xml | 12 +- ...analytic_cost_ledger_for_journal_report.py | 1 - ...ccount_analytic_inverted_balance_report.py | 2 - .../report/account_aged_partner_balance.py | 9 +- addons/account/report/account_balance.py | 14 +- .../account/report/account_central_journal.py | 10 +- .../report/account_financial_report.py | 9 +- .../account/report/account_general_journal.py | 11 +- .../account/report/account_general_ledger.py | 10 +- addons/account/report/account_journal.py | 19 ++- .../account/report/account_partner_balance.py | 10 +- .../account/report/account_partner_ledger.py | 23 ++-- .../account/report/account_print_overdue.py | 32 ++++- addons/account/report/report_vat.py | 129 ++++++++---------- addons/account/test/account_report.yml | 9 +- .../views/report_agedpartnerbalance.xml | 10 +- addons/account/views/report_overdue.xml | 1 + addons/account/views/report_vat.xml | 2 +- .../wizard/account_financial_report.py | 2 - .../wizard/account_report_partner_ledger.py | 2 + addons/account_analytic_plans/__openerp__.py | 2 +- .../report/crossovered_analytic.py | 11 +- .../test/acount_analytic_plans_report.yml | 2 +- .../views/report_crossoveredanalyticplans.xml | 4 +- .../report/bank_statement_balance_report.py | 19 ++- .../report/analytic_account_budget_report.py | 11 +- addons/account_budget/report/budget_report.py | 8 +- .../report/crossovered_budget_report.py | 14 +- .../test/account_budget_report.yml | 25 +--- .../report/check_print.py | 29 ++-- addons/account_followup/account_followup.py | 7 +- .../report/account_followup_print.py | 12 +- .../wizard/account_followup_print.py | 8 +- .../account_payment/report/payment_order.py | 10 +- .../test/account_payment_report.yml | 2 +- .../report/account_test_report.py | 11 +- addons/account_voucher/__openerp__.py | 2 - .../account_voucher_report.xml | 23 ---- addons/account_voucher/report/__init__.py | 2 - .../account_voucher/report/account_voucher.py | 75 ---------- .../report/account_voucher_print.py | 96 ------------- .../test/account_voucher_report.yml | 27 ---- addons/lunch/report/order.py | 29 ++-- addons/mrp/report/bom_structure.py | 29 ++-- .../test/report_intrastat_report.yml | 2 +- 55 files changed, 379 insertions(+), 572 deletions(-) delete mode 100644 addons/account/project/report/account_journal.py delete mode 100644 addons/account_voucher/account_voucher_report.xml delete mode 100644 addons/account_voucher/report/account_voucher.py delete mode 100644 addons/account_voucher/report/account_voucher_print.py delete mode 100644 addons/account_voucher/test/account_voucher_report.yml diff --git a/addons/account/project/report/account_journal.py b/addons/account/project/report/account_journal.py deleted file mode 100644 index 50f98fd0ee0..00000000000 --- a/addons/account/project/report/account_journal.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - - -import time -from openerp.report import report_sxw - -# -# Use period and Journal for selection or resources -# -class journal_print(report_sxw.rml_parse): - def lines(self, journal_id, *args): - self.cr.execute('select id from account_analytic_line where journal_id=%s order by date,id', (journal_id,)) - ids = map(lambda x: x[0], self.cr.fetchall()) - res = self.pool.get('account.analytic.line').browse(self.cr, self.uid, ids) - return res - def _sum_lines(self, journal_id): - self.cr.execute('select sum(amount) from account_analytic_line where journal_id=%s', (journal_id,)) - return self.cr.fetchone()[0] or 0.0 - def __init__(self, cr, uid, name, context): - super(journal_print, self).__init__(cr, uid, name, context=context) - self.localcontext = { - 'time': time, - 'lines': self.lines, - 'sum_lines': self._sum_lines, - } -report_sxw.report_sxw('report.account.analytic.journal.print', 'account.analytic.journal', 'addons/account/project/report/analytic_journal.rml',parser=journal_print) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/analytic_balance.py b/addons/account/project/report/analytic_balance.py index 2aa9f2c549e..7c333b84c45 100644 --- a/addons/account/project/report/analytic_balance.py +++ b/addons/account/project/report/analytic_balance.py @@ -20,7 +20,7 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw @@ -56,7 +56,6 @@ class account_analytic_balance(report_sxw.rml_parse): self.get_children(data['child_ids']) return True - def _get_objects(self, empty_acc): if self.read_data: return self.read_data @@ -143,18 +142,16 @@ class account_analytic_balance(report_sxw.rml_parse): WHERE account_id IN %s AND date>=%s AND date<=%s",query_params) return self.cr.fetchone()[0] or 0.0 - - def _sum_balance(self, accounts, date1, date2): debit = self._sum_all(accounts, date1, date2, 'debit') or 0.0 credit = self._sum_all(accounts, date1, date2, 'credit') or 0.0 return (debit-credit) -report_sxw.report_sxw('report.account.analytic.account.balance', - 'account.analytic.account', 'addons/account/project/report/analytic_balance.rml', - parser=account_analytic_balance, header="internal") - +class report_analyticbalance(osv.AbstractModel): + _name = 'report.account.report_analyticbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticbalance' + _wrapped_report_class = account_analytic_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/analytic_journal.py b/addons/account/project/report/analytic_journal.py index 1ca1ffb3ca4..c59efb057d7 100644 --- a/addons/account/project/report/analytic_journal.py +++ b/addons/account/project/report/analytic_journal.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + # # Use period and Journal for selection or resources # @@ -57,8 +58,11 @@ class account_analytic_journal(report_sxw.rml_parse): res = self.cr.dictfetchone() return res['sum'] or 0 -report_sxw.report_sxw('report.account.analytic.journal', 'account.analytic.journal', 'addons/account/project/report/analytic_journal.rml',parser=account_analytic_journal,header="internal") +class report_analyticjournal(osv.AbstractModel): + _name = 'report.account.report_analyticjournal' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticjournal' + _wrapped_report_class = account_analytic_journal # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/cost_ledger.py b/addons/account/project/report/cost_ledger.py index e594ab92a63..5eef375eaab 100644 --- a/addons/account/project/report/cost_ledger.py +++ b/addons/account/project/report/cost_ledger.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class account_analytic_cost_ledger(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(account_analytic_cost_ledger, self).__init__(cr, uid, name, context=context) @@ -100,8 +101,11 @@ class account_analytic_cost_ledger(report_sxw.rml_parse): credit = self._sum_credit(accounts, date1, date2) return (debit-credit) -report_sxw.report_sxw('report.account.analytic.account.cost_ledger', 'account.analytic.account', 'addons/account/project/report/cost_ledger.rml',parser=account_analytic_cost_ledger, header="internal") +class report_analyticcostledger(osv.AbstractModel): + _name = 'report.account.report_analyticcostledger' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticcostledger' + _wrapped_report_class = account_analytic_cost_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/inverted_analytic_balance.py b/addons/account/project/report/inverted_analytic_balance.py index bd86bcfe257..23129144555 100644 --- a/addons/account/project/report/inverted_analytic_balance.py +++ b/addons/account/project/report/inverted_analytic_balance.py @@ -20,7 +20,7 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw class account_inverted_analytic_balance(report_sxw.rml_parse): @@ -120,8 +120,11 @@ class account_inverted_analytic_balance(report_sxw.rml_parse): WHERE account_id IN %s AND date>=%s AND date<=%s", (tuple(ids),date1, date2,)) return self.cr.fetchone()[0] or 0.0 -report_sxw.report_sxw('report.account.analytic.account.inverted.balance', 'account.analytic.account', 'addons/account/project/report/inverted_analytic_balance.rml',parser=account_inverted_analytic_balance, header="internal") +class report_invertedanalyticbalance(osv.AbstractModel): + _name = 'report.account.report_invertedanalyticbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_invertedanalyticbalance' + _wrapped_report_class = account_inverted_analytic_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account/project/report/quantity_cost_ledger.py b/addons/account/project/report/quantity_cost_ledger.py index b22558b900f..d3ed1cdc3a8 100644 --- a/addons/account/project/report/quantity_cost_ledger.py +++ b/addons/account/project/report/quantity_cost_ledger.py @@ -19,9 +19,10 @@ # ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class account_analytic_quantity_cost_ledger(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(account_analytic_quantity_cost_ledger, self).__init__(cr, uid, name, context=context) @@ -116,9 +117,11 @@ class account_analytic_quantity_cost_ledger(report_sxw.rml_parse): AND journal_id IN %s",(tuple(ids), date1, date2, tuple(journal_ids))) return self.cr.fetchone()[0] or 0.0 -report_sxw.report_sxw('report.account.analytic.account.quantity_cost_ledger', - 'account.analytic.account', - 'addons/account/project/report/quantity_cost_ledger.rml', - parser=account_analytic_quantity_cost_ledger, header="internal") + +class report_analyticcostledgerquantity(osv.AbstractModel): + _name = 'report.account.report_analyticcostledgerquantity' + _inherit = 'report.abstract_report' + _template = 'account.report_analyticcostledgerquantity' + _wrapped_report_class = account_analytic_quantity_cost_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/views/report_analyticbalance.xml b/addons/account/project/views/report_analyticbalance.xml index 96f692eda3d..09cd56fc83f 100644 --- a/addons/account/project/views/report_analyticbalance.xml +++ b/addons/account/project/views/report_analyticbalance.xml @@ -22,28 +22,28 @@ Total - + - + - + - + - + - - - - + + + + - + diff --git a/addons/account/project/views/report_analyticcostledger.xml b/addons/account/project/views/report_analyticcostledger.xml index fd99c637411..cda37d4158f 100644 --- a/addons/account/project/views/report_analyticcostledger.xml +++ b/addons/account/project/views/report_analyticcostledger.xml @@ -10,11 +10,11 @@
    Period From: -

    +

    Period To: -

    +

    Printing Date: @@ -38,10 +38,10 @@ Total: - - + + - + @@ -50,12 +50,12 @@ - - - + + + - + @@ -66,7 +66,7 @@ - + diff --git a/addons/account/project/views/report_analyticcostledgerquantity.xml b/addons/account/project/views/report_analyticcostledgerquantity.xml index 1098a7627f3..de49d4972e5 100644 --- a/addons/account/project/views/report_analyticcostledgerquantity.xml +++ b/addons/account/project/views/report_analyticcostledgerquantity.xml @@ -10,11 +10,11 @@
    Period From: -

    +

    Period To: -

    +

    Printing Date: @@ -39,7 +39,7 @@ - + @@ -54,11 +54,11 @@

    - + - + @@ -66,7 +66,7 @@ - + diff --git a/addons/account/project/views/report_analyticjournal.xml b/addons/account/project/views/report_analyticjournal.xml index ce2f216e419..1b3a4fda97c 100644 --- a/addons/account/project/views/report_analyticjournal.xml +++ b/addons/account/project/views/report_analyticjournal.xml @@ -11,11 +11,11 @@
    Period From: -

    +

    Period To: -

    +

    Currency: @@ -35,12 +35,12 @@ - - - + + - + @@ -56,7 +56,7 @@ - + @@ -71,13 +71,13 @@ - +

    - - + diff --git a/addons/account/project/views/report_invertedanalyticbalance.xml b/addons/account/project/views/report_invertedanalyticbalance.xml index 7ed8f4f84f3..e545ec8525b 100644 --- a/addons/account/project/views/report_invertedanalyticbalance.xml +++ b/addons/account/project/views/report_invertedanalyticbalance.xml @@ -22,14 +22,14 @@ Total - - + + - + - + - + @@ -58,7 +58,7 @@ - + diff --git a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py index b3c2d1bec12..125dfda46fb 100644 --- a/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py +++ b/addons/account/project/wizard/account_analytic_cost_ledger_for_journal_report.py @@ -49,7 +49,6 @@ class account_analytic_cost_ledger_journal_report(osv.osv_memory): } datas['form']['active_ids'] = context.get('active_ids', False) - return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticcostledgerquantity', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/project/wizard/account_analytic_inverted_balance_report.py b/addons/account/project/wizard/account_analytic_inverted_balance_report.py index 3b03ad2da56..ad79c0b33f6 100644 --- a/addons/account/project/wizard/account_analytic_inverted_balance_report.py +++ b/addons/account/project/wizard/account_analytic_inverted_balance_report.py @@ -46,9 +46,7 @@ class account_analytic_inverted_balance(osv.osv_memory): 'model': 'account.analytic.account', 'form': data } - datas['form']['active_ids'] = context.get('active_ids', False) - return self.pool['report'].get_action(cr, uid, ids, 'account.report_invertedanalyticbalance', data=datas, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py index 3b000e40592..3fd83c19207 100644 --- a/addons/account/report/account_aged_partner_balance.py +++ b/addons/account/report/account_aged_partner_balance.py @@ -20,9 +20,11 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header + class aged_trial_report(report_sxw.rml_parse, common_report_header): def __init__(self, cr, uid, name, context): @@ -375,8 +377,11 @@ class aged_trial_report(report_sxw.rml_parse, common_report_header): return self._translate('Receivable and Payable Accounts') return '' -report_sxw.report_sxw('report.account.aged_trial_balance', 'res.partner', - 'addons/account/report/account_aged_partner_balance.rml',parser=aged_trial_report, header="internal landscape") +class report_agedpartnerbalance(osv.AbstractModel): + _name = 'report.account.report_agedpartnerbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_agedpartnerbalance' + _wrapped_report_class = aged_trial_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_balance.py b/addons/account/report/account_balance.py index 2a445984b27..af2c37fc610 100644 --- a/addons/account/report/account_balance.py +++ b/addons/account/report/account_balance.py @@ -21,9 +21,11 @@ import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header + class account_balance(report_sxw.rml_parse, common_report_header): _name = 'report.account.account.balance' @@ -58,11 +60,6 @@ class account_balance(report_sxw.rml_parse, common_report_header): objects = self.pool.get('account.account').browse(self.cr, self.uid, new_ids) return super(account_balance, self).set_context(objects, data, new_ids, report_type=report_type) - #def _add_header(self, node, header=1): - # if header == 0: - # self.rml_header = "" - # return True - def _get_account(self, data): if data['model']=='account.account': return self.pool.get('account.account').browse(self.cr, self.uid, data['form']['id']).company_id.name @@ -131,6 +128,11 @@ class account_balance(report_sxw.rml_parse, common_report_header): _process_child(accounts,form['display_account'],parent) return self.result_acc -report_sxw.report_sxw('report.account.account.balance', 'account.account', 'addons/account/report/account_balance.rml', parser=account_balance, header="internal") + +class report_trialbalance(osv.AbstractModel): + _name = 'report.account.report_trialbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_trialbalance' + _wrapped_report_class = account_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_central_journal.py b/addons/account/report/account_central_journal.py index 8dae208a7a5..28892d0730e 100644 --- a/addons/account/report/account_central_journal.py +++ b/addons/account/report/account_central_journal.py @@ -20,11 +20,14 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header # # Use period and Journal for selection or resources # + + class journal_print(report_sxw.rml_parse, common_report_header): def __init__(self, cr, uid, name, context=None): @@ -103,6 +106,11 @@ class journal_print(report_sxw.rml_parse, common_report_header): return True return data['form']['amount_currency'] -report_sxw.report_sxw('report.account.central.journal', 'account.journal.period', 'addons/account/report/account_central_journal.rml', parser=journal_print, header='external') + +class report_agedpartnerbalance(osv.AbstractModel): + _name = 'report.account.report_centraljournal' + _inherit = 'report.abstract_report' + _template = 'account.report_centraljournal' + _wrapped_report_class = journal_print # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_financial_report.py b/addons/account/report/account_financial_report.py index 2b1f5af4d68..064f02c5fbf 100644 --- a/addons/account/report/account_financial_report.py +++ b/addons/account/report/account_financial_report.py @@ -23,6 +23,8 @@ import time from openerp.report import report_sxw from common_report_header import common_report_header from openerp.tools.translate import _ +from openerp.osv import osv + class report_account_common(report_sxw.rml_parse, common_report_header): @@ -105,8 +107,11 @@ class report_account_common(report_sxw.rml_parse, common_report_header): lines.append(vals) return lines -report_sxw.report_sxw('report.account.financial.report', 'account.financial.report', - 'addons/account/report/account_financial_report.rml', parser=report_account_common, header='internal') +class report_financial(osv.AbstractModel): + _name = 'report.account.report_financial' + _inherit = 'report.abstract_report' + _template = 'account.report_financial' + _wrapped_report_class = report_account_common # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_general_journal.py b/addons/account/report/account_general_journal.py index 4f63411478c..ada615e31fa 100644 --- a/addons/account/report/account_general_journal.py +++ b/addons/account/report/account_general_journal.py @@ -20,8 +20,10 @@ ############################################################################## import time -from common_report_header import common_report_header +from openerp.osv import osv from openerp.report import report_sxw +from common_report_header import common_report_header + class journal_print(report_sxw.rml_parse, common_report_header): @@ -156,6 +158,11 @@ class journal_print(report_sxw.rml_parse, common_report_header): (tuple(move_state), period_id, tuple(journals))) return self.cr.fetchone()[0] or 0.0 -report_sxw.report_sxw('report.account.general.journal', 'account.journal.period', 'addons/account/report/general_journal.rml', parser=journal_print, header='internal') + +class report_generaljournal(osv.AbstractModel): + _name = 'report.account.report_generaljournal' + _inherit = 'report.abstract_report' + _template = 'account.report_generaljournal' + _wrapped_report_class = journal_print # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_general_ledger.py b/addons/account/report/account_general_ledger.py index 4f712ad58cc..ffccbec300d 100644 --- a/addons/account/report/account_general_ledger.py +++ b/addons/account/report/account_general_ledger.py @@ -28,9 +28,11 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw from common_report_header import common_report_header + class general_ledger(report_sxw.rml_parse, common_report_header): _name = 'report.account.general.ledger' @@ -304,7 +306,11 @@ class general_ledger(report_sxw.rml_parse, common_report_header): return self._translate('Journal & Partner') return self._translate('Date') -report_sxw.report_sxw('report.account.general.ledger', 'account.account', 'addons/account/report/account_general_ledger.rml', parser=general_ledger, header='internal') -report_sxw.report_sxw('report.account.general.ledger_landscape', 'account.account', 'addons/account/report/account_general_ledger_landscape.rml', parser=general_ledger, header='internal landscape') + +class report_generalledger(osv.AbstractModel): + _name = 'report.account.report_generalledger' + _inherit = 'report.abstract_report' + _template = 'account.report_generalledger' + _wrapped_report_class = general_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_journal.py b/addons/account/report/account_journal.py index 97e19be4b0c..13dfd538f4a 100644 --- a/addons/account/report/account_journal.py +++ b/addons/account/report/account_journal.py @@ -20,8 +20,10 @@ ############################################################################## import time -from common_report_header import common_report_header +from openerp.osv import osv from openerp.report import report_sxw +from common_report_header import common_report_header + class journal_print(report_sxw.rml_parse, common_report_header): @@ -196,7 +198,18 @@ class journal_print(report_sxw.rml_parse, common_report_header): return self._translate('Reference Number') return self._translate('Date') -report_sxw.report_sxw('report.account.journal.period.print', 'account.journal.period', 'addons/account/report/account_journal.rml', parser=journal_print, header='external') -report_sxw.report_sxw('report.account.journal.period.print.sale.purchase', 'account.journal.period', 'addons/account/report/account_journal_sale_purchase.rml', parser=journal_print, header='external') + +class report_journal(osv.AbstractModel): + _name = 'report.account.report_journal' + _inherit = 'report.abstract_report' + _template = 'account.report_journal' + _wrapped_report_class = journal_print + + +class report_salepurchasejournal(osv.AbstractModel): + _name = 'report.account.report_salepurchasejournal' + _inherit = 'report.abstract_report' + _template = 'account.report_salepurchasejournal' + _wrapped_report_class = journal_print # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_partner_balance.py b/addons/account/report/account_partner_balance.py index 53edbbe9685..ecd287551e5 100644 --- a/addons/account/report/account_partner_balance.py +++ b/addons/account/report/account_partner_balance.py @@ -20,11 +20,12 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.tools.translate import _ from openerp.report import report_sxw from common_report_header import common_report_header + class partner_balance(report_sxw.rml_parse, common_report_header): def __init__(self, cr, uid, name, context=None): @@ -301,6 +302,11 @@ class partner_balance(report_sxw.rml_parse, common_report_header): return _('Receivable and Payable Accounts') return '' -report_sxw.report_sxw('report.account.partner.balance', 'res.partner', 'account/report/account_partner_balance.rml',parser=partner_balance, header="internal") + +class report_partnerbalance(osv.AbstractModel): + _name = 'report.account.report_partnerbalance' + _inherit = 'report.abstract_report' + _template = 'account.report_partnerbalance' + _wrapped_report_class = partner_balance # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_partner_ledger.py b/addons/account/report/account_partner_ledger.py index d21323e02fc..f02ac96b6fc 100644 --- a/addons/account/report/account_partner_ledger.py +++ b/addons/account/report/account_partner_ledger.py @@ -20,10 +20,11 @@ ############################################################################## import time -import re +from openerp.osv import osv +from openerp.tools.translate import _ from openerp.report import report_sxw from common_report_header import common_report_header -from openerp.tools.translate import _ + class third_party_ledger(report_sxw.rml_parse, common_report_header): @@ -297,12 +298,18 @@ class third_party_ledger(report_sxw.rml_parse, common_report_header): return True return False -report_sxw.report_sxw('report.account.third_party_ledger', 'res.partner', - 'addons/account/report/account_partner_ledger.rml',parser=third_party_ledger, - header='internal') -report_sxw.report_sxw('report.account.third_party_ledger_other', 'res.partner', - 'addons/account/report/account_partner_ledger_other.rml',parser=third_party_ledger, - header='internal') +class report_partnerledger(osv.AbstractModel): + _name = 'report.account.report_partnerledger' + _inherit = 'report.abstract_report' + _template = 'account.report_partnerledger' + _wrapped_report_class = third_party_ledger + + +class report_partnerledgerother(osv.AbstractModel): + _name = 'report.account.report_partnerledgerother' + _inherit = 'report.abstract_report' + _template = 'account.report_partnerledgerother' + _wrapped_report_class = third_party_ledger # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_print_overdue.py b/addons/account/report/account_print_overdue.py index e135f41309d..26192d39949 100644 --- a/addons/account/report/account_print_overdue.py +++ b/addons/account/report/account_print_overdue.py @@ -22,15 +22,36 @@ import time from openerp.report import report_sxw +from openerp.osv import osv + class Overdue(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(Overdue, self).__init__(cr, uid, name, context=context) - self.localcontext.update( { + ids = context.get('active_ids') + partner_obj = self.pool['res.partner'] + docs = partner_obj.browse(cr, uid, ids, context) + + due = {} + paid = {} + mat = {} + + for partner in docs: + due[partner.id] = reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), self._lines_get(partner), 0) + paid[partner.id] = reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), self._lines_get(partner), 0) + mat[partner.id] = reduce(lambda x, y: x + (y['debit'] - y['credit']), filter(lambda x: x['date_maturity'] < time.strftime('%Y-%m-%d'), self._lines_get(partner)), 0) + + addresses = self.pool['res.partner']._address_display(cr, uid, ids, None, None) + self.localcontext.update({ + 'docs': docs, 'time': time, 'getLines': self._lines_get, 'tel_get': self._tel_get, 'message': self._message, + 'due': due, + 'paid': paid, + 'mat': mat, + 'addresses': addresses }) self.context = context @@ -41,7 +62,7 @@ class Overdue(report_sxw.rml_parse): addresses = res_partner.address_get(self.cr, self.uid, [partner.id], ['invoice']) adr_id = addresses and addresses['invoice'] or False if adr_id: - adr=res_partner_address.read(self.cr, self.uid, [adr_id])[0] + adr=res_partner.read(self.cr, self.uid, [adr_id])[0] return adr['phone'] else: return partner.phone or False @@ -62,5 +83,10 @@ class Overdue(report_sxw.rml_parse): return message.split('\n') -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +class report_overdue(osv.AbstractModel): + _name = 'report.account.report_overdue' + _inherit = 'report.abstract_report' + _template = 'account.report_overdue' + _wrapped_report_class = Overdue +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/report_vat.py b/addons/account/report/report_vat.py index 3a0950ac62f..be2b6244f7d 100644 --- a/addons/account/report/report_vat.py +++ b/addons/account/report/report_vat.py @@ -19,24 +19,16 @@ # ############################################################################## +import time from openerp.osv import osv -from openerp.addons.web import http -from openerp.addons.web.http import request +from openerp.report import report_sxw from common_report_header import common_report_header -try: - import cStringIO as StringIO -except ImportError: - import StringIO -import xlwt -class tax_report(osv.AbstractModel, common_report_header): - _name = 'report.account.report_vat' - - def render_html(self, cr, uid, ids, data=None, context=None): - report_obj = request.registry['report'] - self.cr, self.uid, self.context = cr, uid, context +class tax_report(report_sxw.rml_parse, common_report_header): + def set_context(self, objects, data, ids, report_type=None): + new_ids = ids res = {} self.period_ids = [] period_obj = self.pool.get('account.period') @@ -46,30 +38,42 @@ class tax_report(osv.AbstractModel, common_report_header): if data['form'].get('period_from', False) and data['form'].get('period_to', False): self.period_ids = period_obj.build_ctx_periods(self.cr, self.uid, data['form']['period_from'], data['form']['period_to']) + periods_l = period_obj.read(self.cr, self.uid, self.period_ids, ['name']) + for period in periods_l: + if res['periods'] == '': + res['periods'] = period['name'] + else: + res['periods'] += ", "+ period['name'] + return super(tax_report, self).set_context(objects, data, new_ids, report_type=report_type) - docargs = { - 'fiscalyear': self._get_fiscalyear(data), - 'account': self._get_account(data), - 'based_on': self._get_basedon(data), - 'period_from': self.get_start_period(data), - 'period_to': self.get_end_period(data), - 'taxlines': self._get_lines(self._get_basedon(data), company_id=data['form']['company_id'], cr=cr, uid=uid), - } - return report_obj.render(self.cr, self.uid, [], 'account.report_vat', docargs, context=context) + def __init__(self, cr, uid, name, context=None): + super(tax_report, self).__init__(cr, uid, name, context=context) + self.localcontext.update({ + 'time': time, + 'get_codes': self._get_codes, + 'get_general': self._get_general, + 'get_currency': self._get_currency, + 'get_lines': self._get_lines, + 'get_fiscalyear': self._get_fiscalyear, + 'get_account': self._get_account, + 'get_start_period': self.get_start_period, + 'get_end_period': self.get_end_period, + 'get_basedon': self._get_basedon, + }) def _get_basedon(self, form): return form['form']['based_on'] - def _get_lines(self, based_on, company_id=False, parent=False, level=0, context=None, cr=None, uid=None): + def _get_lines(self, based_on, company_id=False, parent=False, level=0, context=None): period_list = self.period_ids - res = self._get_codes(based_on, company_id, parent, level, period_list, cr=cr, uid=uid, context=context) + res = self._get_codes(based_on, company_id, parent, level, period_list, context=context) if period_list: res = self._add_codes(based_on, res, period_list, context=context) else: - cr.execute ("select id from account_fiscalyear") - fy = cr.fetchall() - cr.execute ("select id from account_period where fiscalyear_id = %s",(fy[0][0],)) - periods = cr.fetchall() + self.cr.execute ("select id from account_fiscalyear") + fy = self.cr.fetchall() + self.cr.execute ("select id from account_period where fiscalyear_id = %s",(fy[0][0],)) + periods = self.cr.fetchall() for p in periods: period_list.append(p[0]) res = self._add_codes(based_on, res, period_list, context=context) @@ -89,7 +93,7 @@ class tax_report(osv.AbstractModel, common_report_header): } top_result.append(res_dict) - res_general = self._get_general(res[i][1].id, period_list, company_id, based_on, cr=cr, uid=uid, context=context) + res_general = self._get_general(res[i][1].id, period_list, company_id, based_on, context=context) ind_general = 0 while ind_general < len(res_general): res_general[ind_general]['type'] = 2 @@ -100,14 +104,14 @@ class tax_report(osv.AbstractModel, common_report_header): i+=1 return top_result - def _get_general(self, tax_code_id, period_list, company_id, based_on, cr=None, uid=None, context=None): + def _get_general(self, tax_code_id, period_list, company_id, based_on, context=None): if not self.display_detail: return [] res = [] obj_account = self.pool.get('account.account') periods_ids = tuple(period_list) if based_on == 'payments': - cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ + self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ SUM(line.debit) AS debit, \ SUM(line.credit) AS credit, \ COUNT(*) AS count, \ @@ -131,7 +135,7 @@ class tax_report(osv.AbstractModel, common_report_header): company_id, periods_ids, 'paid',)) else: - cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ + self.cr.execute('SELECT SUM(line.tax_amount) AS tax_amount, \ SUM(line.debit) AS debit, \ SUM(line.credit) AS credit, \ COUNT(*) AS count, \ @@ -148,21 +152,23 @@ class tax_report(osv.AbstractModel, common_report_header): AND account.active \ GROUP BY account.id,account.name,account.code', ('draft', tax_code_id, company_id, periods_ids,)) - res = cr.dictfetchall() + res = self.cr.dictfetchall() i = 0 while i= int(accounts[bcl_rup_ind]['level']) and bcl_rup_ind >= 0 ): - res_tot = { - 'code': accounts[bcl_rup_ind]['code'], + res_tot = { 'code': accounts[bcl_rup_ind]['code'], 'name': '', 'debit': 0, 'credit': 0, @@ -225,40 +234,10 @@ class tax_report(osv.AbstractModel, common_report_header): return result_accounts -class tax_report_xls(http.Controller): - - @http.route(['/report/account.report_vat_xls'], type='http', auth='user', website=True, multilang=True) - def report_account_tax_xls(self, **data): - - # Very ugly lines, only for the proof of concept of 'controller' report - taxreport_obj = request.registry['report.account.report_vat'] - from openerp.addons.report.controllers.main import ReportController - eval_params = ReportController()._eval_params - - cr, uid = request.cr, request.uid - data = eval_params(data) - data = {'form': data} - - taxreport_obj.render_html(cr, uid, [], data=data) - lines = taxreport_obj._get_lines(taxreport_obj._get_basedon(data), company_id=data['form']['company_id'], cr=cr, uid=uid) - - if lines: - xls = StringIO.StringIO() - xls_workbook = xlwt.Workbook() - vat_sheet = xls_workbook.add_sheet('report_vat') - - for x in range(0, len(lines)): - for y in range(0, len(lines[0])): - vat_sheet.write(x, y, lines[x].values()[y]) - - xls_workbook.save(xls) - xls.seek(0) - content = xls.read() - - response = request.make_response(content, headers=[ - ('Content-Type', 'application/vnd.ms-excel'), - ('Content-Disposition', 'attachment; filename=report_vat.xls;') - ]) - return response +class report_vat(osv.AbstractModel): + _name = 'report.account.report_vat' + _inherit = 'report.abstract_report' + _template = 'account.report_vat' + _wrapped_report_class = tax_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/test/account_report.yml b/addons/account/test/account_report.yml index 7a2d09486e4..9173c37b61e 100644 --- a/addons/account/test/account_report.yml +++ b/addons/account/test/account_report.yml @@ -16,10 +16,9 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('account.account_invoice_customer0')], 'account.invoice', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('account.account_invoice_customer0')], 'account.report_invoice', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account-invoice.'+format), 'wb+').write(data) - - In order to test the PDF reports defined on a partner, we will print the Overdue Report - @@ -27,7 +26,7 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('base.res_partner_1'),ref('base.res_partner_2'),ref('base.res_partner_12')], 'account.overdue', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('base.res_partner_1'),ref('base.res_partner_2'),ref('base.res_partner_12')], 'account.report_overdue', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account-report_overdue.'+format), 'wb+').write(data) - @@ -86,8 +85,8 @@ Print the General Ledger Report in Landscape Mode - !python {model: account.account}: | - ctx={} - data_dict = {'chart_account_id':ref('account.chart0'),'landscape':True} + ctx={'landscape': True} + data_dict = {'chart_account_id':ref('account.chart0')} from openerp.tools import test_reports test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu',wiz_data=data_dict, context=ctx, our_module='account') - diff --git a/addons/account/views/report_agedpartnerbalance.xml b/addons/account/views/report_agedpartnerbalance.xml index 9ab05afa772..019f32a35de 100644 --- a/addons/account/views/report_agedpartnerbalance.xml +++ b/addons/account/views/report_agedpartnerbalance.xml @@ -52,11 +52,11 @@ Due Not due - - - - - + + + + + + Total diff --git a/addons/account/views/report_overdue.xml b/addons/account/views/report_overdue.xml index 080de9a5615..0c2d763f84e 100644 --- a/addons/account/views/report_overdue.xml +++ b/addons/account/views/report_overdue.xml @@ -8,6 +8,7 @@
    +
    diff --git a/addons/account/views/report_vat.xml b/addons/account/views/report_vat.xml index 03664045ef4..f88d45e5c44 100644 --- a/addons/account/views/report_vat.xml +++ b/addons/account/views/report_vat.xml @@ -39,7 +39,7 @@ - + diff --git a/addons/account/wizard/account_financial_report.py b/addons/account/wizard/account_financial_report.py index df1fa94ae90..6c1b57fa428 100644 --- a/addons/account/wizard/account_financial_report.py +++ b/addons/account/wizard/account_financial_report.py @@ -84,8 +84,6 @@ class accounting_report(osv.osv_memory): if isinstance(data['form'][field], tuple): data['form'][field] = data['form'][field][0] comparison_context = self._build_comparison_context(cr, uid, ids, data, context=context) - res['data'] = {} - res['data']['form'] = data['form'] res['data']['form']['comparison_context'] = comparison_context return res diff --git a/addons/account/wizard/account_report_partner_ledger.py b/addons/account/wizard/account_report_partner_ledger.py index 75f79512603..eb743e32e4f 100644 --- a/addons/account/wizard/account_report_partner_ledger.py +++ b/addons/account/wizard/account_report_partner_ledger.py @@ -57,6 +57,8 @@ class account_partner_ledger(osv.osv_memory): context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids, ['initial_balance', 'filter', 'page_split', 'amount_currency'])[0]) + if data['form'].get('page_split') is True: + return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerledgerother', data=data, context=context) return self.pool['report'].get_action(cr, uid, ids, 'account.report_partnerledger', data=data, context=context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_analytic_plans/__openerp__.py b/addons/account_analytic_plans/__openerp__.py index 7c580bd14f2..7ca7c00e6c0 100644 --- a/addons/account_analytic_plans/__openerp__.py +++ b/addons/account_analytic_plans/__openerp__.py @@ -76,7 +76,7 @@ The analytic plan validates the minimum and maximum percentage at the time of cr 'views/report_crossoveredanalyticplans.xml', ], 'demo': [], - 'test': [], + 'test': ['test/acount_analytic_plans_report.yml'], 'installable': True, 'auto_install': False, } diff --git a/addons/account_analytic_plans/report/crossovered_analytic.py b/addons/account_analytic_plans/report/crossovered_analytic.py index b1a8f965d6b..ef7589fda8e 100644 --- a/addons/account_analytic_plans/report/crossovered_analytic.py +++ b/addons/account_analytic_plans/report/crossovered_analytic.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class crossovered_analytic(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(crossovered_analytic, self).__init__(cr, uid, name, context = context) @@ -173,7 +174,11 @@ class crossovered_analytic(report_sxw.rml_parse): final.append(item) return final -report_sxw.report_sxw('report.account.analytic.account.crossovered.analytic', 'account.analytic.account', 'addons/account_analytic_plans/report/crossovered_analytic.rml',parser = crossovered_analytic, header='internal') + +class report_crossoveredanalyticplans(osv.AbstractModel): + _name = 'report.account_analytic_plans.report_crossoveredanalyticplans' + _inherit = 'report.abstract_report' + _template = 'account_analytic_plans.report_crossoveredanalyticplans' + _wrapped_report_class = crossovered_analytic # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml index 6aa67a3052a..cae58583793 100644 --- a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml +++ b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml @@ -6,6 +6,6 @@ import openerp.report from openerp import tools data_dict = {'model': 'account.analytic.account', 'form': {'date1':time.strftime("%Y-01-01"),'date2':time.strftime('%Y-%m-%d'),'journal_ids':[6,0,(ref('account.cose_journal_sale'))],'ref':ref('account.analytic_root'),'empty_line':True,'id':ref('account.analytic_root'),'context':{}}} - data, format = openerp.report.render_report(cr, uid, [ref('account.analytic_root')], 'account.analytic.account.crossovered.analytic', data_dict, {}) + data, format = openerp.report.render_report(cr, uid, [ref('account.analytic_root')], 'account_analytic_plans.report_crossoveredanalyticplans', data_dict, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_analytic_plans-crossovered_analyitic.'+format), 'wb+').write(data) diff --git a/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml b/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml index bce3cccd5c7..b4470ea2913 100644 --- a/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml +++ b/addons/account_analytic_plans/views/report_crossoveredanalyticplans.xml @@ -11,11 +11,11 @@
    From Date: -

    +

    To Date: -

    +

    Company: diff --git a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py index 59b8efb23e1..f0b63bf148c 100644 --- a/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py +++ b/addons/account_bank_statement_extensions/report/bank_statement_balance_report.py @@ -21,15 +21,14 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class bank_statement_balance_report(report_sxw.rml_parse): def set_context(self, objects, data, ids, report_type=None): cr = self.cr - uid = self.uid - context = self.context cr.execute('SELECT s.name as s_name, s.date AS s_date, j.code as j_code, s.balance_end_real as s_balance ' \ 'FROM account_bank_statement s ' \ @@ -46,7 +45,6 @@ class bank_statement_balance_report(report_sxw.rml_parse): }) super(bank_statement_balance_report, self).set_context(objects, data, ids, report_type=report_type) - def __init__(self, cr, uid, name, context): if context is None: context = {} @@ -56,12 +54,11 @@ class bank_statement_balance_report(report_sxw.rml_parse): }) self.context = context -report_sxw.report_sxw( - 'report.bank.statement.balance.report', - 'account.bank.statement', - 'addons/account_bank_statement_extensions/report/bank_statement_balance_report.rml', - parser=bank_statement_balance_report, - header='internal' -) + +class report_bankstatementbalance(osv.AbstractModel): + _name = 'report.account_bank_statement_extensions.report_bankstatementbalance' + _inherit = 'report.abstract_report' + _template = 'account_bank_statement_extensions.report_bankstatementbalance' + _wrapped_report_class = bank_statement_balance_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/report/analytic_account_budget_report.py b/addons/account_budget/report/analytic_account_budget_report.py index 6701fc06a2b..4e3feaf06b7 100644 --- a/addons/account_budget/report/analytic_account_budget_report.py +++ b/addons/account_budget/report/analytic_account_budget_report.py @@ -20,10 +20,10 @@ ############################################################################## import time -import datetime - +from openerp.osv import osv from openerp.report import report_sxw + class analytic_account_budget_report(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): super(analytic_account_budget_report, self).__init__(cr, uid, name, context=context) @@ -166,6 +166,11 @@ class analytic_account_budget_report(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw('report.account.analytic.account.budget', 'account.analytic.account', 'addons/account_budget/report/analytic_account_budget_report.rml',parser=analytic_account_budget_report,header='internal') + +class report_analyticaccountbudget(osv.AbstractModel): + _name = 'report.account_budget.report_analyticaccountbudget' + _inherit = 'report.abstract_report' + _template = 'account_budget.report_analyticaccountbudget' + _wrapped_report_class = analytic_account_budget_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/report/budget_report.py b/addons/account_budget/report/budget_report.py index f00eb8a3713..f8f812639b0 100644 --- a/addons/account_budget/report/budget_report.py +++ b/addons/account_budget/report/budget_report.py @@ -20,6 +20,7 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw tot = {} @@ -187,6 +188,11 @@ class budget_report(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw('report.account.budget', 'account.budget.post', 'addons/account_budget/report/budget_report.rml', parser=budget_report, header='internal') + +class report_budget(osv.AbstractModel): + _name = 'report.account_budget.report_budget' + _inherit = 'report.abstract_report' + _template = 'account_budget.report_budget' + _wrapped_report_class = budget_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_budget/report/crossovered_budget_report.py b/addons/account_budget/report/crossovered_budget_report.py index 70cbdecb713..8a001aafb39 100644 --- a/addons/account_budget/report/crossovered_budget_report.py +++ b/addons/account_budget/report/crossovered_budget_report.py @@ -20,11 +20,9 @@ ############################################################################## import time -import datetime - +from openerp.osv import osv from openerp.report import report_sxw -import operator -from openerp import osv + class budget_report(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): @@ -191,7 +189,11 @@ class budget_report(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw('report.crossovered.budget.report', 'crossovered.budget', 'addons/account_budget/report/crossovered_budget_report.rml',parser=budget_report,header='internal') + +class report_crossoveredbudget(osv.AbstractModel): + _name = 'report.account_budget.report_crossoveredbudget' + _inherit = 'report.abstract_report' + _template = 'account_budget.report_crossoveredbudget' + _wrapped_report_class = budget_report # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/account_budget/test/account_budget_report.yml b/addons/account_budget/test/account_budget_report.yml index 80ab9b36b34..a36c2d87d04 100644 --- a/addons/account_budget/test/account_budget_report.yml +++ b/addons/account_budget/test/account_budget_report.yml @@ -2,35 +2,22 @@ Print the Analytic Budget Report through wizard - !python {model: account.analytic.account}: | - import os, time - from openerp import netsvc, tools - ctx={} - ctx.update({'model': 'account.analytic.account','active_ids': [ref('account.analytic_root')]}) - data_dict = {} + ctx = {'model': 'account.analytic.account','active_ids': [ref('account.analytic_root')]} from openerp.tools import test_reports - test_reports.try_report_action(cr, uid, 'action_account_budget_analytic',wiz_data=data_dict, context=ctx, our_module='account_budget') + test_reports.try_report_action(cr, uid, 'action_account_budget_analytic',wiz_data={}, context=ctx, our_module='account_budget') - Print the Budget Report through wizard - !python {model: account.budget.post}: | - import os, time - from openerp import netsvc, tools - ctx={} - ctx.update({'model': 'account.budget.post','active_ids': [ref('account_budget.account_budget_post_sales0')]}) - data_dict = {} + ctx = {'model': 'account.budget.post','active_ids': [ref('account_budget.account_budget_post_sales0')]} from openerp.tools import test_reports - test_reports.try_report_action(cr, uid, 'action_account_budget_report',wiz_data=data_dict, context=ctx, our_module='account_budget') + test_reports.try_report_action(cr, uid, 'action_account_budget_report',wiz_data={}, context=ctx, our_module='account_budget') - Print the CrossOvered Budget Report mode through wizard - !python {model: crossovered.budget}: | - import os, time - from openerp import netsvc, tools - ctx={} - ctx.update({'model': 'account.budget.post','active_ids': [ref('account_budget.crossovered_budget_budgetoptimistic0')]}) - data_dict = {} + ctx = {'model': 'account.budget.post','active_ids': [ref('account_budget.crossovered_budget_budgetoptimistic0')]} from openerp.tools import test_reports - test_reports.try_report_action(cr, uid, 'action_account_budget_crossvered_report',wiz_data=data_dict, context=ctx, our_module='account_budget') - + test_reports.try_report_action(cr, uid, 'action_account_budget_crossvered_report',wiz_data={}, context=ctx, our_module='account_budget') diff --git a/addons/account_check_writing/report/check_print.py b/addons/account_check_writing/report/check_print.py index add79fcc35a..be5feb4662b 100644 --- a/addons/account_check_writing/report/check_print.py +++ b/addons/account_check_writing/report/check_print.py @@ -20,8 +20,9 @@ ############################################################################## import time +from openerp.osv import osv from openerp.report import report_sxw -from openerp.tools import amount_to_text_en + class report_print_check(report_sxw.rml_parse): def __init__(self, cr, uid, name, context): @@ -33,13 +34,14 @@ class report_print_check(report_sxw.rml_parse): 'get_lines': self.get_lines, 'fill_stars' : self.fill_stars, }) + def fill_stars(self, amount): if len(amount) < 100: stars = 100 - len(amount) return ' '.join([amount,'*'*stars]) else: return amount - + def get_lines(self, voucher_lines): result = [] self.number_lines = len(voucher_lines) @@ -63,24 +65,11 @@ class report_print_check(report_sxw.rml_parse): result.append(res) return result -report_sxw.report_sxw( - 'report.account.print.check.top', - 'account.voucher', - 'addons/account_check_writing/report/check_print_top.rml', - parser=report_print_check,header=False -) -report_sxw.report_sxw( - 'report.account.print.check.middle', - 'account.voucher', - 'addons/account_check_writing/report/check_print_middle.rml', - parser=report_print_check,header=False -) +class report_check(osv.AbstractModel): + _name = 'report.account_check_writing.report_check' + _inherit = 'report.abstract_report' + _template = 'account_check_writing.report_check' + _wrapped_report_class = report_print_check -report_sxw.report_sxw( - 'report.account.print.check.bottom', - 'account.voucher', - 'addons/account_check_writing/report/check_print_bottom.rml', - parser=report_print_check,header=False -) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_followup/account_followup.py b/addons/account_followup/account_followup.py index 5f912b61b37..eae361913ad 100644 --- a/addons/account_followup/account_followup.py +++ b/addons/account_followup/account_followup.py @@ -21,7 +21,6 @@ from openerp.osv import fields, osv from lxml import etree -import openerp.tools as tools from openerp.tools.translate import _ class followup(osv.osv): @@ -243,7 +242,8 @@ class res_partner(osv.osv): if partner.unreconciled_aml_ids: company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id current_date = fields.date.context_today(self, cr, uid, context=context) - final_res = self.pool['report.account_followup.report_followup']._lines_get_with_partner(partner, company.id, cr=cr, uid=uid) + rml_parse = account_followup_print.report_rappel(cr, uid, "followup_rml_parser") + final_res = rml_parse._lines_get_with_partner(partner, company.id) for currency_dict in final_res: currency = currency_dict.get('line', [{'currency_id': company.currency_id}])[0]['currency_id'] @@ -272,8 +272,7 @@ class res_partner(osv.osv): total = reduce(lambda x, y: x+y['balance'], currency_dict['line'], 0.00) - report_obj = self.pool.get('report') - total = report_obj.formatLang(total, dp='Account', currency_obj=currency, cr=cr, uid=uid) + total = rml_parse.formatLang(total, dp='Account', currency_obj=currency) followup_table += '''
    ''' + _("Amount due") + ''' : %s
    ''' % (total) diff --git a/addons/account_followup/report/account_followup_print.py b/addons/account_followup/report/account_followup_print.py index eecba81acb9..4e856853915 100644 --- a/addons/account_followup/report/account_followup_print.py +++ b/addons/account_followup/report/account_followup_print.py @@ -21,9 +21,10 @@ import time from collections import defaultdict - +from openerp.osv import osv from openerp.report import report_sxw + class report_rappel(report_sxw.rml_parse): _name = "account_followup.report.rappel" @@ -108,8 +109,11 @@ class report_rappel(report_sxw.rml_parse): } return text -report_sxw.report_sxw('report.account_followup.followup.print', - 'account_followup.stat.by.partner', 'addons/account_followup/report/account_followup_print.rml', - parser=report_rappel) + +class report_followup(osv.AbstractModel): + _name = 'report.account_followup.report_followup' + _inherit = 'report.abstract_report' + _template = 'account_followup.report_followup' + _wrapped_report_class = report_rappel # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_followup/wizard/account_followup_print.py b/addons/account_followup/wizard/account_followup_print.py index 00ecab7b860..7b7cb8fc77e 100644 --- a/addons/account_followup/wizard/account_followup_print.py +++ b/addons/account_followup/wizard/account_followup_print.py @@ -218,18 +218,18 @@ class account_followup_print(osv.osv_memory): #Update partners self.do_update_followup_level(cr, uid, to_update, partner_list, date, context=context) #process the partners (send mails...) - restot = self.process_partners(cr, uid, partner_list, data, context=context) + restot_context = context.copy() + restot = self.process_partners(cr, uid, partner_list, data, context=restot_context) + context.update(restot_context) #clear the manual actions if nothing is due anymore nbactionscleared = self.clear_manual_actions(cr, uid, partner_list, context=context) if nbactionscleared > 0: restot['resulttext'] = restot['resulttext'] + "
  • " + _("%s partners have no credits and as such the action is cleared") %(str(nbactionscleared)) + "
  • " - res = restot['action'] - #return the next action mod_obj = self.pool.get('ir.model.data') model_data_ids = mod_obj.search(cr, uid, [('model','=','ir.ui.view'),('name','=','view_account_followup_sending_results')], context=context) resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] - context.update({'description': restot['resulttext'], 'needprinting': restot['needprinting'], 'report_data': res}) + context.update({'description': restot['resulttext'], 'needprinting': restot['needprinting'], 'report_data': restot['action']}) return { 'name': _('Send Letters and Emails: Actions Summary'), 'view_type': 'form', diff --git a/addons/account_payment/report/payment_order.py b/addons/account_payment/report/payment_order.py index a851a54ecbb..292d0e11bf4 100644 --- a/addons/account_payment/report/payment_order.py +++ b/addons/account_payment/report/payment_order.py @@ -20,9 +20,10 @@ ############################################################################## import time - +from openerp.osv import osv from openerp.report import report_sxw + class payment_order(report_sxw.rml_parse): def __init__(self, cr, uid, name, context=None): @@ -70,6 +71,11 @@ class payment_order(report_sxw.rml_parse): return value_name[0][1] return False -report_sxw.report_sxw('report.payment.order', 'payment.order', 'addons/account_payment/report/payment_order.rml', parser=payment_order, header="external") + +class report_paymentorder(osv.AbstractModel): + _name = 'report.account_payment.report_paymentorder' + _inherit = 'report.abstract_report' + _template = 'account_payment.report_paymentorder' + _wrapped_report_class = payment_order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_payment/test/account_payment_report.yml b/addons/account_payment/test/account_payment_report.yml index 3def62de429..922d2502203 100644 --- a/addons/account_payment/test/account_payment_report.yml +++ b/addons/account_payment/test/account_payment_report.yml @@ -5,6 +5,6 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('payment_order_1')], 'payment.order', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('payment_order_1')], 'account_payment.report_paymentorder', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'account_payment-payment_order_report.'+format), 'wb+').write(data) diff --git a/addons/account_test/report/account_test_report.py b/addons/account_test/report/account_test_report.py index 0cfbc040d82..bb21e3807a8 100644 --- a/addons/account_test/report/account_test_report.py +++ b/addons/account_test/report/account_test_report.py @@ -23,8 +23,10 @@ import datetime import time -from openerp.report import report_sxw +from openerp.osv import osv from openerp.tools.translate import _ +from openerp.report import report_sxw + # # Use period and Journal for selection or resources @@ -84,6 +86,11 @@ class report_assert_account(report_sxw.rml_parse): return result -report_sxw.report_sxw('report.account.test.assert.print', 'accounting.assert.test', 'addons/account_test/report/account_test.rml', parser=report_assert_account, header=False) + +class report_accounttest(osv.AbstractModel): + _name = 'report.account_test.report_accounttest' + _inherit = 'report.abstract_report' + _template = 'account_test.report_accounttest' + _wrapped_report_class = report_assert_account # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/__openerp__.py b/addons/account_voucher/__openerp__.py index 6a3b0ee81cd..dc8102d6647 100644 --- a/addons/account_voucher/__openerp__.py +++ b/addons/account_voucher/__openerp__.py @@ -58,7 +58,6 @@ This module manages: 'report/account_voucher_sales_receipt_view.xml', 'security/account_voucher_security.xml', 'account_voucher_data.xml', - 'account_voucher_report.xml', ], 'test' : [ 'test/account_voucher_users.yml', @@ -73,7 +72,6 @@ This module manages: 'test/case3_eur_eur.yml', 'test/case4_cad_chf.yml', 'test/case_eur_usd.yml', - 'account_voucher_report.yml', ], 'auto_install': False, 'application': True, diff --git a/addons/account_voucher/account_voucher_report.xml b/addons/account_voucher/account_voucher_report.xml deleted file mode 100644 index 239492d1a27..00000000000 --- a/addons/account_voucher/account_voucher_report.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - diff --git a/addons/account_voucher/report/__init__.py b/addons/account_voucher/report/__init__.py index 862843352a8..53ac7e915be 100644 --- a/addons/account_voucher/report/__init__.py +++ b/addons/account_voucher/report/__init__.py @@ -19,8 +19,6 @@ # ############################################################################## -import account_voucher -import account_voucher_print import account_voucher_sales_receipt # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/report/account_voucher.py b/addons/account_voucher/report/account_voucher.py deleted file mode 100644 index c23c7f4d384..00000000000 --- a/addons/account_voucher/report/account_voucher.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -import time -from openerp.report import report_sxw -from openerp.tools import amount_to_text_en - -class report_voucher(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(report_voucher, self).__init__(cr, uid, name, context) - self.localcontext.update({ - 'time': time, - 'convert':self.convert, - 'get_title': self.get_title, - 'debit':self.debit, - 'credit':self.credit, - 'get_ref': self._get_ref - }) - - def convert(self, amount, cur): - amt_en = amount_to_text_en.amount_to_text(amount, 'en', cur) - return amt_en - - def get_title(self, type): - title = '' - if type: - title = type[0].swapcase() + type[1:] + " Voucher" - return title - - def debit(self, move_ids): - debit = 0.0 - for move in move_ids: - debit += move.debit - return debit - - def credit(self, move_ids): - credit = 0.0 - for move in move_ids: - credit += move.credit - return credit - - def _get_ref(self, voucher_id, move_ids): - voucher_line_obj = self.pool.get('account.voucher.line') - voucher_line = voucher_line_obj.search(self.cr, self.uid, [('partner_id', '=', move_ids.partner_id.id), ('voucher_id', '=', voucher_id)]) - if voucher_line: - voucher = voucher_line_obj.browse(self.cr, self.uid, voucher_line)[0] - return voucher.name - else: - return -report_sxw.report_sxw( - 'report.voucher.cash_receipt.drcr', - 'account.voucher', - 'addons/account_voucher/report/account_voucher.rml', - parser=report_voucher,header="external" -) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/report/account_voucher_print.py b/addons/account_voucher/report/account_voucher_print.py deleted file mode 100644 index 1bc411947f6..00000000000 --- a/addons/account_voucher/report/account_voucher_print.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -import time -from openerp.report import report_sxw -from openerp.tools import amount_to_text_en - -class report_voucher_print(report_sxw.rml_parse): - def __init__(self, cr, uid, name, context): - super(report_voucher_print, self).__init__(cr, uid, name, context) - self.localcontext.update({ - 'time': time, - 'get_title': self.get_title, - 'get_lines':self.get_lines, - 'get_on_account':self.get_on_account, - 'convert':self.convert - }) - - def convert(self, amount, cur): - amt_en = amount_to_text_en.amount_to_text(amount, 'en', cur) - return amt_en - - def get_lines(self, voucher): - result = [] - if voucher.type in ('payment','receipt'): - type = voucher.line_ids and voucher.line_ids[0].type or False - for move in voucher.move_ids: - res = {} - amount = move.credit - if type == 'dr': - amount = move.debit - if amount > 0.0: - res['pname'] = move.partner_id.name - res['ref'] = 'Agst Ref'+" "+str(move.name) - res['aname'] = move.account_id.name - res['amount'] = amount - result.append(res) - else: - type = voucher.line_ids and voucher.line_ids[0].type or False - for move in voucher.move_ids: - res = {} - amount = move.credit - if type == 'dr': - amount = move.debit - if amount > 0.0: - res['pname'] = move.partner_id.name - res['ref'] = move.name - res['aname'] = move.account_id.name - res['amount'] = amount - result.append(res) - return result - - def get_title(self, type): - title = '' - if type: - title = type[0].swapcase() + type[1:] + " Voucher" - return title - - def get_on_account(self, voucher): - name = "" - if voucher.type == 'receipt': - name = "Received cash from "+str(voucher.partner_id.name) - elif voucher.type == 'payment': - name = "Payment from "+str(voucher.partner_id.name) - elif voucher.type == 'sale': - name = "Sale to "+str(voucher.partner_id.name) - elif voucher.type == 'purchase': - name = "Purchase from "+str(voucher.partner_id.name) - return name - -report_sxw.report_sxw( - 'report.voucher.print', - 'account.voucher', - 'addons/account_voucher/report/account_voucher_print.rml', - parser=report_voucher_print,header="external" -) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account_voucher/test/account_voucher_report.yml b/addons/account_voucher/test/account_voucher_report.yml deleted file mode 100644 index 96e96e4bdfd..00000000000 --- a/addons/account_voucher/test/account_voucher_report.yml +++ /dev/null @@ -1,27 +0,0 @@ -- - Demo for Account Voucher -- - !record {model: account.voucher, id: account_voucher_voucheraxelor0again, view: view_sale_receipt_form}: - type: sale - account_id: account.cash - company_id: base.main_company - journal_id: account.bank_journal - name: Voucher Axelor - narration: PC Assemble SC234 - amount: 1000.0 - line_ids: - - account_id: account.cash - amount: 1000.0 - name: Voucher Axelor - period_id: account.period_6 - -- - In order to test the PDF reports defined on a account_voucher, we will print account voucher Report -- - !python {model: account.voucher}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref("account_voucher_voucheraxelor0again")], 'voucher.cash_receipt.drcr', {}, {}) - if tools.config['test_report_directory']: - file(os.path.join(tools.config['test_report_directory'], 'account_voucher-report.'+format), 'wb+').write(data) diff --git a/addons/lunch/report/order.py b/addons/lunch/report/order.py index 0bb99f01017..85b216ac632 100644 --- a/addons/lunch/report/order.py +++ b/addons/lunch/report/order.py @@ -20,11 +20,11 @@ ############################################################################## import time -from openerp.addons.web import http -from openerp.addons.web.http import request +from openerp.report import report_sxw +from openerp.osv import osv -class order(http.Controller): +class order(report_sxw.rml_parse): def get_lines(self, user,objects): lines=[] @@ -60,24 +60,23 @@ class order(http.Controller): notes.append(obj.note) return notes - @http.route(['/report/lunch.report_lunchorder/'], type='http', auth='user', website=True, multilang=True) - def report_lunch(self, docids): - self.cr, self.uid, self.context = request.cr, request.uid, request.context - - ids = [int(i) for i in docids.split(',')] - report_obj = request.registry['lunch.order.line'] - docs = report_obj.browse(self.cr, self.uid, ids, context=self.context) - + def __init__(self, cr, uid, name, context): + super(order, self).__init__(cr, uid, name, context) self.net_total=0.0 - docargs = { - 'docs': docs, + self.localcontext.update({ 'time': time, 'get_lines': self.get_lines, 'get_users': self.get_users, 'get_total': self.get_total, 'get_nettotal': self.get_nettotal, 'get_note': self.get_note, - } - return request.registry['report'].render(self.cr, self.uid, [], 'lunch.report_lunchorder', docargs) + }) + + +class report_lunchorder(osv.AbstractModel): + _name = 'report.lunch.report_lunchorder' + _inherit = 'report.abstract_report' + _template = 'lunch.report_lunchorder' + _wrapped_report_class = order # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/mrp/report/bom_structure.py b/addons/mrp/report/bom_structure.py index 98949ed75dc..1b286feac46 100644 --- a/addons/mrp/report/bom_structure.py +++ b/addons/mrp/report/bom_structure.py @@ -19,22 +19,18 @@ # ############################################################################## +import time from openerp.osv import osv +from openerp.report import report_sxw -class bom_structure(osv.AbstractModel): - _name = 'report.mrp.report_mrpbomstructure' - - def render_html(self, cr, uid, ids, data=None, context=None): - mrpbom_obj = self.pool['mrp.bom'] - report_obj = self.pool['report'] - docs = mrpbom_obj.browse(cr, uid, ids, context=context) - - docargs = { - 'docs': docs, - 'get_children': self.get_children, - } - return report_obj.render(cr, uid, [], 'mrp.report_mrpbomstructure', docargs, context=context) +class bom_structure(report_sxw.rml_parse): + def __init__(self, cr, uid, name, context): + super(bom_structure, self).__init__(cr, uid, name, context=context) + self.localcontext.update({ + 'time': time, + 'get_children':self.get_children, + }) def get_children(self, object, level=0): result = [] @@ -62,4 +58,11 @@ class bom_structure(osv.AbstractModel): return children + +class report_lunchorder(osv.AbstractModel): + _name = 'report.mrp.report_mrpbomstructure' + _inherit = 'report.abstract_report' + _template = 'mpr.report_mrpbomstructure' + _wrapped_report_class = bom_structure + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/report_intrastat/test/report_intrastat_report.yml b/addons/report_intrastat/test/report_intrastat_report.yml index 687f605b901..5c70ba67ef2 100644 --- a/addons/report_intrastat/test/report_intrastat_report.yml +++ b/addons/report_intrastat/test/report_intrastat_report.yml @@ -16,6 +16,6 @@ import os import openerp.report from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('test_invoice_1')], 'account.invoice.intrastat', {}, {}) + data, format = openerp.report.render_report(cr, uid, [ref('test_invoice_1')], 'report_intrastat.report_intrastatinvoice', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'report_intrastat-intrastat_report.'+format), 'wb+').write(data) From c0db6aec56d383d173fa56b1a2dec2e42495911b Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Wed, 2 Apr 2014 18:50:08 +0200 Subject: [PATCH 053/140] [FIX] web: do not reload record on dialog close if the wizard return an action bzr revid: dle@openerp.com-20140402165008-y19pnbb35eerrnwx --- addons/web/static/src/js/chrome.js | 10 ++++------ addons/web/static/src/js/view_form.js | 6 ++++-- addons/web/static/src/js/views.js | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index add30866111..e893873a31e 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -105,9 +105,6 @@ instance.web.Dialog = instance.web.Widget.extend({ autoOpen: false, position: [false, 40], buttons: null, - beforeClose: function () { - self.trigger("closing"); - }, resizeStop: function() { self.trigger("resized"); }, @@ -208,8 +205,9 @@ instance.web.Dialog = instance.web.Widget.extend({ /** Closes the popup, if destroy_on_close was passed to the constructor, it is also destroyed. */ - close: function() { + close: function(reason) { if (this.dialog_inited && this.$el.is(":data(dialog)")) { + this.trigger("closing", reason); this.$el.dialog('close'); } }, @@ -225,14 +223,14 @@ instance.web.Dialog = instance.web.Widget.extend({ /** Destroys the popup, also closes it. */ - destroy: function () { + destroy: function (reason) { this.$buttons.remove(); _.each(this.getChildren(), function(el) { el.destroy(); }); if (! this.__tmp_dialog_closing) { this.__tmp_dialog_destroying = true; - this.close(); + this.close(reason); this.__tmp_dialog_destroying = undefined; } if (this.dialog_inited && !this.isDestroyed() && this.$el.is(":data(dialog)")) { diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index fd838686ba9..ce2de551e53 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -1982,8 +1982,10 @@ instance.web.form.WidgetButton = instance.web.form.FormWidget.extend({ return this.view.do_execute_action( _.extend({}, this.node.attrs, {context: context}), - this.view.dataset, this.view.datarecord.id, function () { - self.view.recursive_reload(); + this.view.dataset, this.view.datarecord.id, function (reason) { + if (!_.isObject(reason)) { + self.view.recursive_reload(); + } }); }, check_disable: function() { diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index b2bd33b393a..e3e91752f4d 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -25,9 +25,9 @@ instance.web.ActionManager = instance.web.Widget.extend({ this._super.apply(this, arguments); this.$el.on('click', 'a.oe_breadcrumb_item', this.on_breadcrumb_clicked); }, - dialog_stop: function () { + dialog_stop: function (reason) { if (this.dialog) { - this.dialog.destroy(); + this.dialog.destroy(reason); } this.dialog = null; }, @@ -408,7 +408,7 @@ instance.web.ActionManager = instance.web.Widget.extend({ if (this.dialog_widget && !this.dialog_widget.isDestroyed()) { this.dialog_widget.destroy(); } - this.dialog_stop(); + this.dialog_stop(executor.action); this.dialog = new instance.web.Dialog(this, { dialogClass: executor.klass, }); @@ -426,7 +426,7 @@ instance.web.ActionManager = instance.web.Widget.extend({ this.dialog.open(); return initialized; } else { - this.dialog_stop(); + this.dialog_stop(executor.action); this.inner_action = executor.action; this.inner_widget = widget; executor.post_process(widget); From 33471e966fcae83b60b75ced8d63b0ddb8e2d251 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 11:18:18 +0200 Subject: [PATCH 054/140] [FIX] missing dependancies of report module bzr revid: sle@openerp.com-20140403091818-6evr0k4r2k4818j1 --- addons/account/__openerp__.py | 2 +- addons/lunch/__openerp__.py | 2 +- addons/mrp/__openerp__.py | 2 +- addons/purchase/__openerp__.py | 2 +- addons/sale/__openerp__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 83434893ac7..1a222b2f83c 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -49,7 +49,7 @@ for a particular financial year and for preparation of vouchers there is a modul """, 'website': 'http://www.openerp.com', 'images' : ['images/accounts.jpeg','images/bank_statement.jpeg','images/cash_register.jpeg','images/chart_of_accounts.jpeg','images/customer_invoice.jpeg','images/journal_entries.jpeg'], - 'depends' : ['base_setup', 'product', 'analytic', 'process', 'board', 'edi'], + 'depends' : ['base_setup', 'product', 'analytic', 'process', 'board', 'edi', 'report'], 'data': [ 'security/account_security.xml', 'security/ir.model.access.csv', diff --git a/addons/lunch/__openerp__.py b/addons/lunch/__openerp__.py index f8a4a1ddcf2..955a1278c03 100644 --- a/addons/lunch/__openerp__.py +++ b/addons/lunch/__openerp__.py @@ -23,7 +23,7 @@ 'name': 'Lunch Orders', 'author': 'OpenERP SA', 'version': '0.2', - 'depends': ['base'], + 'depends': ['base', 'report'], 'category' : 'Tools', 'summary': 'Lunch Order, Meal, Food', 'description': """ diff --git a/addons/mrp/__openerp__.py b/addons/mrp/__openerp__.py index ef68b27a489..f3f290b12b0 100644 --- a/addons/mrp/__openerp__.py +++ b/addons/mrp/__openerp__.py @@ -29,7 +29,7 @@ 'sequence': 18, 'summary': 'Manufacturing Orders, Bill of Materials, Routing', 'images': ['images/bill_of_materials.jpeg', 'images/manufacturing_order.jpeg', 'images/planning_manufacturing_order.jpeg', 'images/manufacturing_analysis.jpeg', 'images/production_dashboard.jpeg','images/routings.jpeg','images/work_centers.jpeg'], - 'depends': ['product','procurement', 'stock', 'resource', 'purchase','process'], + 'depends': ['product','procurement', 'stock', 'resource', 'purchase','process', 'report'], 'description': """ Manage the Manufacturing process in OpenERP =========================================== diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py index 0d0a372a3d0..009cbf00b78 100644 --- a/addons/purchase/__openerp__.py +++ b/addons/purchase/__openerp__.py @@ -46,7 +46,7 @@ Dashboard / Reports for Purchase Management will include: 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', 'images' : ['images/purchase_order.jpeg', 'images/purchase_analysis.jpeg', 'images/request_for_quotation.jpeg'], - 'depends': ['stock', 'process', 'procurement'], + 'depends': ['stock', 'process', 'procurement', 'report'], 'data': [ 'security/purchase_security.xml', 'security/ir.model.access.csv', diff --git a/addons/sale/__openerp__.py b/addons/sale/__openerp__.py index bb5bac89e46..1684760debf 100644 --- a/addons/sale/__openerp__.py +++ b/addons/sale/__openerp__.py @@ -59,7 +59,7 @@ The Dashboard for the Sales Manager will include 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', 'images': ['images/sale_dashboard.jpeg','images/Sale_order_line_to_invoice.jpeg','images/sale_order.jpeg','images/sales_analysis.jpeg'], - 'depends': ['account_voucher'], + 'depends': ['account_voucher', 'report'], 'data': [ 'wizard/sale_make_invoice_advance.xml', 'wizard/sale_line_invoice.xml', From 0d4732b5c4194c7c25a13266dfdd1aed05e534eb Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 3 Apr 2014 11:40:50 +0200 Subject: [PATCH 055/140] [FIX] makes sure the internal data structure of pivot table is correct after update_data (the children were not correct when the tree of headers was not full, after an expand for example (addon web_graph) bzr revid: ged@openerp.com-20140403094050-vjeq4dks86mejuub --- addons/web_graph/static/src/js/pivot_table.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index 9231765c485..309bb103fa8 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -219,8 +219,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ header.root.groupby.push(groupby); } return this.perform_requests(this_gb, other_gbs, header.domain).then(function () { - var data = Array.prototype.slice.call(arguments); - data = data.slice(other_gbs.length + 1, data.length); + var data = Array.prototype.slice.call(arguments).slice(other_gbs.length + 1); _.each(data, function (data_pt) { self.make_headers_and_cell( data_pt, header.root.headers, other_root.headers, 1, header.path, true); @@ -369,6 +368,7 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ } if (corresponding_header && (!header.expanded)) { corresponding_header.expanded = false; + corresponding_header.children = []; } }); var updated_headers = _.filter(new_headers, function (header) { From 75b66ed77c89f14cb4215f4a677298bdcfce3881 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 3 Apr 2014 11:43:16 +0200 Subject: [PATCH 056/140] [FIX] work around a read bug: false data are fetched when the same field is present multiple times as a field parameter. The solution is to make sure the list many2onefields does not contain duplicate fields (orm.py) bzr revid: ged@openerp.com-20140403094316-kmlliqbwd14ey68p --- openerp/osv/orm.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 9d267816ad5..d9340745b11 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2382,6 +2382,7 @@ class BaseModel(object): many2onefields = [gb['field'] for gb in annotated_groupbys if gb['type'] == 'many2one'] if many2onefields: data_ids = [r['id'] for r in fetched_data] + many2onefields = list(set(many2onefields)) data_dict = {d['id']: d for d in self.read(cr, uid, data_ids, many2onefields, context=context)} for d in fetched_data: d.update(data_dict[d['id']]) @@ -2416,7 +2417,7 @@ class BaseModel(object): return result result = map(format_result, data) - + if lazy and groupby_fields[0] in self._group_by_full: # Right now, read_group only fill results in lazy mode (by default). # If you need to have the empty groups in 'eager' mode, then the From 55090e56db84bae50166f1813874f0da32eaac5d Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 12:05:43 +0200 Subject: [PATCH 057/140] [FIX] payment order: do not use qweb contact widget on res.bank as it is made for res.partner and res.bank has not all the res.partner fields bzr revid: sle@openerp.com-20140403100543-t0m45q1wkgbkli7i --- addons/account_payment/views/report_paymentorder.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/account_payment/views/report_paymentorder.xml b/addons/account_payment/views/report_paymentorder.xml index c2662b6aa77..42a2cbe989a 100644 --- a/addons/account_payment/views/report_paymentorder.xml +++ b/addons/account_payment/views/report_paymentorder.xml @@ -10,8 +10,13 @@
    -
    + + + + + + +
    From 1aba5f08cf8697fbfe12b5694e609dfc174d7c03 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 3 Apr 2014 13:56:05 +0200 Subject: [PATCH 058/140] [FIX] fixes read_group so that it uses the correct _count attribute in the result dictionary (orm.py) bzr revid: ged@openerp.com-20140403115605-tuboy66r9ews2u0e --- openerp/osv/orm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index d9340745b11..c916b40b6d8 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2337,7 +2337,7 @@ class BaseModel(object): groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query, fget) from_clause, where_clause, where_clause_params = query.get_sql() - count_field = groupby_fields[0] if (len(groupby_fields) == 1 and context.get('group_by_no_leaf')) else '_' + count_field = groupby_fields[0] if lazy and (len(groupby_fields) >= 2 or not context.get('group_by_no_leaf')) else '_' prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else '' prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else '' From b89d6d99c80e812295b4f6eaf9e9903ee4ebab06 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 3 Apr 2014 16:28:36 +0200 Subject: [PATCH 059/140] [FIX] product_email_template: typos bzr revid: odo@openerp.com-20140403142836-9na8qo7y7gqr0nmi --- addons/product_email_template/__openerp__.py | 2 +- addons/product_email_template/models/product.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/product_email_template/__openerp__.py b/addons/product_email_template/__openerp__.py index 2fdce7f2889..9b7af6f992b 100644 --- a/addons/product_email_template/__openerp__.py +++ b/addons/product_email_template/__openerp__.py @@ -10,7 +10,7 @@ Add email templates to products to be send on invoice confirmation ================================================================== With this module, link your products to a template to send complete information and tools to your customer. -For instance when invoicing a training, the training agenda and materials will automatically be send to your customers.' +For instance when invoicing a training, the training agenda and materials will automatically be sent to your customers.' """, 'website': 'http://www.openerp.com', 'demo': [ diff --git a/addons/product_email_template/models/product.py b/addons/product_email_template/models/product.py index cafdef7ab9d..6b463ffbeb5 100644 --- a/addons/product_email_template/models/product.py +++ b/addons/product_email_template/models/product.py @@ -13,7 +13,7 @@ class product_template(osv.Model): _columns = { 'email_template_id': fields.many2one( 'email.template', 'Product Email Template', - help='When validating an invoice, an email will be send to the customer' + help='When validating an invoice, an email will be sent to the customer' 'based on this template. The customer will receive an email for each' 'product linked to an email template.'), } From 7dd2e6789d2bc7619b6d99dd65f64f133d401ff4 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Thu, 3 Apr 2014 16:29:23 +0200 Subject: [PATCH 060/140] [FIX] when using readgroup in eager mode, there is a possible name collision when grouping on several fields with different intervals, for ex, date_deadline:month, date_deadline:week. This commit resolves the issue by changing the keys 'field' into 'field:interval' (for ex, date_deadline:month) in the results (orm.py) bzr revid: ged@openerp.com-20140403142923-puiruf29tbi1pjj9 --- openerp/osv/orm.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index c916b40b6d8..1c72001c275 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2207,7 +2207,7 @@ class BaseModel(object): """ orderby_terms = [] groupby_terms = [gb['qualified_field'] for gb in annotated_groupbys] - groupby_fields = [gb['field'] for gb in annotated_groupbys] + groupby_fields = [gb['groupby'] for gb in annotated_groupbys] if not orderby: return groupby_terms, orderby_terms @@ -2217,13 +2217,13 @@ class BaseModel(object): order_field = order_split[0] if order_field in groupby_fields: - if fget[order_field]['type'] == 'many2one': + if fget[order_field.split(':')[0]]['type'] == 'many2one': order_clause = self._generate_order_by(order_part, query).replace('ORDER BY ', '') if order_clause: orderby_terms.append(order_clause) groupby_terms += [order_term.split()[0] for order_term in order_clause.split(',')] else: - orderby_terms.append(order_part) + orderby_terms.append('"%s"' % order_part) elif order_field in aggregated_fields: orderby_terms.append(order_part) else: @@ -2299,7 +2299,8 @@ class BaseModel(object): if field_type == 'boolean': qualified_field = "coalesce(%s,false)" % qualified_field return { - 'field': split[0], + 'field': split[0], + 'groupby': gb, 'type': field_type, 'display_format': display_formats[gb_function or 'month'] if temporal else None, 'interval': time_intervals[gb_function or 'month'] if temporal else None, @@ -2309,8 +2310,8 @@ class BaseModel(object): annotated_groupbys = map(process_groupby, groupby[:1] if lazy else groupby) groupby_fields = [g['field'] for g in annotated_groupbys] - order = orderby or ','.join(groupby_fields) - groupby_dict = {gb['field']: gb for gb in annotated_groupbys} + order = orderby or ','.join([g['groupby'] for g in annotated_groupbys]) + groupby_dict = {gb['groupby']: gb for gb in annotated_groupbys} self._apply_ir_rules(cr, uid, query, 'read', context=context) for gb in groupby_fields: @@ -2333,7 +2334,7 @@ class BaseModel(object): select_terms = ["%s(%s) AS %s" % field_formatter(f) for f in aggregated_fields] for gb in annotated_groupbys: - select_terms.append("%s as %s " % (gb['qualified_field'], gb['field'])) + select_terms.append('%s as "%s" ' % (gb['qualified_field'], gb['groupby'])) groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query, fget) from_clause, where_clause, where_clause_params = query.get_sql() @@ -2404,7 +2405,7 @@ class BaseModel(object): return [(gb['field'], '=', value)] def format_result (fromquery): - domain_group = [dom for gb in annotated_groupbys for dom in get_domain(gb, fromquery[gb['field']])] + domain_group = [dom for gb in annotated_groupbys for dom in get_domain(gb, fromquery[gb['groupby']])] result = { '__domain': domain_group + domain } if len(groupby) - len(annotated_groupbys) >= 1: result['__context'] = { 'group_by': groupby[len(annotated_groupbys):]} @@ -4421,7 +4422,7 @@ class BaseModel(object): return Query(tables, where_clause, where_params) def _check_qorder(self, word): - if not regex_order.match(word): + if not regex_order.match(word.split(':')[0]): raise except_orm(_('AccessError'), _('Invalid "order" specified. A valid "order" specification is a comma-separated list of valid field names (optionally followed by asc/desc for the direction)')) return True From 4975d2b9dc3afe12dfce8a5c6e80dbd42f7a0073 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 16:32:35 +0200 Subject: [PATCH 061/140] [FIX] fixed report translation and translate overdue report into partner's lang bzr revid: sle@openerp.com-20140403143235-mpw30fq4j2nyov6x --- addons/account/views/report_overdue.xml | 204 ++++++++++++------------ addons/report/models/abstract_report.py | 5 + addons/report/models/report.py | 18 ++- addons/website_report/views/layouts.xml | 27 ++-- 4 files changed, 141 insertions(+), 113 deletions(-) diff --git a/addons/account/views/report_overdue.xml b/addons/account/views/report_overdue.xml index 0c2d763f84e..772e7661800 100644 --- a/addons/account/views/report_overdue.xml +++ b/addons/account/views/report_overdue.xml @@ -1,112 +1,116 @@ - From fba0d3da9a913fab43aeec719c9dd5f5b14a45af Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 3 Apr 2014 16:34:48 +0200 Subject: [PATCH 062/140] [REM] google_drive: remove unused (but sourced) Goggle API JS lib Should have been removed when Google Drive API was switched to server-side Python at revid:pga@tinyerp.com-20130523104155-83gmp2gucvackppv bzr revid: odo@openerp.com-20140403143448-vds7crizqed0l80a --- addons/google_drive/__openerp__.py | 1 - addons/google_drive/static/lib/gapi/client.js | 7 ------- 2 files changed, 8 deletions(-) delete mode 100644 addons/google_drive/static/lib/gapi/client.js diff --git a/addons/google_drive/__openerp__.py b/addons/google_drive/__openerp__.py index 8f135c5f9d1..e486c2c2d34 100644 --- a/addons/google_drive/__openerp__.py +++ b/addons/google_drive/__openerp__.py @@ -28,7 +28,6 @@ 'installable': True, 'auto_install': False, 'js': [ - 'static/lib/gapi/client.js', 'static/src/js/gdrive.js', ], 'data': [ diff --git a/addons/google_drive/static/lib/gapi/client.js b/addons/google_drive/static/lib/gapi/client.js deleted file mode 100644 index 7f40ec55ef9..00000000000 --- a/addons/google_drive/static/lib/gapi/client.js +++ /dev/null @@ -1,7 +0,0 @@ -var gapi=window.gapi=window.gapi||{};gapi._bs=new Date().getTime();(function(){var f=null,g=encodeURIComponent,k=window,m=decodeURIComponent,n="push",r="test",t="shift",u="replace",y="length",B="split",C="join";var D=k,E=document,aa=D.location,ba=function(){},ca=/\[native code\]/,G=function(a,b,c){return a[b]=a[b]||c},da=function(a){for(var b=0;bda.call(b,e)&&c[n](e)}return c},sa=function(a){"loading"!=E.readyState?Z(a):E.write("<"+X+' src="'+encodeURI(a)+'">")},Z=function(a){var b=E.createElement(X);b.setAttribute("src",a);b.async="true";(a=E.getElementsByTagName(X)[0])?a.parentNode.insertBefore(b,a):(E.head||E.body||E.documentElement).appendChild(b)},ta=function(a,b){var c=b&&b._c;if(c)for(var d=0;d Date: Thu, 3 Apr 2014 16:35:34 +0200 Subject: [PATCH 063/140] [FIX] read_group has been changed to return the results with field:interval as key (for example, date_deadline:week), to avoid name collisions. This commit changes the web client to make sure it properly processes the new result format. No change at all for queries that do not use the field:interval format (addon web) bzr revid: ged@openerp.com-20140403143534-3jpugw9g8n966n9t --- addons/web/static/src/js/data.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index 413d0621011..9d11dbcf2a8 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -238,31 +238,26 @@ instance.web.QueryGroup = instance.web.Class.extend({ {__context: {group_by: []}, __domain: []}, read_group_group); - var raw_fields = _.map(grouping_fields, function (field) { - return field && field.split(':')[0]; - }); - - + var count_key = (grouping_fields[0] && grouping_fields[0].split(':')[0]) + '_count'; var aggregates = {}; _(fixed_group).each(function (value, key) { if (key.indexOf('__') === 0 - || _.contains(raw_fields, key) - || (key === raw_fields[0] + '_count')) { + || _.contains(grouping_fields, key) + || (key === count_key)) { return; } aggregates[key] = value || 0; }); - this.model = new instance.web.Model( model, fixed_group.__context, fixed_group.__domain); - var group_size = fixed_group[raw_fields[0] + '_count'] || fixed_group.__count || 0; + var group_size = fixed_group[count_key] || fixed_group.__count || 0; var leaf_group = fixed_group.__context.group_by.length === 0; var value = (grouping_fields.length === 1) - ? fixed_group[raw_fields[0]] - : _.map(raw_fields, function (field) { return fixed_group[field]; }); + ? fixed_group[grouping_fields[0]] + : _.map(grouping_fields, function (field) { return fixed_group[field]; }); var grouped_on = (grouping_fields.length === 1) ? grouping_fields[0] : grouping_fields; From 27be515eabb4b099a6aed4ad89f80be4ba8c4178 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 3 Apr 2014 16:37:17 +0200 Subject: [PATCH 064/140] [FIX] res.partner: missing index on `parent_id` column bzr revid: odo@openerp.com-20140403143717-dy2bszaevsyivryo --- openerp/addons/base/res/res_partner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/res/res_partner.py b/openerp/addons/base/res/res_partner.py index d66c69daaa7..5d97311c01d 100644 --- a/openerp/addons/base/res/res_partner.py +++ b/openerp/addons/base/res/res_partner.py @@ -216,7 +216,7 @@ class res_partner(osv.osv, format_address): 'name': fields.char('Name', size=128, required=True, select=True), 'date': fields.date('Date', select=1), 'title': fields.many2one('res.partner.title', 'Title'), - 'parent_id': fields.many2one('res.partner', 'Related Company'), + 'parent_id': fields.many2one('res.partner', 'Related Company', select=True), 'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts', domain=[('active','=',True)]), # force "active_test" domain to bypass _search() override 'ref': fields.char('Reference', size=64, select=1), 'lang': fields.selection(_lang_get, 'Language', From 73b3c851da7c9dc371aa2aafbb896b4c617daa4b Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 3 Apr 2014 16:51:28 +0200 Subject: [PATCH 065/140] [FIX] website*: remove unusable demo links from manifests bzr revid: dle@openerp.com-20140403145128-9w92v4mmasz66mqj --- addons/hr_recruitment/static/description/index.html | 7 +------ addons/website_blog/static/description/index.html | 5 +---- addons/website_crm/static/description/index.html | 5 +---- addons/website_event/static/description/index.html | 5 +---- addons/website_event_track/static/description/index.html | 5 +---- .../website_hr_recruitment/static/description/index.html | 5 +---- 6 files changed, 6 insertions(+), 26 deletions(-) diff --git a/addons/hr_recruitment/static/description/index.html b/addons/hr_recruitment/static/description/index.html index e5196e488f8..6d3aaca308a 100644 --- a/addons/hr_recruitment/static/description/index.html +++ b/addons/hr_recruitment/static/description/index.html @@ -5,12 +5,7 @@

    Organize your vacancies and applications

    -
    - - - - -
    +

    diff --git a/addons/website_blog/static/description/index.html b/addons/website_blog/static/description/index.html index 1f198c11678..171fe942843 100644 --- a/addons/website_blog/static/description/index.html +++ b/addons/website_blog/static/description/index.html @@ -6,10 +6,7 @@

    - - - - +
    diff --git a/addons/website_crm/static/description/index.html b/addons/website_crm/static/description/index.html index 897bee4011e..334e6932bf4 100644 --- a/addons/website_crm/static/description/index.html +++ b/addons/website_crm/static/description/index.html @@ -6,10 +6,7 @@
    - - - - +
    diff --git a/addons/website_event/static/description/index.html b/addons/website_event/static/description/index.html index b47dfc493a8..34669aa4da8 100644 --- a/addons/website_event/static/description/index.html +++ b/addons/website_event/static/description/index.html @@ -6,10 +6,7 @@
    - - - - +
    diff --git a/addons/website_event_track/static/description/index.html b/addons/website_event_track/static/description/index.html index 2612f75d5d3..1bdcb1edd77 100644 --- a/addons/website_event_track/static/description/index.html +++ b/addons/website_event_track/static/description/index.html @@ -6,10 +6,7 @@
    - - - - +
    diff --git a/addons/website_hr_recruitment/static/description/index.html b/addons/website_hr_recruitment/static/description/index.html index 7af603b64dc..f1b255a0758 100644 --- a/addons/website_hr_recruitment/static/description/index.html +++ b/addons/website_hr_recruitment/static/description/index.html @@ -6,10 +6,7 @@
    - - - - +
    From a59b438ceb469857a75cff9c13d626dbf206a49d Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 3 Apr 2014 16:58:15 +0200 Subject: [PATCH 066/140] [FIX] share: at module init force re-generation of the user groups view without the shared groups bzr revid: chs@openerp.com-20140403145815-i3q3cprl2rvdfunf --- addons/share/res_users.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addons/share/res_users.py b/addons/share/res_users.py index 25fd25c234f..9f0a47c6674 100644 --- a/addons/share/res_users.py +++ b/addons/share/res_users.py @@ -19,6 +19,7 @@ # ############################################################################## from openerp.osv import fields, osv +from openerp import SUPERUSER_ID class res_groups(osv.osv): _name = "res.groups" @@ -28,6 +29,10 @@ class res_groups(osv.osv): help="Group created to set access rights for sharing data with some users.") } + def init(self, cr): + # force re-generation of the user groups view without the shared groups + self.update_user_groups_view(cr, SUPERUSER_ID) + def get_application_groups(self, cr, uid, domain=None, context=None): if domain is None: domain = [] From 9c1debf7d9b29ce31f3a126961c47fde9763568d Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Thu, 3 Apr 2014 17:17:46 +0200 Subject: [PATCH 067/140] [FIX] base_gengo: don't wait another cron job execution to ask translation for the next n words bzr revid: qdp-launchpad@openerp.com-20140403151746-znoheqb8scjmudct --- .../wizard/base_gengo_translations.py | 86 ++++++++++--------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/addons/base_gengo/wizard/base_gengo_translations.py b/addons/base_gengo/wizard/base_gengo_translations.py index ecfb696fddc..b044b929c65 100644 --- a/addons/base_gengo/wizard/base_gengo_translations.py +++ b/addons/base_gengo/wizard/base_gengo_translations.py @@ -71,7 +71,7 @@ class base_gengo_translations(osv.osv_memory): gengo = MyGengo( public_key=user.company_id.gengo_public_key.encode('ascii'), private_key=user.company_id.gengo_private_key.encode('ascii'), - sandbox = user.company_id.gengo_sandbox, + sandbox=user.company_id.gengo_sandbox, ) gengo.getAccountStats() return (True, gengo) @@ -83,7 +83,7 @@ class base_gengo_translations(osv.osv_memory): ''' Function called by the wizard. ''' - if context == None: + if context is None: context = {} flag, gengo = self.gengo_authentication(cr, uid, context=context) @@ -99,16 +99,16 @@ class base_gengo_translations(osv.osv_memory): ctx['gengo_language'] = wizard.lang_id.id if wizard.sync_limit > 200 or wizard.sync_limit < 1: raise osv.except_osv(_("Warning"), _('Sync limit should between 1 to 200 for Gengo translation services.')) - if wizard.sync_type in ['send','both']: + if wizard.sync_type in ['send', 'both']: self._sync_request(cr, uid, wizard.sync_limit, context=ctx) - if wizard.sync_type in ['receive','both']: - self._sync_response( cr, uid, wizard.sync_limit, context=ctx) + if wizard.sync_type in ['receive', 'both']: + self._sync_response(cr, uid, wizard.sync_limit, context=ctx) return {'type': 'ir.actions.act_window_close'} def _sync_response(self, cr, uid, limit=GENGO_DEFAULT_LIMIT, context=None): """ This method will be called by cron services to get translations from - Gengo. It will read translated terms and comments from Gengo and will + Gengo. It will read translated terms and comments from Gengo and will update respective ir.translation in openerp. """ translation_pool = self.pool.get('ir.translation') @@ -116,31 +116,36 @@ class base_gengo_translations(osv.osv_memory): if not flag: _logger.warning("%s", gengo) else: - translation_id = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine','standard','pro','ultra')), ('job_id', "!=",False)], limit=limit, context=context) - translation_terms = translation_pool.browse(cr, uid, translation_id, context=context) - gengo_job_id = [term.job_id for term in translation_terms] - if gengo_job_id: - gengo_ids = ','.join(gengo_job_id) - job_response = gengo.getTranslationJobBatch(id=gengo_ids) - if job_response['opstat'] == 'ok': - job_response_dict = dict([(job['job_id'],job) for job in job_response['response']['jobs']]) - for term in translation_terms: - up_term = up_comment = 0 - vals={} - if job_response_dict[term.job_id]['status'] == 'approved': - vals.update({'state': 'translated', - 'value': job_response_dict[term.job_id]['body_tgt']}) - up_term += 1 - job_comment = gengo.getTranslationJobComments(id=term.job_id) - if job_comment['opstat']=='ok': - gengo_comments="" - for comment in job_comment['response']['thread']: - gengo_comments += _('%s\n-- Commented on %s by %s.\n\n') % (comment['body'], time.ctime(comment['ctime']), comment['author']) - vals.update({'gengo_comment': gengo_comments}) - up_comment += 1 - if vals: - translation_pool.write(cr, uid, term.id, vals) - _logger.info("Successfully Updated `%d` terms and %d Comments." % (up_term, up_comment )) + offset = 0 + while True: + translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine','standard','pro','ultra')), ('job_id', "!=",False)], limit=limit, offset=offset, context=context) + if not translation_ids: + break + offset += limit + translation_terms = translation_pool.browse(cr, uid, translation_ids, context=context) + gengo_job_id = [term.job_id for term in translation_terms] + if gengo_job_id: + gengo_ids = ','.join(gengo_job_id) + job_response = gengo.getTranslationJobBatch(id=gengo_ids) + if job_response['opstat'] == 'ok': + job_response_dict = dict([(job['job_id'],job) for job in job_response['response']['jobs']]) + for term in translation_terms: + up_term = up_comment = 0 + vals={} + if job_response_dict[term.job_id]['status'] == 'approved': + vals.update({'state': 'translated', + 'value': job_response_dict[term.job_id]['body_tgt']}) + up_term += 1 + job_comment = gengo.getTranslationJobComments(id=term.job_id) + if job_comment['opstat']=='ok': + gengo_comments="" + for comment in job_comment['response']['thread']: + gengo_comments += _('%s\n-- Commented on %s by %s.\n\n') % (comment['body'], time.ctime(comment['ctime']), comment['author']) + vals.update({'gengo_comment': gengo_comments}) + up_comment += 1 + if vals: + translation_pool.write(cr, uid, term.id, vals) + _logger.info("Successfully Updated `%d` terms and %d Comments." % (up_term, up_comment )) return True def _update_terms(self, cr, uid, response, context=None): @@ -187,7 +192,7 @@ class base_gengo_translations(osv.osv_memory): return {'jobs': jobs} - def _send_translation_terms(self, cr, uid, term_ids, context=None): + def _send_translation_terms(self, cr, uid, term_ids, context=None): """ Send a request to Gengo with all the term_ids in a different job, get the response and update the terms in database accordingly. @@ -223,13 +228,16 @@ class base_gengo_translations(osv.osv_memory): #but if this specific key is given, then we restrict the request on terms of this language only lang_ids = [context.get('gengo_language')] langs = [lang.code for lang in language_pool.browse(cr, uid, lang_ids, context=context)] - #search for the n first terms to translate - term_ids = translation_pool.search(cr, uid, [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine','standard','pro','ultra')), ('lang', 'in', langs),('job_id',"=",False)], limit=limit, context=context) - if term_ids: - self._send_translation_terms(cr, uid, term_ids, context=context) - _logger.info("%s Translation terms have been posted to Gengo successfully", len(term_ids)) - else: - _logger.info('No Translation terms to process.') + offset = 0 + while True: + #search for the n first terms to translate + term_ids = translation_pool.search(cr, uid, [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine','standard','pro','ultra')), ('lang', 'in', langs),('job_id',"=",False)], limit=limit, offset=offset, context=context) + if term_ids: + self._send_translation_terms(cr, uid, term_ids, context=context) + offset += limit + _logger.info("%s Translation terms have been posted to Gengo successfully", len(term_ids)) + else: + break except Exception, e: _logger.error("%s", e) From c6b281c3f00599ca3d6e45bccdf62fbbca46262d Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 3 Apr 2014 17:31:29 +0200 Subject: [PATCH 068/140] [FIX] share: move inheritance from res.user before the one from res.groups because res.groups need the change on res.users in its init() function. [FIX] share: call parent init() if present in res.groups bzr revid: chs@openerp.com-20140403153129-jq9zc7ityoy25c73 --- addons/share/res_users.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/addons/share/res_users.py b/addons/share/res_users.py index 9f0a47c6674..fb0dd163b6e 100644 --- a/addons/share/res_users.py +++ b/addons/share/res_users.py @@ -21,6 +21,14 @@ from openerp.osv import fields, osv from openerp import SUPERUSER_ID +class res_users(osv.osv): + _name = 'res.users' + _inherit = 'res.users' + _columns = { + 'share': fields.boolean('Share User', readonly=True, + help="External user with limited access, created only for the purpose of sharing data.") + } + class res_groups(osv.osv): _name = "res.groups" _inherit = 'res.groups' @@ -32,6 +40,9 @@ class res_groups(osv.osv): def init(self, cr): # force re-generation of the user groups view without the shared groups self.update_user_groups_view(cr, SUPERUSER_ID) + parent_class = super(res_groups, self) + if hasattr(parent_class, 'init'): + parent_class.init(cr) def get_application_groups(self, cr, uid, domain=None, context=None): if domain is None: @@ -39,15 +50,5 @@ class res_groups(osv.osv): domain.append(('share', '=', False)) return super(res_groups, self).get_application_groups(cr, uid, domain=domain, context=context) -res_groups() - -class res_users(osv.osv): - _name = 'res.users' - _inherit = 'res.users' - _columns = { - 'share': fields.boolean('Share User', readonly=True, - help="External user with limited access, created only for the purpose of sharing data.") - } -res_users() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 126d61796aaa0eb8dbf6375ddfd27905bb7b6e23 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 17:48:56 +0200 Subject: [PATCH 069/140] [FIX] abstract_report: correctly pass the active ids in wrapped_report.set_context, fix analytic journal from ir.ui.menu by setting a consistent context bzr revid: sle@openerp.com-20140403154856-s3i220d6w1yw4e5s --- .../project/wizard/account_analytic_journal_report.py | 5 ++++- addons/report/models/abstract_report.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/account/project/wizard/account_analytic_journal_report.py b/addons/account/project/wizard/account_analytic_journal_report.py index ab7e553435d..f2e406bc3a5 100644 --- a/addons/account/project/wizard/account_analytic_journal_report.py +++ b/addons/account/project/wizard/account_analytic_journal_report.py @@ -54,7 +54,10 @@ class account_analytic_journal_report(osv.osv_memory): 'model': 'account.analytic.journal', 'form': data } - return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticjournal', data=datas, context=context) + context2 = context.copy() + context2['active_model'] = 'account.analytic.journal' + context2['active_ids'] = ids_list + return self.pool['report'].get_action(cr, uid, ids, 'account.report_analyticjournal', data=datas, context=context2) def default_get(self, cr, uid, fields, context=None): if context is None: diff --git a/addons/report/models/abstract_report.py b/addons/report/models/abstract_report.py index 730d47287c5..2da32b6c0f6 100644 --- a/addons/report/models/abstract_report.py +++ b/addons/report/models/abstract_report.py @@ -51,7 +51,7 @@ class AbstractReport(osv.AbstractModel): # Generate the old style report wrapped_report = self._wrapped_report_class(cr, uid, '', context=context) - wrapped_report.set_context(objects, data, ids) + wrapped_report.set_context(objects, data, context['active_ids']) # Rendering self._template with the wrapped report instance localcontext as # rendering environment From d5c06607b69680f13eece3700d801c5507fb0599 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 18:01:33 +0200 Subject: [PATCH 070/140] [FIX] Report: in the save_in_attachment logic, when a single report is printed, use the id passed in argument to identify it (and not the qweb branding) bzr revid: sle@openerp.com-20140403160133-4axmxhw7bq2yf94l --- addons/report/models/report.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index bf1b34b9f2a..9a65134b0b1 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -233,6 +233,14 @@ class Report(osv.Model): body = lxml.html.tostring(node) reportcontent = self.MINIMAL_HTML_PAGE.format(css=css, subst='', body=body, base_url=base_url) + + # FIXME: imo the best way to extract record id from html reports is by using the + # qweb branding. As website editor is not yet splitted in a module independant from + # website, when we print a unique report we can use the id passed in argument to + # identify it. + if len(ids) == 1: + reportid = ids[0] + contenthtml.append(tuple([reportid, reportcontent])) except lxml.etree.XMLSyntaxError: From e98131e0cdc24858459d88187e6016074fd40ac9 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 3 Apr 2014 18:20:05 +0200 Subject: [PATCH 071/140] [FIX] ir.qweb: avoid errors with function fields of type datetime bzr revid: odo@openerp.com-20140403162005-i6lbbj6uco6dnrkq --- openerp/addons/base/ir/ir_qweb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index e9e0386b4e2..f6387d8c2aa 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -602,7 +602,7 @@ class DateTimeConverter(osv.AbstractModel): if isinstance(value, basestring): value = datetime.datetime.strptime( value, openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT) - value = column.context_timestamp( + value = fields.datetime.context_timestamp( cr, uid, timestamp=value, context=context) if options and 'format' in options: From ff1e5edceaa2f3acdb5620ef29312a5e541b20b7 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 18:21:38 +0200 Subject: [PATCH 072/140] [FIX] guess the language in which the document must be translated without triggering an orm warning bzr revid: sle@openerp.com-20140403162138-6yvh3q24n39tdi4r --- addons/report/models/report.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 9a65134b0b1..96296d50218 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -124,9 +124,9 @@ class Report(osv.Model): else: # Guessing the lang we want to translate the doc into newlang = None - if hasattr(doc, 'partner_id'): + if doc._model._all_columns.get('partner_id'): newlang = doc.partner_id.lang - elif hasattr(doc, 'lang'): + elif doc._model._all_columns.get('lang'): newlang = doc.lang if newlang: ctx['lang'] = newlang From effa87f79404f0100cf78bc65087fd1693732a20 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Thu, 3 Apr 2014 18:26:50 +0200 Subject: [PATCH 073/140] [IMP] ir.actions: add Warning in eval context for server actions This way one can do `raise Warning(Foo)` to abort a transaction and show a user-friendly warning to the user. bzr revid: odo@openerp.com-20140403162650-m7zmmr9dba7jnzxp --- openerp/addons/base/ir/ir_actions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 2e95b3ee306..748e209bb54 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -935,6 +935,7 @@ class ir_actions_server(osv.osv): 'uid': uid, 'user': user, 'context': context, + 'Warning': openerp.exceptions.Warning, } return eval_context From 3a917639c84b37459a419b4db28a0dcdd9982afd Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 18:50:51 +0200 Subject: [PATCH 074/140] [FIX] report: there are not always ids in get_pdf... bzr revid: sle@openerp.com-20140403165051-e6sg419c19xv3w7b --- addons/report/models/report.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 96296d50218..723c098ccb2 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -238,7 +238,7 @@ class Report(osv.Model): # qweb branding. As website editor is not yet splitted in a module independant from # website, when we print a unique report we can use the id passed in argument to # identify it. - if len(ids) == 1: + if ids and len(ids) == 1: reportid = ids[0] contenthtml.append(tuple([reportid, reportcontent])) From a1f08e0d103e96268c5bbd1a83d0869d1bfba44d Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 23:17:17 +0200 Subject: [PATCH 075/140] [FIX] action manager: use EncodeURIComponent instead of EncodeURI because of bad encoding of the ampersand in the secund (resulting in impossibility to encode 'Belgium Profit & Loss' for instance) bzr revid: sle@openerp.com-20140403211717-sb84ir2ts62yizzf --- addons/report/static/src/js/qwebactionmanager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js index aa98b2c9c52..3910cab4dd7 100644 --- a/addons/report/static/src/js/qwebactionmanager.js +++ b/addons/report/static/src/js/qwebactionmanager.js @@ -33,8 +33,8 @@ openerp.report = function(instance) { report_url += "/" + action.context.active_ids.join(','); } } else { - report_url += "?options=" + encodeURI(JSON.stringify(action.data)); - report_url += "&context=" + encodeURI(JSON.stringify(action.context)); + report_url += "?options=" + encodeURIComponent(JSON.stringify(action.data)); + report_url += "&context=" + encodeURIComponent(JSON.stringify(action.context)); } if (action.report_type == 'qweb-html') { From 0cbd5fb87b39683689e9694ba369e5a94ef33e1d Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Thu, 3 Apr 2014 23:22:38 +0200 Subject: [PATCH 076/140] [REM] Removed the luxembourg tax report (this report is now deprecated as LU only accepts xml etva or onlineform filling) bzr revid: sle@openerp.com-20140403212238-rf85l911i2g5da3t --- addons/l10n_lu/__init__.py | 2 - addons/l10n_lu/__openerp__.py | 5 +- addons/l10n_lu/test/l10n_lu_report.yml | 18 ---- addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf | Bin 384828 -> 0 bytes addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf | Bin 291286 -> 0 bytes addons/l10n_lu/wizard/__init__.py | 24 ----- addons/l10n_lu/wizard/pdf_ext.py | 110 ---------------------- addons/l10n_lu/wizard/print_vat.py | 96 ------------------- addons/l10n_lu/wizard/print_vat_view.xml | 39 -------- 9 files changed, 2 insertions(+), 292 deletions(-) delete mode 100644 addons/l10n_lu/test/l10n_lu_report.yml delete mode 100644 addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf delete mode 100644 addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf delete mode 100644 addons/l10n_lu/wizard/__init__.py delete mode 100644 addons/l10n_lu/wizard/pdf_ext.py delete mode 100644 addons/l10n_lu/wizard/print_vat.py delete mode 100644 addons/l10n_lu/wizard/print_vat_view.xml diff --git a/addons/l10n_lu/__init__.py b/addons/l10n_lu/__init__.py index 0e933f136e0..9a6ca02408e 100644 --- a/addons/l10n_lu/__init__.py +++ b/addons/l10n_lu/__init__.py @@ -19,6 +19,4 @@ # ############################################################################## -import wizard - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/__openerp__.py b/addons/l10n_lu/__openerp__.py index 46d2312bb02..96c4ea64dea 100644 --- a/addons/l10n_lu/__openerp__.py +++ b/addons/l10n_lu/__openerp__.py @@ -22,7 +22,6 @@ # ############################################################################## - { 'name': 'Luxembourg - Accounting', 'version': '1.0', @@ -51,12 +50,12 @@ This is the base module to manage the accounting chart for Luxembourg. 'account.fiscal.position.tax.template-2011.csv', # configuration wizard, views, reports... 'l10n_lu_wizard.xml', - 'wizard/print_vat_view.xml' ], - 'test': ['test/l10n_lu_report.yml'], + 'test': [], 'demo': [], 'installable': True, 'auto_install': False, 'images': ['images/config_chart_l10n_lu.jpeg','images/l10n_lu_chart.jpeg'], } + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/test/l10n_lu_report.yml b/addons/l10n_lu/test/l10n_lu_report.yml deleted file mode 100644 index 0ee032d581c..00000000000 --- a/addons/l10n_lu/test/l10n_lu_report.yml +++ /dev/null @@ -1,18 +0,0 @@ -- - It is demo data for the account.tax.code -- - !record {model: account.tax.code, id: account_tax_code_id_r1}: - name: a - -- - In order to test the PDF reports defined on a l10u_lu, we will print a VAT Report -- - !python {model: res.partner}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [], 'l10n_lu.tax.report.print', {'model':'ir.ui.menu', 'form':{'tax_code_id': ref('account_tax_code_id_r1'), 'period_id': ref('account.period_1')}}, {}) - if tools.config['test_report_directory']: - file(os.path.join(tools.config['test_report_directory'], 'l10n_lu-vat_report.'+format), 'wb+').write(data) - - diff --git a/addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf b/addons/l10n_lu/wizard/TVA_MEN_09_xxxx.pdf deleted file mode 100644 index 9df4ae34065816a636cc5c4805eee2a541f7cbcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384828 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%0AZ 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 SYM?AP3Wn0Tr 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
    c5Y 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 XrtmP#94su%0C*TOGEsRkc$ohK75}?> diff --git a/addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf b/addons/l10n_lu/wizard/TVA_TRI_10_xxxx.pdf deleted file mode 100644 index 0699bbcb7d93a7a19f01121ebe322d38adec82e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 291286 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

    s-Do>o_;71 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

    GKEHh3YP~&? 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 DL65k) diff --git a/addons/l10n_lu/wizard/__init__.py b/addons/l10n_lu/wizard/__init__.py deleted file mode 100644 index 140f04905ab..00000000000 --- a/addons/l10n_lu/wizard/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -import print_vat - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/wizard/pdf_ext.py b/addons/l10n_lu/wizard/pdf_ext.py deleted file mode 100644 index 94f150e41d7..00000000000 --- a/addons/l10n_lu/wizard/pdf_ext.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -""" Copyright (c) 2003-2007 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ -- mailto:contact@logilab.fr - -manipulate pdf and fdf files. pdftk recommended. - -Notes regarding pdftk, pdf forms and fdf files (form definition file) -fields names can be extracted with: - pdftk orig.pdf generate_fdf output truc.fdf -to merge fdf and pdf: - pdftk orig.pdf fill_form test.fdf output result.pdf [flatten] -without flatten, one could further edit the resulting form. -with flatten, everything is turned into text. -""" - -import os -from openerp import tools - -HEAD="""%FDF-1.2 -%\xE2\xE3\xCF\xD3 -1 0 obj -<< -/FDF -<< -/Fields [ -""" - -TAIL="""] ->> ->> -endobj -trailer - -<< -/Root 1 0 R ->> -%%EOF -""" - -def output_field(f): - return "\xfe\xff" + "".join( [ "\x00"+c for c in f ] ) - -def extract_keys(lines): - keys = [] - for line in lines: - if line.startswith('/V'): - pass - elif line.startswith('/T'): - key = line[7:-2] - key = ''.join(key.split('\x00')) - keys.append( key ) - return keys - -def write_field(out, key, value): - out.write("<<\n") - if value: - out.write("/V (%s)\n" %value) - else: - out.write("/V /\n") - out.write("/T (%s)\n" % output_field(key) ) - out.write(">> \n") - -def write_fields(out, fields): - out.write(HEAD) - for key in fields: - value = fields[key] - write_field(out, key, value) - out.write(TAIL) - -def extract_keys_from_pdf(filename): - # what about using 'pdftk filename dump_data_fields' and parsing the output ? - os.system('pdftk %s generate_fdf output /tmp/toto.fdf' % filename) - lines = file('/tmp/toto.fdf').readlines() - return extract_keys(lines) - - -def fill_pdf(infile, outfile, fields): - write_fields(file('/tmp/toto.fdf', 'w'), fields) - os.system('pdftk %s fill_form /tmp/toto.fdf output %s flatten' % (infile, outfile)) - -def testfill_pdf(infile, outfile): - keys = extract_keys_from_pdf(infile) - fields = [] - for key in keys: - fields.append( (key, key, '') ) - fill_pdf(infile, outfile, fields) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/l10n_lu/wizard/print_vat.py b/addons/l10n_lu/wizard/print_vat.py deleted file mode 100644 index 04d4fe9a3b7..00000000000 --- a/addons/l10n_lu/wizard/print_vat.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) Vincent Cardon -# Denis Cardon and Emmanuel RICHARD. -#Ingenieur fondateur -#Tranquil IT Systems - -from __future__ import with_statement - -import openerp -from openerp.osv import fields, osv -from openerp import tools -from openerp.modules.module import get_module_resource -from openerp.tools.translate import _ -from openerp.report.render import render -from openerp.report.interface import report_int -import tempfile -import os - -class external_pdf(render): - - def __init__(self, pdf): - render.__init__(self) - self.pdf = pdf - self.output_type='pdf' - - def _render(self): - return self.pdf - - -class report_custom(report_int): - - def create(self, cr, uid, ids, datas, context=None): - - registry = openerp.registry(cr.dbname) - taxobj = registry['account.tax.code'] - - if context is None: - context = {} - code_ids = taxobj.search(cr, uid, [('parent_id','child_of',[datas['form']['tax_code_id']])]) - result = {} - for t in taxobj.browse(cr, uid, code_ids, {'period_id': datas['form']['period_id']}): - if str(t.code): - result['case_'+str(t.code)] = '%.2f' % (t.sum_period or 0.0, ) - user = registry['res.users'].browse(cr, uid, uid, context) - - # Not Clean, to be changed - partner = user.company_id.partner_id - result['info_name'] = user.company_id.name - result['info_vatnum'] = partner.vat - if partner: - result['info_address'] = partner.street - result['info_address2'] = (partner.zip or '') + ' ' + (partner.city or '') - try: - tmp_file = tempfile.mkstemp(".pdf")[1] - try: - tools.pdf_utils.fill_pdf(get_module_resource('l10n_lu','wizard', '2008_DECL_F_M10.pdf'), tmp_file, result) - with open(tmp_file, "r") as ofile: - self.obj = external_pdf(ofile.read()) - finally: - try: - os.remove(tmp_file) - except: - pass # nothing to do - self.obj.render() - return (self.obj.pdf, 'pdf') - except Exception: - raise osv.except_osv(_('PDF Not Created!'), _('Please check if package pdftk is installed!')) - -report_custom('report.l10n_lu.tax.report.print') - -class vat_declaration_report(osv.osv_memory): - _name = 'vat.declaration.report' - _description = 'VAT Declaration Report' - - _columns = { - 'tax_code_id': fields.many2one('account.tax.code', 'Company', readonly=False, required=True, domain=[('parent_id','=',False)]), - 'type': fields.selection([('monthly','Monthly'),('quarterly','Quaterly'),('yearly','Yearly')], 'Type', required=True), - 'period_id' : fields.many2one('account.period', 'From Period', required=True), - 'to_period_id': fields.many2one('account.period', 'To Period', required=True), - } - - _defaults = { - 'type': 'monthly', - } - - def print_vat_declaration_report(self, cr, uid, ids, context=None): - active_ids = context.get('active_ids',[]) - data = {} - data['form'] = {} - data['ids'] = active_ids - data['form']['tax_code_id'] = self.browse(cr, uid, ids)[0].tax_code_id.id - data['form']['period_id'] = self.browse(cr, uid, ids)[0].period_id.id - return { 'type': 'ir.actions.report.xml', 'report_name': 'l10n_lu.tax.report.print', 'datas': data} - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/l10n_lu/wizard/print_vat_view.xml b/addons/l10n_lu/wizard/print_vat_view.xml deleted file mode 100644 index 61a29378163..00000000000 --- a/addons/l10n_lu/wizard/print_vat_view.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - VAT Declaration Report - vat.declaration.report - - - - - - - - -
    -
    - -
    -
    - - - VAT Declaration Report - ir.actions.act_window - vat.declaration.report - form - form - - new - - - - - -
    - -
    From 8f174e13bdb603065978419b67c32370ba1c3ea9 Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of openerp <> Date: Fri, 4 Apr 2014 07:07:59 +0000 Subject: [PATCH 077/140] Launchpad automatic translations update. bzr revid: launchpad_translations_on_behalf_of_openerp-20140404070722-99m3lomg172fzapc bzr revid: launchpad_translations_on_behalf_of_openerp-20140404070759-302tyo6k09v8arhz --- addons/account_asset/i18n/sv.po | 30 +++++-- addons/delivery/i18n/sv.po | 54 +++++++++--- addons/hr/i18n/sv.po | 8 +- addons/hr_attendance/i18n/sv.po | 31 ++++--- addons/hr_expense/i18n/sv.po | 47 ++++++---- addons/hr_holidays/i18n/sv.po | 112 +++++++++++++++--------- addons/hr_payroll/i18n/sv.po | 60 ++++++++----- addons/mail/i18n/sv.po | 61 ++++++++----- addons/sale/i18n/sv.po | 124 ++++++++++++++++++++++++--- addons/stock/i18n/zh_TW.po | 12 +-- openerp/addons/base/i18n/ab.po | 4 +- openerp/addons/base/i18n/af.po | 4 +- openerp/addons/base/i18n/am.po | 4 +- openerp/addons/base/i18n/ar.po | 4 +- openerp/addons/base/i18n/bg.po | 4 +- openerp/addons/base/i18n/bn.po | 4 +- openerp/addons/base/i18n/bs.po | 6 +- openerp/addons/base/i18n/ca.po | 4 +- openerp/addons/base/i18n/cs.po | 4 +- openerp/addons/base/i18n/da.po | 4 +- openerp/addons/base/i18n/de.po | 4 +- openerp/addons/base/i18n/el.po | 4 +- openerp/addons/base/i18n/en_GB.po | 4 +- openerp/addons/base/i18n/es.po | 4 +- openerp/addons/base/i18n/es_AR.po | 4 +- openerp/addons/base/i18n/es_BO.po | 4 +- openerp/addons/base/i18n/es_CL.po | 4 +- openerp/addons/base/i18n/es_CR.po | 4 +- openerp/addons/base/i18n/es_DO.po | 4 +- openerp/addons/base/i18n/es_EC.po | 4 +- openerp/addons/base/i18n/es_MX.po | 7 +- openerp/addons/base/i18n/es_PE.po | 6 +- openerp/addons/base/i18n/es_VE.po | 4 +- openerp/addons/base/i18n/et.po | 6 +- openerp/addons/base/i18n/eu.po | 4 +- openerp/addons/base/i18n/fa.po | 4 +- openerp/addons/base/i18n/fa_AF.po | 4 +- openerp/addons/base/i18n/fi.po | 4 +- openerp/addons/base/i18n/fr.po | 4 +- openerp/addons/base/i18n/fr_CA.po | 6 +- openerp/addons/base/i18n/gl.po | 4 +- openerp/addons/base/i18n/gu.po | 4 +- openerp/addons/base/i18n/he.po | 4 +- openerp/addons/base/i18n/hi.po | 4 +- openerp/addons/base/i18n/hr.po | 4 +- openerp/addons/base/i18n/hu.po | 40 ++++----- openerp/addons/base/i18n/hy.po | 4 +- openerp/addons/base/i18n/id.po | 4 +- openerp/addons/base/i18n/is.po | 4 +- openerp/addons/base/i18n/it.po | 6 +- openerp/addons/base/i18n/ja.po | 4 +- openerp/addons/base/i18n/ka.po | 4 +- openerp/addons/base/i18n/kk.po | 4 +- openerp/addons/base/i18n/ko.po | 4 +- openerp/addons/base/i18n/lt.po | 4 +- openerp/addons/base/i18n/lv.po | 4 +- openerp/addons/base/i18n/mk.po | 4 +- openerp/addons/base/i18n/mn.po | 4 +- openerp/addons/base/i18n/nb.po | 4 +- openerp/addons/base/i18n/nl.po | 4 +- openerp/addons/base/i18n/nl_BE.po | 4 +- openerp/addons/base/i18n/pl.po | 4 +- openerp/addons/base/i18n/pt.po | 4 +- openerp/addons/base/i18n/pt_BR.po | 4 +- openerp/addons/base/i18n/ro.po | 4 +- openerp/addons/base/i18n/ru.po | 4 +- openerp/addons/base/i18n/sk.po | 4 +- openerp/addons/base/i18n/sl.po | 4 +- openerp/addons/base/i18n/sq.po | 4 +- openerp/addons/base/i18n/sr.po | 4 +- openerp/addons/base/i18n/sr@latin.po | 4 +- openerp/addons/base/i18n/sv.po | 4 +- openerp/addons/base/i18n/th.po | 4 +- openerp/addons/base/i18n/tlh.po | 4 +- openerp/addons/base/i18n/tr.po | 4 +- openerp/addons/base/i18n/uk.po | 4 +- openerp/addons/base/i18n/ur.po | 4 +- openerp/addons/base/i18n/vi.po | 4 +- openerp/addons/base/i18n/zh_CN.po | 4 +- openerp/addons/base/i18n/zh_HK.po | 4 +- openerp/addons/base/i18n/zh_TW.po | 4 +- 81 files changed, 546 insertions(+), 326 deletions(-) diff --git a/addons/account_asset/i18n/sv.po b/addons/account_asset/i18n/sv.po index e95872c9ff0..83e412a1d42 100644 --- a/addons/account_asset/i18n/sv.po +++ b/addons/account_asset/i18n/sv.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-03-27 12:09+0000\n" +"PO-Revision-Date: 2014-04-03 22:23+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-28 06:44+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: account_asset #: view:account.asset.asset:0 @@ -440,12 +440,17 @@ msgid "" "You can manually close an asset when the depreciation is over. If the last " "line of depreciation is posted, the asset automatically goes in that status." msgstr "" +"När en inventarie har skapats, är statusen \"Utkast\".\n" +"Om inventarien är bekräftad, går status i \"Aktiv\" och avskrivningslraderna " +"kan postas i redovisningen.\n" +"Du kan stänga manuellt en inventarie när avskrivningen är över. Om den sista " +"raden i avskrivning postas, går tillgången automatiskt i denna status." #. module: account_asset #: field:account.asset.asset,state:0 #: field:asset.asset.report,state:0 msgid "Status" -msgstr "" +msgstr "Status" #. module: account_asset #: field:account.asset.asset,partner_id:0 @@ -492,7 +497,7 @@ msgstr "Beräkna" #. module: account_asset #: view:account.asset.history:0 msgid "Asset History" -msgstr "" +msgstr "Inventariehistorik" #. module: account_asset #: model:ir.model,name:account_asset.model_asset_depreciation_confirmation_wizard @@ -605,6 +610,7 @@ msgstr "Aktuellt" #, python-format msgid "You cannot delete an asset that contains posted depreciation lines." msgstr "" +"Du kan inte ta bort en inventarie som innehåller bokförda avskrivningsrader." #. module: account_asset #: view:account.asset.category:0 @@ -614,12 +620,12 @@ msgstr "Avskrivningsmetod" #. module: account_asset #: field:account.asset.depreciation.line,amount:0 msgid "Current Depreciation" -msgstr "" +msgstr "Aktuell avskrivningsgrad" #. module: account_asset #: field:account.asset.asset,name:0 msgid "Asset Name" -msgstr "" +msgstr "Inventarienamn" #. module: account_asset #: field:account.asset.category,open_asset:0 @@ -679,6 +685,14 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Ur denna rapport kan du få en överblick på alla avskrivningar. " +"Den\n" +" verktygsökning kan också användas för att anpassa dina " +"inventarierapporter och\n" +" så, matcha denna analys till dina behov;\n" +" \n" +" " #. module: account_asset #: field:account.asset.asset,purchase_value:0 @@ -736,7 +750,7 @@ msgstr "" #. module: account_asset #: field:account.asset.depreciation.line,sequence:0 msgid "Sequence" -msgstr "" +msgstr "Nummerserie" #. module: account_asset #: help:account.asset.category,method_period:0 diff --git a/addons/delivery/i18n/sv.po b/addons/delivery/i18n/sv.po index 9067f5ea56c..36bc1f25b67 100644 --- a/addons/delivery/i18n/sv.po +++ b/addons/delivery/i18n/sv.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-03-31 16:57+0000\n" +"PO-Revision-Date: 2014-04-03 10:23+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-01 06:52+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: delivery #: report:sale.shipping:0 @@ -30,7 +30,7 @@ msgstr "Leverans per post" #. module: delivery #: view:delivery.grid.line:0 msgid " in Function of " -msgstr "" +msgstr " är en funktion av " #. module: delivery #: view:delivery.carrier:0 @@ -93,6 +93,8 @@ msgstr "Utgående Leverans" #, python-format msgid "No line matched this product or order in the chosen delivery grid." msgstr "" +"Ingen rad matchade denna produkt eller order inom det valda " +"leveranskombinationen." #. module: delivery #: model:ir.actions.act_window,name:delivery.action_picking_tree4 @@ -132,6 +134,19 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Klicka för att skapa en leveransprislista för en viss " +"region.\n" +"

    \n" +" Med leveransprislistan kan du beräkna kostnaden och\n" +" försäljningspriset för leveransen baserat på produkternas " +"vikt\n" +" och andra kriterier. Du kan definiera flera prislistor\n" +" för varje leveransmetod: per land eller ett område i ett " +"visst\n" +" land som definieras av ett postnummerområde.\n" +"

    \n" +" " #. module: delivery #: report:sale.shipping:0 @@ -151,7 +166,7 @@ msgstr "Mängd" #. module: delivery #: view:sale.order:0 msgid "Add in Quote" -msgstr "" +msgstr "Lägg till på offert" #. module: delivery #: selection:delivery.grid.line,price_type:0 @@ -232,6 +247,8 @@ msgid "" "If you don't 'Add in Quote', the exact price will be computed when invoicing " "based on delivery order(s)." msgstr "" +"Om du inte \"Lägg i offert\", kommer det exakta priset beräknas vid " +"fakturering baserad på leveransordern." #. module: delivery #: field:delivery.carrier,partner_id:0 @@ -276,7 +293,7 @@ msgstr "Beloppsgräns för fri frakt i företagets valuta" #. module: delivery #: field:delivery.carrier,free_if_more_than:0 msgid "Free If Order Total Amount Is More Than" -msgstr "" +msgstr "Fritt vid ordertotal över" #. module: delivery #: field:delivery.grid.line,grid_id:0 @@ -432,6 +449,21 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Klicka för att definiera en ny leveransmetod.\n" +"

    \n" +" Varje transportör (t.ex. UPS) kan ha flera leveransmetoder " +"(t.ex.\n" +" UPS Express, UPS Standard) med en uppsättning av " +"prissättningsregler knuten\n" +" till varje metod.\n" +"

    \n" +" Dessa metoder gör det möjligt att automatiskt beräkna " +"leveranspriset\n" +" enligt dina inställningar; på kundordern (baserat på\n" +" offert) eller faktura (baserat på leveransorder).\n" +"

    \n" +" " #. module: delivery #: field:delivery.grid.line,max_value:0 @@ -465,7 +497,7 @@ msgstr "Fritt om det överstiger %.2f" #. module: delivery #: model:ir.model,name:delivery.model_stock_picking_in msgid "Incoming Shipments" -msgstr "" +msgstr "Inkommande leveranser" #. module: delivery #: selection:delivery.grid.line,operator:0 @@ -475,7 +507,7 @@ msgstr "<=" #. module: delivery #: help:stock.picking,weight_uom_id:0 msgid "Unit of measurement for Weight" -msgstr "" +msgstr "Viktsenhet" #. module: delivery #: report:sale.shipping:0 @@ -550,7 +582,7 @@ msgstr "Speditör" #: model:ir.actions.act_window,name:delivery.action_delivery_carrier_form #: model:ir.ui.menu,name:delivery.menu_action_delivery_carrier_form msgid "Delivery Methods" -msgstr "" +msgstr "Leveransmetoder" #. module: delivery #: code:addons/delivery/sale.py:57 @@ -577,7 +609,7 @@ msgstr "Försäljningspris" #. module: delivery #: view:stock.picking.out:0 msgid "Print Delivery Order" -msgstr "" +msgstr "Skriv ut leveransorder" #. module: delivery #: view:delivery.grid:0 @@ -589,7 +621,7 @@ msgstr "Tillstånd" #: help:stock.move,weight_uom_id:0 msgid "" "Unit of Measure (Unit of Measure) is the unit of measurement for Weight" -msgstr "" +msgstr "Enhet är måttenheten för vikt" #. module: delivery #: field:delivery.grid.line,price_type:0 diff --git a/addons/hr/i18n/sv.po b/addons/hr/i18n/sv.po index 2f08a0c9526..baa00de4231 100644 --- a/addons/hr/i18n/sv.po +++ b/addons/hr/i18n/sv.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-04-02 13:01+0000\n" +"PO-Revision-Date: 2014-04-04 06:48+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-03 06:01+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: hr #: model:process.node,name:hr.process_node_openerpuser0 @@ -169,7 +169,7 @@ msgstr "Född" #: model:ir.actions.act_window,name:hr.open_view_categ_form #: model:ir.ui.menu,name:hr.menu_view_employee_category_form msgid "Employee Tags" -msgstr "Etiketter på anställda" +msgstr "Medarbetaretiketter" #. module: hr #: view:hr.job:0 diff --git a/addons/hr_attendance/i18n/sv.po b/addons/hr_attendance/i18n/sv.po index 5dd39961d5a..3d4c87f2592 100644 --- a/addons/hr_attendance/i18n/sv.po +++ b/addons/hr_attendance/i18n/sv.po @@ -8,19 +8,19 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:37+0000\n" -"PO-Revision-Date: 2014-03-19 07:45+0000\n" +"PO-Revision-Date: 2014-04-04 06:54+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 06:19+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: hr_attendance #: model:ir.model,name:hr_attendance.model_hr_attendance_month msgid "Print Monthly Attendance Report" -msgstr "Skriv månatlig närvarorapport" +msgstr "" #. module: hr_attendance #: view:hr.attendance:0 @@ -37,7 +37,7 @@ msgstr "Senaste stämpling" #: field:hr.employee,state:0 #: model:ir.model,name:hr_attendance.model_hr_attendance msgid "Attendance" -msgstr "Närvarande" +msgstr "Närvaro" #. module: hr_attendance #. openerp-web @@ -56,14 +56,15 @@ msgstr "" #. module: hr_attendance #: help:hr.action.reason,name:0 msgid "Specifies the reason for Signing In/Signing Out." -msgstr "Ange in/utloggningsorsak" +msgstr "Ange in/utstämplingsorsak" #. module: hr_attendance #: report:report.hr.timesheet.attendance.error:0 msgid "" "(*) A positive delay means that the employee worked less than recorded." msgstr "" -"(*) A positive delay means that the employee worked less than recorded." +"(*) Ett positiv uppehåll innebär att den anställde arbetat mindre än " +"registrerat." #. module: hr_attendance #: view:hr.attendance.month:0 @@ -127,7 +128,7 @@ msgstr "Utskrift" #: field:hr.attendance,employee_id:0 #: model:ir.model,name:hr_attendance.model_hr_employee msgid "Employee" -msgstr "Anställd" +msgstr "Medarbetare" #. module: hr_attendance #: field:hr.attendance.month,month:0 @@ -179,7 +180,7 @@ msgstr "Varning" #. module: hr_attendance #: help:hr.config.settings,group_hr_attendance:0 msgid "Allocates attendance group to all users." -msgstr "" +msgstr "Tilldela närvarogrupp till alla användare." #. module: hr_attendance #: view:hr.attendance:0 @@ -220,7 +221,7 @@ msgstr "Anledning" #. module: hr_attendance #: view:hr.attendance.error:0 msgid "Print Attendance Report Error" -msgstr "Skrivut delatagarrapportfel" +msgstr "Skriv ut närvarorapportfel" #. module: hr_attendance #: model:ir.actions.act_window,help:hr_attendance.open_view_attendance @@ -251,7 +252,7 @@ msgstr "Datum" #. module: hr_attendance #: field:hr.config.settings,group_hr_attendance:0 msgid "Track attendances for all employees" -msgstr "" +msgstr "Följ upp närvaro för alla anställda" #. module: hr_attendance #: selection:hr.attendance.month,month:0 @@ -309,7 +310,7 @@ msgstr "Anställds närvaro" #. module: hr_attendance #: view:hr.action.reason:0 msgid "Define attendance reason" -msgstr "Define attendance reason" +msgstr "Defniera frånvarorsak" #. module: hr_attendance #: selection:hr.action.reason,action_type:0 @@ -367,7 +368,7 @@ msgstr "Tidrapporter" #: model:ir.actions.act_window,name:hr_attendance.open_view_attendance_reason #: model:ir.ui.menu,name:hr_attendance.menu_open_view_attendance_reason msgid "Attendance Reasons" -msgstr "Närvaro Orsaker" +msgstr "Frånvaroorsaker" #. module: hr_attendance #: selection:hr.attendance.month,month:0 @@ -398,7 +399,7 @@ msgstr "september" #. module: hr_attendance #: view:hr.action.reason:0 msgid "Attendance reasons" -msgstr "Närvaro orsaker" +msgstr "Frånvaroorsaker" #. module: hr_attendance #: model:ir.model,name:hr_attendance.model_hr_attendance_week @@ -434,6 +435,8 @@ msgid "" "You tried to %s with a date anterior to another event !\n" "Try to contact the HR Manager to correct attendances." msgstr "" +"Du försökte %s med ett datum som föregår en annan händelse!\n" +"Försök att kontakta personalansvarig för att korrigera närvaro." #. module: hr_attendance #: selection:hr.attendance.month,month:0 diff --git a/addons/hr_expense/i18n/sv.po b/addons/hr_expense/i18n/sv.po index 8e6353ba5f3..c3647221266 100644 --- a/addons/hr_expense/i18n/sv.po +++ b/addons/hr_expense/i18n/sv.po @@ -8,20 +8,20 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-03-31 17:01+0000\n" +"PO-Revision-Date: 2014-04-04 06:12+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-01 06:52+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: hr_expense #: view:hr.expense.expense:0 #: model:process.node,name:hr_expense.process_node_confirmedexpenses0 msgid "Confirmed Expenses" -msgstr "Bekräftade utgifter" +msgstr "Bekräftade utlägg" #. module: hr_expense #: code:addons/hr_expense/hr_expense.py:349 @@ -181,7 +181,7 @@ msgstr "Produkter" #. module: hr_expense #: view:hr.expense.report:0 msgid "Confirm Expenses" -msgstr "Bekräfta utgifter" +msgstr "Bekräfta utlägg" #. module: hr_expense #: selection:hr.expense.report,state:0 @@ -266,7 +266,7 @@ msgstr "Totalt:" #. module: hr_expense #: model:process.transition,name:hr_expense.process_transition_refuseexpense0 msgid "Refuse expense" -msgstr "Avslagna utgifter" +msgstr "Avslagna utlägg" #. module: hr_expense #: field:hr.expense.report,price_average:0 @@ -340,7 +340,7 @@ msgstr "Följare" #: field:hr.expense.expense,employee_id:0 #: view:hr.expense.report:0 msgid "Employee" -msgstr "Anställd" +msgstr "Medarbetare" #. module: hr_expense #: view:hr.expense.expense:0 @@ -369,7 +369,7 @@ msgstr "Vissa kostnader kan faktureras kunden" #: code:addons/hr_expense/hr_expense.py:238 #, python-format msgid "The employee must have a home address." -msgstr "" +msgstr "Medarbetaren måste ha en hemadress" #. module: hr_expense #: view:board.board:0 @@ -386,7 +386,7 @@ msgstr "Skapad datum" #. module: hr_expense #: model:ir.actions.report.xml,name:hr_expense.hr_expenses msgid "HR expenses" -msgstr "Personalutgifter" +msgstr "Personalutlägg" #. module: hr_expense #: field:hr.expense.expense,id:0 @@ -447,7 +447,7 @@ msgstr "" #: code:addons/hr_expense/hr_expense.py:240 #, python-format msgid "The employee must have a payable account set on his home address." -msgstr "" +msgstr "Den anställde måste ha ett utgiftskonto anslutet till sin hemadress" #. module: hr_expense #: view:hr.expense.report:0 @@ -502,7 +502,7 @@ msgstr "Valuta" #. module: hr_expense #: field:hr.expense.expense,voucher_id:0 msgid "Employee's Receipt" -msgstr "" +msgstr "Medarbetarkvitto" #. module: hr_expense #: selection:hr.expense.expense,state:0 @@ -512,7 +512,7 @@ msgstr "Väntar på godkännande" #. module: hr_expense #: model:process.node,note:hr_expense.process_node_draftexpenses0 msgid "Employee encode all his expenses" -msgstr "Anställd koda alla hans utgifter" +msgstr "Medarbetare kodifierar alla sina utgifter" #. module: hr_expense #: view:hr.expense.expense:0 @@ -648,6 +648,17 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Klicka för att registrera nya utgifter.\n" +"

    \n" +" OpenERP kommer att se till att hela processen följs; " +"bekostnad\n" +" Bladet är validerat av chef (s), har arbetstagaren " +"ersättning\n" +" utlägg sina utlägg, vissa utlägg måste återfaktureras\n" +" kunder.\n" +"

    \n" +" " #. module: hr_expense #: view:hr.expense.expense:0 @@ -677,7 +688,7 @@ msgstr "" #. module: hr_expense #: model:product.template,name:hr_expense.car_travel_product_template msgid "Car Travel Expenses" -msgstr "Utgifter resor med bil" +msgstr "Bilutlägg" #. module: hr_expense #: view:hr.expense.expense:0 @@ -692,12 +703,12 @@ msgstr "" #. module: hr_expense #: model:process.node,note:hr_expense.process_node_confirmedexpenses0 msgid "The employee validates his expense sheet" -msgstr "Den anställde bekräftar sin kostnadsblankett" +msgstr "Medarbetaren granskar sin utläggsansökan" #. module: hr_expense #: view:hr.expense.expense:0 msgid "Expenses to Invoice" -msgstr "Utgifter att fakturera" +msgstr "Utlägg att fakturera" #. module: hr_expense #: model:process.node,name:hr_expense.process_node_supplierinvoice0 @@ -718,7 +729,7 @@ msgstr "" #. module: hr_expense #: view:hr.expense.report:0 msgid "Approved Expenses" -msgstr "Godkända utgifter" +msgstr "Godkända utlägg" #. module: hr_expense #: report:hr.expense:0 @@ -883,7 +894,7 @@ msgstr "Ref." #. module: hr_expense #: field:hr.expense.report,employee_id:0 msgid "Employee's Name" -msgstr "Anställds namn" +msgstr "Medarbetarens namn" #. module: hr_expense #: view:hr.expense.report:0 @@ -964,7 +975,7 @@ msgstr "Utlägg godkänt" #: model:ir.ui.menu,name:hr_expense.next_id_49 #: model:product.category,name:hr_expense.cat_expense msgid "Expenses" -msgstr "Utgifter" +msgstr "Utlägg" #. module: hr_expense #: help:product.product,hr_expense_ok:0 diff --git a/addons/hr_holidays/i18n/sv.po b/addons/hr_holidays/i18n/sv.po index 3bf5378ef53..6bbc5a77e5b 100644 --- a/addons/hr_holidays/i18n/sv.po +++ b/addons/hr_holidays/i18n/sv.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-03-31 17:00+0000\n" +"PO-Revision-Date: 2014-04-03 07:21+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-01 06:52+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: hr_holidays #: selection:hr.holidays.status,color_name:0 @@ -39,6 +39,8 @@ msgid "" "You cannot modify a leave request that has been approved. Contact a human " "resource manager." msgstr "" +"Du kan inte ändra ett redan godkänt frånvaroönskemål. Kontakta " +"personalansvarig." #. module: hr_holidays #: help:hr.holidays.status,remaining_leaves:0 @@ -75,7 +77,7 @@ msgstr "Avdelning" #: model:ir.actions.act_window,name:hr_holidays.request_approve_allocation #: model:ir.ui.menu,name:hr_holidays.menu_request_approve_allocation msgid "Allocation Requests to Approve" -msgstr "" +msgstr "Frånvaroönskemål att godkänna" #. module: hr_holidays #: help:hr.holidays,category_id:0 @@ -112,12 +114,12 @@ msgstr "" #. module: hr_holidays #: model:mail.message.subtype,description:hr_holidays.mt_holidays_refused msgid "Request refused" -msgstr "" +msgstr "Önskemål tillbakavisat" #. module: hr_holidays #: field:hr.holidays,number_of_days_temp:0 msgid "Allocation" -msgstr "Allokering" +msgstr "Tilldelning" #. module: hr_holidays #: xsl:holidays.summary:0 @@ -132,7 +134,7 @@ msgstr "Ljus cyan" #. module: hr_holidays #: constraint:hr.holidays:0 msgid "You can not have 2 leaves that overlaps on same day!" -msgstr "" +msgstr "Du kan inte ha två ledigheter som överlappar samma dag!" #. module: hr_holidays #: selection:hr.holidays.status,color_name:0 @@ -233,7 +235,7 @@ msgstr "Granskning" #. module: hr_holidays #: help:hr.holidays,message_unread:0 msgid "If checked new messages require your attention." -msgstr "" +msgstr "Om ikryssad nya meddelanden som kräver din uppmärksamhet" #. module: hr_holidays #: field:hr.holidays.status,color_name:0 @@ -263,6 +265,8 @@ msgid "" "Holds the Chatter summary (number of messages, ...). This summary is " "directly in html format in order to be inserted in kanban views." msgstr "" +"Lagrar pladder-sammanfattning (antal meddelanden, ...). Denna sammanfattning " +"presenteras i html-format för att kunna sättas in i kanban vyer." #. module: hr_holidays #: code:addons/hr_holidays/hr_holidays.py:249 @@ -283,12 +287,12 @@ msgstr "Magenta" #. module: hr_holidays #: model:ir.actions.act_window,name:hr_holidays.act_hr_leave_request_to_meeting msgid "Leave Meetings" -msgstr "" +msgstr "Frånvaromöten" #. module: hr_holidays #: model:hr.holidays.status,name:hr_holidays.holiday_status_cl msgid "Legal Leaves 2013" -msgstr "" +msgstr "Lagstadgad ledighet 2013" #. module: hr_holidays #: selection:hr.holidays.summary.dept,holiday_type:0 @@ -322,7 +326,7 @@ msgstr "Summa" #: view:hr.holidays.status:0 #: model:ir.actions.act_window,name:hr_holidays.open_view_holiday_status msgid "Leave Types" -msgstr "" +msgstr "Frånvarotyper" #. module: hr_holidays #: field:hr.holidays.status,remaining_leaves:0 @@ -332,7 +336,7 @@ msgstr "Återstående ledighet" #. module: hr_holidays #: field:hr.holidays,message_follower_ids:0 msgid "Followers" -msgstr "" +msgstr "Följare" #. module: hr_holidays #: model:ir.model,name:hr_holidays.model_hr_holidays_remaining_leaves_user @@ -395,6 +399,10 @@ msgid "" " \n" "The status is 'Approved', when holiday request is approved by manager." msgstr "" +"Statusen är satt till \"att skicka in\", när en semesterbegäran skapas.\n" +"Statusen är \"godkännd\", när semesterbegäran bekräftas av användaren.\n" +"Statusen \"Avvisad\", när semestern begäran avslås av chef.\n" +"Statusen \"Godkänd\", när semestern ansökan godkänns av chef." #. module: hr_holidays #: view:hr.holidays:0 @@ -417,10 +425,10 @@ msgstr "" "Funktionen bakom fältet 'Kvarvarande Semester' kan endast användas när det " "bara finns en ledighetstyp med alternativet 'Tillåt att överskrida gränsen' " "ej är markerad. (%s hittades). Annars är uppdateringen tvetydig eftersom vi " -"inte kan besluta om vilken ledighetstyp uppdateringen måste göras för.\n" -"Du kanske föredrar att använda de vanliga menyerna 'Ledighetsbegäran' och " +"inte kan besluta om vilken ledighetstyp uppdateringen måste göras för. \n" +"Du kanske föredrar att använda de klassiska menyer 'Ledighetsbegäran' och " "'Tilldela Ledighet' som ligger i 'Personal \\ Frånvaro' för att hantera " -"semesterdagar för de anställda, om konfigurationen inte tillåter att använda " +"semesterdagar för de anställda om konfigurationen inte tillåter att använda " "detta fält." #. module: hr_holidays @@ -436,7 +444,7 @@ msgstr "Väntar på godkännande" #. module: hr_holidays #: field:hr.holidays,category_id:0 msgid "Employee Tag" -msgstr "" +msgstr "Anställds etikett" #. module: hr_holidays #: field:hr.holidays.summary.employee,emp:0 @@ -460,6 +468,13 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Du kan tilldela återstående lagstadgad ledighetför varje " +"anställd, OpenERP\n" +" kommer automatiskt att skapa och validera " +"ledighetsförfrågningar.\n" +"

    \n" +" " #. module: hr_holidays #: help:hr.holidays.status,categ_id:0 @@ -472,7 +487,7 @@ msgstr "" #: code:addons/hr_holidays/wizard/hr_holidays_summary_department.py:44 #, python-format msgid "You have to select at least one Department. And try again." -msgstr "" +msgstr "Åtminstonde en avdelning måste vara vald, försök igen." #. module: hr_holidays #: field:hr.holidays,parent_id:0 @@ -492,7 +507,7 @@ msgstr "Månad" #. module: hr_holidays #: field:hr.holidays,message_unread:0 msgid "Unread Messages" -msgstr "" +msgstr "Olästa meddelanden" #. module: hr_holidays #: view:hr.holidays:0 @@ -524,7 +539,7 @@ msgstr "" #: view:hr.holidays.summary.dept:0 #: view:hr.holidays.summary.employee:0 msgid "or" -msgstr "" +msgstr "eller" #. module: hr_holidays #: model:ir.actions.act_window,help:hr_holidays.open_ask_holidays @@ -539,6 +554,16 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Klicka för att skapa en ny ledighetsbegäran.\n" +"

    \n" +" När du har spelat in din ledighetsförfrågan, skickas det\n" +" till en chef för validering. Se till att ställa rätt " +"frånvarotyp\n" +" typ (återhämtning, helgdagar, sjukdom) och den exakta\n" +" antal öppna dagar relaterade till din frånvaro.\n" +"

    \n" +" " #. module: hr_holidays #: view:hr.holidays:0 @@ -565,7 +590,7 @@ msgstr "" #. module: hr_holidays #: view:hr.holidays:0 msgid "Reset to New" -msgstr "" +msgstr "Återställ till ny" #. module: hr_holidays #: sql_constraint:hr.holidays:0 @@ -580,7 +605,7 @@ msgstr "Ljus Coral" #. module: hr_holidays #: field:hr.employee,leave_date_to:0 msgid "To Date" -msgstr "" +msgstr "Till datum" #. module: hr_holidays #: selection:hr.holidays.status,color_name:0 @@ -595,7 +620,7 @@ msgstr "Tilldela ledighet för personal" #. module: hr_holidays #: model:ir.ui.menu,name:hr_holidays.menu_open_view_holiday_status msgid "Leaves Types" -msgstr "" +msgstr "Frånvarotyp" #. module: hr_holidays #: field:hr.holidays,meeting_id:0 @@ -613,7 +638,7 @@ msgstr "" #: view:hr.holidays:0 #: field:hr.holidays,state:0 msgid "Status" -msgstr "" +msgstr "Status" #. module: hr_holidays #: selection:hr.holidays.status,color_name:0 @@ -638,7 +663,7 @@ msgstr "Ledigheten redan förbrukad" #. module: hr_holidays #: field:hr.holidays,message_is_follower:0 msgid "Is a Follower" -msgstr "" +msgstr "Är en följare" #. module: hr_holidays #: field:hr.holidays,user_id:0 @@ -661,7 +686,7 @@ msgstr "" #. module: hr_holidays #: view:hr.holidays:0 msgid "Add a reason..." -msgstr "" +msgstr "Lägg till orsak..." #. module: hr_holidays #: field:hr.holidays,manager_id:0 @@ -671,7 +696,7 @@ msgstr "Första godkännande" #. module: hr_holidays #: field:hr.holidays,message_summary:0 msgid "Summary" -msgstr "" +msgstr "Sammandrag" #. module: hr_holidays #: model:hr.holidays.status,name:hr_holidays.holiday_status_unpaid @@ -692,7 +717,7 @@ msgstr "Ledighetssummering" #. module: hr_holidays #: view:hr.holidays:0 msgid "Submit to Manager" -msgstr "" +msgstr "Skicka till chef" #. module: hr_holidays #: view:hr.employee:0 @@ -775,7 +800,7 @@ msgstr "" #: view:hr.holidays:0 #: selection:hr.holidays,type:0 msgid "Allocation Request" -msgstr "Ledighetstilldelning" +msgstr "Ledighetsönskemål" #. module: hr_holidays #: help:hr.holidays,holiday_type:0 @@ -799,7 +824,7 @@ msgstr "Applicera Dubbel validering" #: view:hr.employee:0 #: view:hr.holidays:0 msgid "days" -msgstr "" +msgstr "dagar" #. module: hr_holidays #: view:hr.holidays.summary.dept:0 @@ -827,7 +852,7 @@ msgstr "Avdelning(ar)" #. module: hr_holidays #: selection:hr.holidays,state:0 msgid "To Submit" -msgstr "" +msgstr "Att skicka" #. module: hr_holidays #: code:addons/hr_holidays/hr_holidays.py:354 @@ -853,7 +878,7 @@ msgstr "Återstående Semester" #. module: hr_holidays #: selection:hr.holidays,holiday_type:0 msgid "By Employee Tag" -msgstr "" +msgstr "Per anställdsetikett" #. module: hr_holidays #: selection:hr.employee,current_leave_state:0 @@ -865,7 +890,7 @@ msgstr "Nekad" #. module: hr_holidays #: field:hr.holidays.status,categ_id:0 msgid "Meeting Type" -msgstr "" +msgstr "Mötestyp" #. module: hr_holidays #: field:hr.holidays.remaining.leaves.user,no_of_leaves:0 @@ -875,7 +900,7 @@ msgstr "Återstående ledighet" #. module: hr_holidays #: view:hr.holidays:0 msgid "Allocated Days" -msgstr "" +msgstr "Dagar med frånvaro" #. module: hr_holidays #: view:hr.holidays:0 @@ -924,13 +949,13 @@ msgstr "Läge" #: selection:hr.holidays.summary.dept,holiday_type:0 #: selection:hr.holidays.summary.employee,holiday_type:0 msgid "Both Approved and Confirmed" -msgstr "" +msgstr "Både godkända och bekräftade" #. module: hr_holidays #: code:addons/hr_holidays/hr_holidays.py:451 #, python-format msgid "Request approved, waiting second validation." -msgstr "" +msgstr "Förfrågan godkänd, väntar sekundär validering." #. module: hr_holidays #: view:hr.holidays:0 @@ -940,7 +965,7 @@ msgstr "Godkänn" #. module: hr_holidays #: help:hr.holidays,message_ids:0 msgid "Messages and communication history" -msgstr "" +msgstr "Meddelande- och kommunikationshistorik" #. module: hr_holidays #: code:addons/hr_holidays/hr_holidays.py:260 @@ -948,7 +973,7 @@ msgstr "" #: sql_constraint:hr.holidays:0 #, python-format msgid "The start date must be anterior to the end date." -msgstr "" +msgstr "Startdatum måste föregå slutdatum." #. module: hr_holidays #: xsl:holidays.summary:0 @@ -967,7 +992,7 @@ msgstr "" #: model:ir.actions.act_window,name:hr_holidays.open_allocation_holidays #: model:ir.ui.menu,name:hr_holidays.menu_open_allocation_holidays msgid "Allocation Requests" -msgstr "Ledighetstilldening" +msgstr "Ledighetsönskemål" #. module: hr_holidays #: xsl:holidays.summary:0 @@ -981,6 +1006,9 @@ msgid "" "to create allocation/leave request. Total based on all the leave types " "without overriding limit." msgstr "" +"Totalt antal lagstadgad ledighet för den anställde, ändra detta värde för " +"att skapa frånvaro / ledighetsbegäran. Totalt baserat på alla frånvarotyper " +"utan tvingande gräns." #. module: hr_holidays #: selection:hr.holidays.status,color_name:0 @@ -990,7 +1018,7 @@ msgstr "Ljusrosa" #. module: hr_holidays #: xsl:holidays.summary:0 msgid "leaves." -msgstr "" +msgstr "Frånvaro" #. module: hr_holidays #: view:hr.holidays:0 @@ -1010,7 +1038,7 @@ msgstr "År" #. module: hr_holidays #: view:hr.holidays:0 msgid "Duration" -msgstr "" +msgstr "Varaktighet" #. module: hr_holidays #: view:hr.holidays:0 @@ -1022,7 +1050,7 @@ msgstr "Att godkänna" #. module: hr_holidays #: model:mail.message.subtype,description:hr_holidays.mt_holidays_approved msgid "Request approved" -msgstr "" +msgstr "Önskemål accepterat" #. module: hr_holidays #: field:hr.holidays,notes:0 @@ -1032,4 +1060,4 @@ msgstr "Anledningar" #. module: hr_holidays #: field:hr.holidays.summary.employee,holiday_type:0 msgid "Select Leave Type" -msgstr "" +msgstr "Välj frånvarotyp" diff --git a/addons/hr_payroll/i18n/sv.po b/addons/hr_payroll/i18n/sv.po index cc19058ecf4..2b10ef92876 100644 --- a/addons/hr_payroll/i18n/sv.po +++ b/addons/hr_payroll/i18n/sv.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-03-31 16:55+0000\n" +"PO-Revision-Date: 2014-04-03 07:50+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-01 06:52+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: hr_payroll #: field:hr.payslip.line,condition_select:0 @@ -102,7 +102,7 @@ msgstr "Överordnad" #: field:hr.salary.rule,company_id:0 #: field:hr.salary.rule.category,company_id:0 msgid "Company" -msgstr "Företag" +msgstr "Bolag" #. module: hr_payroll #: view:hr.payslip:0 @@ -234,7 +234,7 @@ msgstr "Övrig information" #. module: hr_payroll #: field:hr.config.settings,module_hr_payroll_account:0 msgid "Link your payroll to accounting system" -msgstr "" +msgstr "Länka lönesystemet till bokföringen" #. module: hr_payroll #: help:hr.payslip.line,amount_select:0 @@ -313,7 +313,7 @@ msgstr "Totalt Arbetsdagar" #. module: hr_payroll #: constraint:hr.payroll.structure:0 msgid "Error ! You cannot create a recursive Salary Structure." -msgstr "" +msgstr "Fel! Du kan inte skapa rekursiva ersättningsstrukturer." #. module: hr_payroll #: help:hr.payslip.line,code:0 @@ -354,6 +354,17 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Klicka för att lägga till ett nytt medarbetarregister.\n" +"

    \n" +" Ett medarbetarregister är en tredje part inblandad i " +"ersättningssystemet\n" +" för de anställda. Det kan vara Skattemyndighet, " +"Försäkringskassan, Arbetsförmedlingen, pensionsstöd, löntagarorganisation " +"eller vilken den organisation/kassa som tillför eller drar pengar på " +"lönebeskeden.\n" +"

    \n" +" " #. module: hr_payroll #: help:hr.payslip.line,condition_range_max:0 @@ -446,7 +457,7 @@ msgstr "%s (kopia)" #. module: hr_payroll #: help:hr.config.settings,module_hr_payroll_account:0 msgid "Create journal entries from payslips" -msgstr "" +msgstr "Skapa journalverifikat från lönebesked." #. module: hr_payroll #: field:hr.payslip,paid:0 @@ -456,7 +467,7 @@ msgstr "Tillverkade betalningsorder? " #. module: hr_payroll #: report:contribution.register.lines:0 msgid "PaySlip Lines by Contribution Register" -msgstr "Lönespecifikationsrader från Bidrags Register" +msgstr "Lönespecifikationsrader från medarbetarregistret" #. module: hr_payroll #: view:hr.payslip:0 @@ -494,7 +505,7 @@ msgstr "Återbetalning: " #. module: hr_payroll #: model:ir.model,name:hr_payroll.model_payslip_lines_contribution_register msgid "PaySlip Lines by Contribution Registers" -msgstr "Lönespecifikationsrader genom Bidrags Register" +msgstr "Lönespecifikationsrader via medarbetarregistret" #. module: hr_payroll #: view:hr.payslip:0 @@ -630,7 +641,7 @@ msgstr "Lönespecifikation Computation Detaljer" #: help:hr.payslip.line,appears_on_payslip:0 #: help:hr.salary.rule,appears_on_payslip:0 msgid "Used to display the salary rule on payslip." -msgstr "" +msgstr "Används för att visa löneregler på lönebeskedet." #. module: hr_payroll #: model:ir.model,name:hr_payroll.model_hr_payslip_input @@ -647,7 +658,7 @@ msgstr "Lön Rule Kategorier" #. module: hr_payroll #: view:hr.payslip:0 msgid "Cancel Payslip" -msgstr "" +msgstr "Avbryt lönebesked" #. module: hr_payroll #: help:hr.payslip.input,contract_id:0 @@ -664,7 +675,7 @@ msgstr "Beräkning" #: code:addons/hr_payroll/hr_payroll.py:899 #, python-format msgid "Wrong range condition defined for salary rule %s (%s)." -msgstr "" +msgstr "Fel omfångsvillkor definierat för löneregeln %s (%s)." #. module: hr_payroll #: help:hr.payslip.input,amount:0 @@ -694,7 +705,7 @@ msgstr "Kategori" #. module: hr_payroll #: view:hr.salary.rule:0 msgid "Company Contribution" -msgstr "" +msgstr "Bolagets bidrag" #. module: hr_payroll #: help:hr.payslip.run,credit_note:0 @@ -709,7 +720,7 @@ msgstr "" #: code:addons/hr_payroll/hr_payroll.py:876 #, python-format msgid "Wrong percentage base or quantity defined for salary rule %s (%s)." -msgstr "" +msgstr "Fel procentbas eller kvantitet definierad för löneregeln %s (%s)." #. module: hr_payroll #: model:ir.actions.act_window,name:hr_payroll.action_view_hr_payroll_structure_list_form @@ -767,7 +778,7 @@ msgstr "Procent (%)" #: code:addons/hr_payroll/hr_payroll.py:871 #, python-format msgid "Wrong quantity defined for salary rule %s (%s)." -msgstr "" +msgstr "Fel kvantitet definierad för löneregeln %s (%s)." #. module: hr_payroll #: view:hr.payslip:0 @@ -852,7 +863,7 @@ msgstr "Avtal" #: code:addons/hr_payroll/wizard/hr_payroll_payslips_by_employees.py:52 #, python-format msgid "You must select employee(s) to generate payslip(s)." -msgstr "" +msgstr "Du måste välja anställda för att skapa lönebesked" #. module: hr_payroll #: report:paylip.details:0 @@ -1026,7 +1037,7 @@ msgstr "hr.config.settings" #: field:hr.salary.rule,register_id:0 #: model:ir.model,name:hr_payroll.model_hr_contribution_register msgid "Contribution Register" -msgstr "Bidrags Register" +msgstr "Medarbetarregister" #. module: hr_payroll #: view:payslip.lines.contribution.register:0 @@ -1081,7 +1092,7 @@ msgstr "Totala grundlönen" #: model:ir.actions.act_window,name:hr_payroll.action_contribution_register_form #: model:ir.ui.menu,name:hr_payroll.menu_action_hr_contribution_register_form msgid "Contribution Registers" -msgstr "Bidrags Register" +msgstr "Medarbetarregister" #. module: hr_payroll #: model:ir.ui.menu,name:hr_payroll.menu_hr_payroll_reporting @@ -1093,13 +1104,14 @@ msgstr "Lön" #. module: hr_payroll #: model:ir.actions.report.xml,name:hr_payroll.contribution_register msgid "PaySlip Lines By Conribution Register" -msgstr "Lönespecifikationsrader från Bidragsregistret" +msgstr "Lönespecifikationsrader från medarbetarergistret" #. module: hr_payroll #: code:addons/hr_payroll/hr_payroll.py:370 #, python-format msgid "You cannot delete a payslip which is not draft or cancelled!" msgstr "" +"Du kan inte radera ett lönebesked som inte är i \"Utkast\" eller \"Avbruten\"" #. module: hr_payroll #: report:paylip.details:0 @@ -1171,6 +1183,10 @@ msgid "" "* If the payslip is confirmed then status is set to 'Done'. \n" "* When user cancel payslip the status is 'Rejected'." msgstr "" +"* När lönebesked skapas statusen är \"Utkast\".\n" +"* Om lönebesked är under kontroll, är statusen \"Väntar\".\n" +"* Om lönebesked bekräftas då status är inställd på \"Klar\".\n" +"* När användaren avbryter lönespecifikation statusen är \"Avvisad\"." #. module: hr_payroll #: help:hr.payslip.line,condition_range:0 @@ -1197,7 +1213,7 @@ msgstr "Lönespecifikation indata" #. module: hr_payroll #: view:hr.payslip:0 msgid "Other Inputs" -msgstr "" +msgstr "Övriga indata" #. module: hr_payroll #: model:ir.actions.act_window,name:hr_payroll.action_hr_salary_rule_category_tree_view @@ -1209,7 +1225,7 @@ msgstr "Lön Regel Kategorier Hierarki" #: code:addons/hr_payroll/hr_payroll.py:882 #, python-format msgid "Wrong python code defined for salary rule %s (%s)." -msgstr "" +msgstr "Fel i python-koden definierat för löneregeln %s (%s)." #. module: hr_payroll #: report:contribution.register.lines:0 @@ -1240,7 +1256,7 @@ msgstr "Den kod som kan användas i lön reglerna" #: code:addons/hr_payroll/hr_payroll.py:905 #, python-format msgid "Wrong python condition defined for salary rule %s (%s)." -msgstr "" +msgstr "Fel i python-villkoret definierat för löneregeln %s (%s)." #. module: hr_payroll #: view:hr.payslip.run:0 diff --git a/addons/mail/i18n/sv.po b/addons/mail/i18n/sv.po index a5add364ac0..71301cbf59f 100644 --- a/addons/mail/i18n/sv.po +++ b/addons/mail/i18n/sv.po @@ -9,14 +9,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-04-03 05:29+0000\n" +"PO-Revision-Date: 2014-04-03 10:13+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Svenska \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-03 06:02+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: mail #: view:mail.followers:0 @@ -368,6 +368,8 @@ msgid "" "Message type: email for email message, notification for system message, " "comment for other messages such as user replies" msgstr "" +"Meddelandetyp: e-post för e-postmeddelande, avisering för systemmeddelande, " +"kommentar är andra meddelanden som till exempel användarsvar" #. module: mail #: help:mail.message.subtype,relation_field:0 @@ -391,7 +393,7 @@ msgstr "Svar till" #: code:addons/mail/wizard/invite.py:37 #, python-format msgid "
    You have been invited to follow %s.
    " -msgstr "" +msgstr "
    Du har blivit inbjuden att följa %s.
    " #. module: mail #. openerp-web @@ -492,6 +494,8 @@ msgid "" "Holds the Chatter summary (number of messages, ...). This summary is " "directly in html format in order to be inserted in kanban views." msgstr "" +"Lagrar pladder-sammanfattning (antal meddelanden, ...). Denna sammanfattning " +"presenteras i html-format för att kunna sättas in i kanban vyer." #. module: mail #: help:mail.alias,alias_model_id:0 @@ -705,6 +709,9 @@ msgid "" "image, with aspect ratio preserved. Use this field anywhere a small image is " "required." msgstr "" +"Liten bild som representerar gruppen. Det är storleksändras automatiskt till " +"64x64px, men med bevarat bildförhållande. Använd det här fältet när helst en " +"liten bild krävs." #. module: mail #: view:mail.compose.message:0 @@ -745,7 +752,7 @@ msgstr "läs mer" #: code:addons/mail/wizard/invite.py:40 #, python-format msgid "
    You have been invited to follow a new document.
    " -msgstr "" +msgstr "
    Du har blivit inbjuden att följa ett nytt dokument.
    " #. module: mail #: field:mail.compose.message,parent_id:0 @@ -757,6 +764,7 @@ msgstr "Överliggande meddelande" #: selection:res.partner,notification_email_send:0 msgid "All Messages (discussions, emails, followed system notifications)" msgstr "" +"Alla meddelanden (diskussioner, e-post, prenumeration på systemaviseringar)" #. module: mail #. openerp-web @@ -826,12 +834,14 @@ msgid "" "You may not create a user. To create new users, you should use the " "\"Settings > Users\" menu." msgstr "" +"Du kan inte skapa en användare. För att skapa nya användare används " +"\"Inställningar > Användare\"-menyn" #. module: mail #: help:mail.followers,res_model:0 #: help:mail.wizard.invite,res_model:0 msgid "Model of the followed resource" -msgstr "" +msgstr "Modell för den prenumererade resursen" #. module: mail #. openerp-web @@ -870,7 +880,7 @@ msgstr "Kontakt" msgid "" "Only the invited followers can read the\n" " discussions on this group." -msgstr "" +msgstr "Endast inbjudna följare kan läsa denna grupps diskussioner" #. module: mail #: model:ir.model,name:mail.model_ir_ui_menu @@ -894,6 +904,7 @@ msgid "" "The following partners chosen as recipients for the email have no email " "address linked :" msgstr "" +"Följande företag är valda mottagare för e-post som saknar länkad adress:" #. module: mail #: help:mail.alias,alias_defaults:0 @@ -901,11 +912,13 @@ msgid "" "A Python dictionary that will be evaluated to provide default values when " "creating new records for this alias." msgstr "" +"Ett Python-dictionary som används för standardvärden när nya poster skapas " +"för detta alias." #. module: mail #: model:ir.model,name:mail.model_mail_message_subtype msgid "Message subtypes" -msgstr "" +msgstr "Undertyper till meddelande" #. module: mail #. openerp-web @@ -970,6 +983,8 @@ msgstr "Skicka nu" msgid "" "Unable to send email, please configure the sender's email address or alias." msgstr "" +"Kunde inte skicka e-post, vänligen konfigurera avsändarens e-postadress " +"eller alias." #. module: mail #: help:res.users,alias_id:0 @@ -987,7 +1002,7 @@ msgstr "Foto" #: help:mail.compose.message,vote_user_ids:0 #: help:mail.message,vote_user_ids:0 msgid "Users that voted for this message" -msgstr "" +msgstr "Användare som röstat på detta meddelande" #. module: mail #: help:mail.group,alias_id:0 @@ -1077,6 +1092,7 @@ msgstr "Gruppera" #: help:mail.message,starred:0 msgid "Current user has a starred notification linked to this message" msgstr "" +"Aktuell användare har en blockerad avisering länkad till detta meddelande" #. module: mail #: field:mail.group,public:0 @@ -1229,7 +1245,7 @@ msgstr "Ta emot meddelanden per e-post" #. module: mail #: model:mail.group,name:mail.group_best_sales_practices msgid "Best Sales Practices" -msgstr "" +msgstr "Marknadsföringspraxis" #. module: mail #: selection:mail.group,public:0 @@ -1442,7 +1458,7 @@ msgstr "Kopia" #. module: mail #: help:mail.notification,starred:0 msgid "Starred message that goes into the todo mailbox" -msgstr "" +msgstr "Blockerade meddelanden som sorteras in i att-göra-boxen" #. module: mail #: view:mail.group:0 @@ -1517,11 +1533,12 @@ msgstr "Registreringsmånad" msgid "" "Partners that have a notification pushing this message in their mailboxes" msgstr "" +"Företag som har en aviseringsknuff av detta meddelande till sina e-postlådor" #. module: mail #: view:mail.message:0 msgid "Show already read messages" -msgstr "" +msgstr "Visa lästa meddelanden" #. module: mail #: view:mail.message:0 @@ -1560,6 +1577,8 @@ msgid "" "This group is visible by non members. Invisible groups can add " "members through the invite button." msgstr "" +"Denna grupp är synlig för icke medlemmar. Osynliga grupper kan lägga till " +"medlemmar via den \"osynliga\" knappen." #. module: mail #: model:mail.group,name:mail.group_board @@ -1569,7 +1588,7 @@ msgstr "Styrelsemöten" #. module: mail #: field:mail.alias,alias_model_id:0 msgid "Aliased Model" -msgstr "" +msgstr "Aliasobjekt" #. module: mail #: help:mail.compose.message,message_id:0 @@ -1609,7 +1628,7 @@ msgstr "Utgående e-postserver" #: code:addons/mail/mail_message.py:930 #, python-format msgid "Partners email addresses not found" -msgstr "" +msgstr "Företagets e-postadress saknas" #. module: mail #: view:mail.mail:0 @@ -1620,7 +1639,7 @@ msgstr "Skickat" #. module: mail #: field:mail.mail,body_html:0 msgid "Rich-text Contents" -msgstr "" +msgstr "Utsmyckat innehåll" #. module: mail #: help:mail.compose.message,to_read:0 @@ -1667,6 +1686,9 @@ msgid "" "installed\n" " the portal module." msgstr "" +"Denna grupp är synlig för alla,\n" +" även dina kunder i de fall du " +"installerat portalmodulen." #. module: mail #. openerp-web @@ -1680,7 +1702,7 @@ msgstr "Backa till Att göra" #: code:addons/mail/static/src/xml/mail.xml:154 #, python-format msgid "Attach a note that will not be sent to the followers" -msgstr "" +msgstr "Bilägg en notering som inte kommer skickas till prenumeranterna" #. module: mail #. openerp-web @@ -1839,7 +1861,7 @@ msgstr "Alias domän" #: code:addons/mail/update.py:93 #, python-format msgid "Error during communication with the publisher warranty server." -msgstr "" +msgstr "Fel vid kommunikation med servern för 'utgivarens underhållsavtal'." #. module: mail #: selection:mail.group,public:0 @@ -1888,7 +1910,7 @@ msgstr "Inledande meddelande i tråd." #. module: mail #: model:mail.group,name:mail.group_hr_policies msgid "HR Policies" -msgstr "" +msgstr "Personalpolicies" #. module: mail #. openerp-web @@ -1935,6 +1957,3 @@ msgstr "Litet fotografi" #: help:mail.mail,reply_to:0 msgid "Preferred response address for the message" msgstr "Föredragen svarsadress för meddelandet" - -#~ msgid "Invitation to follow %s" -#~ msgstr "Invitation to follow %s" diff --git a/addons/sale/i18n/sv.po b/addons/sale/i18n/sv.po index 8863ff16091..1848dec5270 100644 --- a/addons/sale/i18n/sv.po +++ b/addons/sale/i18n/sv.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:36+0000\n" -"PO-Revision-Date: 2014-04-03 05:30+0000\n" +"PO-Revision-Date: 2014-04-03 10:44+0000\n" "Last-Translator: Anders Wallenquist \n" "Language-Team: Swedish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-04-03 06:02+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: sale #: model:ir.model,name:sale.model_account_config_settings @@ -65,7 +65,7 @@ msgstr "Felaktiga data" #: code:addons/sale/wizard/sale_make_invoice_advance.py:102 #, python-format msgid "The value of Advance Amount must be positive." -msgstr "" +msgstr "Värdet på förskotterat belopp måste vara positivt." #. module: sale #: help:sale.config.settings,group_discount_per_so_line:0 @@ -97,6 +97,10 @@ msgid "" "The 'Waiting Schedule' status is set when the invoice is confirmed " " but waiting for the scheduler to run on the order date." msgstr "" +"Ger status för offert eller kundorder. Status Undantag ställs in automatiskt " +"när faktura- (Faktura i undantag) eller plockningsprocessen (Levarans i " +"undantag). Status 'Planerad väntan' \"ställs in när fakturan är bekräftad, " +"men väntar på planeringsscheduleringskörningen på orderdagen." #. module: sale #: view:sale.report:0 @@ -291,7 +295,7 @@ msgstr "Namn på försäljningsställe" #: code:addons/sale/sale.py:598 #, python-format msgid "You cannot confirm a sales order which has no line." -msgstr "" +msgstr "Du kan inte bekräfta en kundorder som saknar rader." #. module: sale #: model:ir.actions.act_window,help:sale.action_order_line_tree2 @@ -307,6 +311,15 @@ msgid "" "

    \n" " " msgstr "" +"

    \n" +" Här är en lista på varje fakturerbar kundorderrad. Du kan\n" +" göra partiella faktureringar via kundorderrader. Denna " +"listan är onödig \n" +" i de fall du valt att fakturera med leveransorder som " +"underlag eller du alltid\n" +" fakturerar kundordern i sin helhet.\n" +" \n" +" " #. module: sale #: view:sale.order:0 @@ -724,6 +737,14 @@ msgid "" " \n" "* The 'Cancelled' status is set when a user cancel the sales order related." msgstr "" +"* Status \"Utkast\" ställs in när den relaterade kundorder i utkast status.\n" +"* Status \"Bekräftat\" ställs in när den relaterade " +"försäljningsorderläggningen .\n" +"* Status \"Undantag\" ställs in när den relaterade kundorder in som " +"undantag.\n" +"* Status \"Klar\" ställs in när försäljningsorderraden har plockats.\n" +"* Status \"Inställd\" ställs in när en användare avbryter kundorder " +"relaterade." #. module: sale #: code:addons/sale/wizard/sale_make_invoice_advance.py:92 @@ -1565,6 +1586,91 @@ msgid "" "

    4)ka%z2nB`4@E05c>NJYR&8IrSn3iF~s`gsrGcD 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

    \n" " " msgstr "" +"\n" +"
    \n" +"\n" +"

    Hej ${object.partner_id.name},

    \n" +" \n" +"

    Här kommer din ${object.state in ('draft', 'sent') and 'offert' or " +"'orderbekräftelse'} från ${object.company_id.name}:

    \n" +"\n" +"

    \n" +"   UPPGIFTER
    \n" +"   Ordernummer: ${object.name}
    \n" +"   Ordertotal: ${object.amount_total} " +"${object.pricelist_id.currency_id.name}
    \n" +"   Orderdatum: ${object.date_order}
    \n" +" % if object.origin:\n" +"   Orderreferens: ${object.origin}
    \n" +" % endif\n" +" % if object.client_order_ref:\n" +"   Er referens: ${object.client_order_ref}
    \n" +" % endif\n" +" % if object.user_id:\n" +"   Din kontaktperson:
    ${object.user_id.name}\n" +" % endif\n" +"

    \n" +"\n" +" % if object.paypal_url:\n" +"
    \n" +"

    Det är även möjligt att betala direkt via Paypal:

    \n" +" \n" +" \n" +" \n" +" % endif\n" +"\n" +"
    \n" +"

    Vid eventuella frågot, tveka inte att kontakta oss.

    \n" +"

    Tack för att ni väljer ${object.company_id.name or 'oss'}!

    \n" +"
    \n" +"
    \n" +"
    \n" +"

    \n" +" ${object.company_id.name}

    \n" +"
    \n" +"
    \n" +" \n" +" % if object.company_id.street:\n" +" ${object.company_id.street}
    \n" +" % endif\n" +" % if object.company_id.street2:\n" +" ${object.company_id.street2}
    \n" +" % endif\n" +" % if object.company_id.city or object.company_id.zip:\n" +" ${object.company_id.zip} ${object.company_id.city}
    \n" +" % endif\n" +" % if object.company_id.country_id:\n" +" ${object.company_id.state_id and ('%s, ' % " +"object.company_id.state_id.name) or ''} ${object.company_id.country_id.name " +"or ''}
    \n" +" % endif\n" +"
    \n" +" % if object.company_id.phone:\n" +"
    \n" +" Phone:  ${object.company_id.phone}\n" +"
    \n" +" % endif\n" +" % if object.company_id.website:\n" +"
    \n" +" Web : ${object.company_id.website}\n" +"
    \n" +" %endif\n" +"

    \n" +"
    \n" +"
    \n" +" " #. module: sale #: view:sale.order.line:0 @@ -2282,11 +2388,3 @@ msgstr "Plockad" #: field:sale.report,year:0 msgid "Year" msgstr "År" - -#~ msgid "" -#~ "In order to delete a confirmed sales order, you must cancel it before!" -#~ msgstr "" -#~ "In order to delete a confirmed sales order, you must cancel it before!" - -#~ msgid "No Customer Defined!" -#~ msgstr "Kund saknas!" diff --git a/addons/stock/i18n/zh_TW.po b/addons/stock/i18n/zh_TW.po index a4cdb73814d..51050def38b 100644 --- a/addons/stock/i18n/zh_TW.po +++ b/addons/stock/i18n/zh_TW.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2014-02-06 15:56+0000\n" -"PO-Revision-Date: 2014-03-30 12:01+0000\n" +"PO-Revision-Date: 2014-04-03 11:14+0000\n" "Last-Translator: Andy Cheng \n" "Language-Team: Chinese (Traditional) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-31 06:40+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: stock #: field:stock.inventory.line.split,line_exist_ids:0 @@ -4360,7 +4360,7 @@ msgstr "入庫產品" #. module: stock #: view:product.product:0 msgid "update" -msgstr "" +msgstr "更新" #. module: stock #: view:stock.change.product.qty:0 @@ -4379,7 +4379,7 @@ msgstr "" #: view:stock.return.picking:0 #: view:stock.split.into:0 msgid "or" -msgstr "" +msgstr "或" #. module: stock #: selection:stock.picking,invoice_state:0 @@ -4399,7 +4399,7 @@ msgstr "資訊" #: code:addons/stock/stock.py:1213 #, python-format msgid "You cannot remove the picking which is in %s state!" -msgstr "" +msgstr "您不能移除 %s 狀態的提貨單" #. module: stock #: help:res.partner,property_stock_customer:0 diff --git a/openerp/addons/base/i18n/ab.po b/openerp/addons/base/i18n/ab.po index f3ab57c8078..ba58f36d5d1 100644 --- a/openerp/addons/base/i18n/ab.po +++ b/openerp/addons/base/i18n/ab.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:09+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:47+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/af.po b/openerp/addons/base/i18n/af.po index bfa9c43edd6..3014e1b0fe4 100644 --- a/openerp/addons/base/i18n/af.po +++ b/openerp/addons/base/i18n/af.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-11 06:26+0000\n" -"X-Generator: Launchpad (build 16890)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:47+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/am.po b/openerp/addons/base/i18n/am.po index e4bbf993586..347a0aee8a0 100644 --- a/openerp/addons/base/i18n/am.po +++ b/openerp/addons/base/i18n/am.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-19 05:58+0000\n" -"X-Generator: Launchpad (build 16901)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:48+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ar.po b/openerp/addons/base/i18n/ar.po index efa03372573..8959e8d5167 100644 --- a/openerp/addons/base/i18n/ar.po +++ b/openerp/addons/base/i18n/ar.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:09+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:48+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/bg.po b/openerp/addons/base/i18n/bg.po index abcfa36dce1..4c2bfb23d55 100644 --- a/openerp/addons/base/i18n/bg.po +++ b/openerp/addons/base/i18n/bg.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:10+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:49+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/bn.po b/openerp/addons/base/i18n/bn.po index 8048ec219a1..b32a1099d08 100644 --- a/openerp/addons/base/i18n/bn.po +++ b/openerp/addons/base/i18n/bn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-16 06:03+0000\n" -"X-Generator: Launchpad (build 16901)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:49+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/bs.po b/openerp/addons/base/i18n/bs.po index 0223635ee89..03fc2baf6af 100644 --- a/openerp/addons/base/i18n/bs.po +++ b/openerp/addons/base/i18n/bs.po @@ -9,13 +9,13 @@ msgstr "" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:35+0000\n" "PO-Revision-Date: 2013-10-25 21:35+0000\n" -"Last-Translator: Bosko Stojakovic \n" +"Last-Translator: Boško Stojaković \n" "Language-Team: Bosnian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-26 06:24+0000\n" -"X-Generator: Launchpad (build 16810)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:49+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ca.po b/openerp/addons/base/i18n/ca.po index b083939b88d..08aa7ff7c1b 100644 --- a/openerp/addons/base/i18n/ca.po +++ b/openerp/addons/base/i18n/ca.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:10+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:50+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/cs.po b/openerp/addons/base/i18n/cs.po index 1de34103c72..ee177307785 100644 --- a/openerp/addons/base/i18n/cs.po +++ b/openerp/addons/base/i18n/cs.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-08 06:53+0000\n" -"X-Generator: Launchpad (build 16948)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:50+0000\n" +"X-Generator: Launchpad (build 16976)\n" "X-Language: cs_CZ\n" "X-Source-Language: en\n" diff --git a/openerp/addons/base/i18n/da.po b/openerp/addons/base/i18n/da.po index a6b9257fe30..c53ed207f77 100644 --- a/openerp/addons/base/i18n/da.po +++ b/openerp/addons/base/i18n/da.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:10+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:50+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/de.po b/openerp/addons/base/i18n/de.po index 0f1d9fb1448..75509253e98 100644 --- a/openerp/addons/base/i18n/de.po +++ b/openerp/addons/base/i18n/de.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-03 05:55+0000\n" -"X-Generator: Launchpad (build 16916)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:52+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/el.po b/openerp/addons/base/i18n/el.po index 1d0d44913dc..7f21ca27f04 100644 --- a/openerp/addons/base/i18n/el.po +++ b/openerp/addons/base/i18n/el.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:11+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/en_GB.po b/openerp/addons/base/i18n/en_GB.po index a484df07700..9a542d5b49c 100644 --- a/openerp/addons/base/i18n/en_GB.po +++ b/openerp/addons/base/i18n/en_GB.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-31 05:47+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:03+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es.po b/openerp/addons/base/i18n/es.po index 41190b960e1..c30d913bc6e 100644 --- a/openerp/addons/base/i18n/es.po +++ b/openerp/addons/base/i18n/es.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-04 06:18+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: help:ir.actions.act_window,res_id:0 diff --git a/openerp/addons/base/i18n/es_AR.po b/openerp/addons/base/i18n/es_AR.po index b7b436aa1ea..c2481140984 100644 --- a/openerp/addons/base/i18n/es_AR.po +++ b/openerp/addons/base/i18n/es_AR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:16+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:02+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_BO.po b/openerp/addons/base/i18n/es_BO.po index da9875971d6..6fed8dd8daa 100644 --- a/openerp/addons/base/i18n/es_BO.po +++ b/openerp/addons/base/i18n/es_BO.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:17+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:04+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_CL.po b/openerp/addons/base/i18n/es_CL.po index 7fa6da27fe9..57aa90de6cb 100644 --- a/openerp/addons/base/i18n/es_CL.po +++ b/openerp/addons/base/i18n/es_CL.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:16+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:03+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_CR.po b/openerp/addons/base/i18n/es_CR.po index 49e7ed3757b..34cca753860 100644 --- a/openerp/addons/base/i18n/es_CR.po +++ b/openerp/addons/base/i18n/es_CR.po @@ -15,8 +15,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:17+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:05+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_DO.po b/openerp/addons/base/i18n/es_DO.po index e8410f4474a..7e9abea2dd9 100644 --- a/openerp/addons/base/i18n/es_DO.po +++ b/openerp/addons/base/i18n/es_DO.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:16+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:03+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_EC.po b/openerp/addons/base/i18n/es_EC.po index 635a2937665..f22b8fe915b 100644 --- a/openerp/addons/base/i18n/es_EC.po +++ b/openerp/addons/base/i18n/es_EC.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:17+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:06+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_MX.po b/openerp/addons/base/i18n/es_MX.po index 993a6924a3f..eee4e3ed746 100644 --- a/openerp/addons/base/i18n/es_MX.po +++ b/openerp/addons/base/i18n/es_MX.po @@ -9,14 +9,13 @@ msgstr "" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:35+0000\n" "PO-Revision-Date: 2013-07-26 23:36+0000\n" -"Last-Translator: Federico Manuel Echeverri Choux - ( Vauxoo ) " -"\n" +"Last-Translator: Federico Manuel Echeverri Choux \n" "Language-Team: Spanish (Mexico) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:17+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:06+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_PE.po b/openerp/addons/base/i18n/es_PE.po index 8bb9e5a91c3..fba0940742c 100644 --- a/openerp/addons/base/i18n/es_PE.po +++ b/openerp/addons/base/i18n/es_PE.po @@ -9,13 +9,13 @@ msgstr "" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:35+0000\n" "PO-Revision-Date: 2013-12-09 16:08+0000\n" -"Last-Translator: Pepe B. @TelFast Peru Partner \n" +"Last-Translator: Pepe B. @TelFast Perú \n" "Language-Team: Spanish (Peru) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-11 06:27+0000\n" -"X-Generator: Launchpad (build 16869)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:06+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/es_VE.po b/openerp/addons/base/i18n/es_VE.po index 9ae70ae9c12..e697ac64074 100644 --- a/openerp/addons/base/i18n/es_VE.po +++ b/openerp/addons/base/i18n/es_VE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:16+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:02+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/et.po b/openerp/addons/base/i18n/et.po index 4f88f067db2..41c768d2648 100644 --- a/openerp/addons/base/i18n/et.po +++ b/openerp/addons/base/i18n/et.po @@ -9,13 +9,13 @@ msgstr "" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:35+0000\n" "PO-Revision-Date: 2013-10-08 18:24+0000\n" -"Last-Translator: Rait Helmrosin \n" +"Last-Translator: Rait \n" "Language-Team: Estonian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-09 05:48+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/eu.po b/openerp/addons/base/i18n/eu.po index a5423fbb437..ab8ae66fc47 100644 --- a/openerp/addons/base/i18n/eu.po +++ b/openerp/addons/base/i18n/eu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:10+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:49+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fa.po b/openerp/addons/base/i18n/fa.po index fdbebaa55a8..1490a2fd95f 100644 --- a/openerp/addons/base/i18n/fa.po +++ b/openerp/addons/base/i18n/fa.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:13+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fa_AF.po b/openerp/addons/base/i18n/fa_AF.po index 2a3d77a8b18..d3ce5fcfed8 100644 --- a/openerp/addons/base/i18n/fa_AF.po +++ b/openerp/addons/base/i18n/fa_AF.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:18+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fi.po b/openerp/addons/base/i18n/fi.po index 9cd36c2b7b3..06913c1c5a1 100644 --- a/openerp/addons/base/i18n/fi.po +++ b/openerp/addons/base/i18n/fi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-01 05:51+0000\n" -"X-Generator: Launchpad (build 16948)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fr.po b/openerp/addons/base/i18n/fr.po index 06bcdcfc70b..b83844eb5f6 100644 --- a/openerp/addons/base/i18n/fr.po +++ b/openerp/addons/base/i18n/fr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-27 08:12+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:52+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/fr_CA.po b/openerp/addons/base/i18n/fr_CA.po index 49a5fc8820b..0cac409f7a1 100644 --- a/openerp/addons/base/i18n/fr_CA.po +++ b/openerp/addons/base/i18n/fr_CA.po @@ -9,13 +9,13 @@ msgstr "" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:35+0000\n" "PO-Revision-Date: 2014-03-19 20:37+0000\n" -"Last-Translator: Philippe Latouche - Savoir-faire Linux \n" +"Last-Translator: Philippe Latouche \n" "Language-Team: French (Canada) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-20 06:19+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:04+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/gl.po b/openerp/addons/base/i18n/gl.po index 3ca2bf41ca0..6242959f6d7 100644 --- a/openerp/addons/base/i18n/gl.po +++ b/openerp/addons/base/i18n/gl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-16 06:24+0000\n" -"X-Generator: Launchpad (build 16831)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/gu.po b/openerp/addons/base/i18n/gu.po index d000b1ba293..9319ff98c2a 100644 --- a/openerp/addons/base/i18n/gu.po +++ b/openerp/addons/base/i18n/gu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:11+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/he.po b/openerp/addons/base/i18n/he.po index eb302e64b53..1e045cbe540 100644 --- a/openerp/addons/base/i18n/he.po +++ b/openerp/addons/base/i18n/he.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-02 05:45+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" "Language: he\n" #. module: base diff --git a/openerp/addons/base/i18n/hi.po b/openerp/addons/base/i18n/hi.po index ed7a065d9e2..c025913d659 100644 --- a/openerp/addons/base/i18n/hi.po +++ b/openerp/addons/base/i18n/hi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:12+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:53+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/hr.po b/openerp/addons/base/i18n/hr.po index aeda7907a8f..2491143651b 100644 --- a/openerp/addons/base/i18n/hr.po +++ b/openerp/addons/base/i18n/hr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-17 05:44+0000\n" -"X-Generator: Launchpad (build 16831)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/hu.po b/openerp/addons/base/i18n/hu.po index b26b1fc044a..b87bd83d522 100644 --- a/openerp/addons/base/i18n/hu.po +++ b/openerp/addons/base/i18n/hu.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:12+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing @@ -6329,18 +6329,18 @@ msgid "" msgstr "" "\n" "Ez a modul hozzáad állapotot, start_dátumot, stop_dátumot a gyártási " -"megrendelés végrehalytási soraihoz (a 'Gyártási megrendelések' fülön).\n" +"megrendelés végrehajtási soraihoz (a 'Gyártási megrendelések' fülön).\n" "=============================================================================" "===================================\n" "\n" -"Állapot: terv, leigazolt, elvégzett, érévnytelenített\n" -"Ha elvégzett/visszaigazolt, érévnytelenített a gyártási rendelés akkor " +"Állapot: terv, leigazolt, elvégzett, érvénytelenített\n" +"Ha elvégzett/visszaigazolt, érvénytelenített a gyártási rendelés akkor " "megfelelő állapot sorokat\n" "be kell állítani az állapothoz.\n" "\n" "Menük létrehozás:\n" "-------------\n" -" **Gyátás** > **Gyártás** > **Gyártási megrendelések**\n" +" **Gyártás** > **Gyártás** > **Gyártási megrendelések**\n" "\n" "Megtalálható a 'Gyártási megrendelések' soraiban a gyártási " "megrendeléseknél.\n" @@ -6351,8 +6351,8 @@ msgstr "" " * start (állítsa be a visszaigazolt állapotot), állítsa be az " "indulási_dátumot\n" " * stop (állítsa be az elvégzett állapotot), állítsa be a stop_dátumot\n" -" * Tervezettr állít (állítsa be a tervezett állapotot)\n" -" * érévnytelenít (állítsa be az érvénytelenít állapotot)\n" +" * Tervezetet állít (állítsa be a tervezett állapotot)\n" +" * érvénytelenít (állítsa be az érvénytelenít állapotot)\n" "\n" "Ha egy gyártási rendelés 'elvégezhetővé' válik, akkor 'visszaigazoltnak' " "kell lennie.\n" @@ -6397,7 +6397,7 @@ msgstr "Kenya" #: model:ir.actions.act_window,name:base.action_translation #: model:ir.ui.menu,name:base.menu_action_translation msgid "Translated Terms" -msgstr "Lefordított feltételek" +msgstr "Lefordított kifejezések" #. module: base #: selection:base.language.install,lang:0 @@ -9358,7 +9358,7 @@ msgid "" msgstr "" "\n" "Hosszú távú projekt szervezés modul mely nyomon követi a tervezést, " -"ütemtervet, erőforrás kiosztás.\n" +"ütemtervet, erőforrás kiosztást.\n" "=============================================================================" "==============\n" "\n" @@ -9372,7 +9372,7 @@ msgstr "" " feladat megadva akkor az összesre terv, nyitott és folyamatban állapot " "lesz választva.\n" " * Ügy ütemterv számítás: Ez ugyanúgy működik mint az ütemezés gomb a \n" -" project.phase project.fázis-on. Ez alapul veszi a projectet és " +" projekt.projekt fázis.fázis-on. Ez alapul veszi a projektet és " "kiszámítja az összes nyitott,\n" " tervet és elintézetlen ügyeket.\n" " * Ütemezett ügyek: Minden ügy, mely terv, elintézetlen és nyitott " @@ -11437,7 +11437,7 @@ msgstr "" "\n" "Beállítás:\n" "--------------\n" -"A madul telepítése után konfigurálni kell az LDAP paramétereket a vállalat " +"A modul telepítése után konfigurálni kell az LDAP paramétereket a vállalat " "részletei\n" "beállítás fülön. Különböző vállalatoknak különböző LDAP szerverei vannak,\n" "amíg egyedi felhasználó nevei vannak (a felhasználó neveknek az OpenERP-ben\n" @@ -11533,7 +11533,7 @@ msgstr "Réunion (Francia)" msgid "" "New column name must still start with x_ , because it is a custom field!" msgstr "" -"Az új oszlopnévnek még mindig x_-sal kell kezdődnie, mert ez egy egyéni mező!" +"Az új oszlopnévnek még mindig x_-al kell kezdődnie, mert ez egy egyéni mező!" #. module: base #: model:ir.module.module,shortdesc:base.module_mrp_repair @@ -12429,8 +12429,8 @@ msgid "" " " msgstr "" "\n" -"Ez a modul kiegészíti a Raktárház alkalmazást, hatásosan beágyazva a Belökés " -"& Kihúzás raktár folyamatokat.\n" +"Ez a modul kiegészíti a Raktárépület alkalmazást, hatásosan beágyazva a " +"Belökés & Kihúzás raktár folyamatokat.\n" "=============================================================================" "===============================\n" "\n" @@ -12844,7 +12844,7 @@ msgstr "This method does not exist anymore" #: model:ir.actions.act_window,name:base.action_wizard_update_translations #: model:ir.ui.menu,name:base.menu_wizard_update_translations msgid "Synchronize Terms" -msgstr "Feltételek szinkronizáása" +msgstr "Kifejezések szinkronizáása" #. module: base #: field:res.lang,thousands_sep:0 @@ -14008,7 +14008,7 @@ msgstr "Érvénytelen adatbázis azonosító '%s' ehhez a mezőhöz '%%(field)s' #. module: base #: view:res.lang:0 msgid "Update Languague Terms" -msgstr "Nyelvi feltételek frissítése" +msgstr "Nyelvi kifejezések frissítése" #. module: base #: field:workflow.activity,join_mode:0 @@ -14099,7 +14099,7 @@ msgstr "Normál" #. module: base #: model:ir.module.module,shortdesc:base.module_purchase_double_validation msgid "Double Validation on Purchases" -msgstr "A vásárlásokra kétszeres jóváhagyás" +msgstr "Kkétszeres jóváhagyás a beszerzésekre" #. module: base #: field:res.bank,street2:0 @@ -18559,8 +18559,8 @@ msgstr "" "Az Elválasztó formátumnak olyannak kell lennie [,n] ahol 0 < n :egység " "számjegytől indul. A -1 fogja jelezni az elválasztás végét. Pl. a [3,2,-1] " "fogja jelölni a 106500-nál, hogy 1,06,500 lehessen; az [1,2,-1] fogja " -"lehetővé tenni, hogy a szám 106,50,0 legyen. Ebben az esetben mindig a ',' " -"az ezres elválasztó." +"lehetővé tenni, hogy a szám 106,50,0 legyen;[3] fogja jelölni mint 106,500. " +"Ebben az esetben mindig a ',' az ezres elválasztó." #. module: base #: field:ir.module.module,auto_install:0 diff --git a/openerp/addons/base/i18n/hy.po b/openerp/addons/base/i18n/hy.po index a96eabcf7a7..fdc7f61cdcb 100644 --- a/openerp/addons/base/i18n/hy.po +++ b/openerp/addons/base/i18n/hy.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:09+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:48+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/id.po b/openerp/addons/base/i18n/id.po index 7d8cc6a4f14..e906a03f03f 100644 --- a/openerp/addons/base/i18n/id.po +++ b/openerp/addons/base/i18n/id.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-11 06:08+0000\n" -"X-Generator: Launchpad (build 16948)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/is.po b/openerp/addons/base/i18n/is.po index 824538b219d..b466386bf6d 100644 --- a/openerp/addons/base/i18n/is.po +++ b/openerp/addons/base/i18n/is.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:12+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/it.po b/openerp/addons/base/i18n/it.po index 47f95f75c39..090b0c6c16a 100644 --- a/openerp/addons/base/i18n/it.po +++ b/openerp/addons/base/i18n/it.po @@ -9,13 +9,13 @@ msgstr "" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2013-06-07 19:35+0000\n" "PO-Revision-Date: 2013-01-19 09:34+0000\n" -"Last-Translator: Davide Corio \n" +"Last-Translator: Davide Corio @ LS \n" "Language-Team: Italian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:12+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:54+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ja.po b/openerp/addons/base/i18n/ja.po index 288297863a1..624110f0d5e 100644 --- a/openerp/addons/base/i18n/ja.po +++ b/openerp/addons/base/i18n/ja.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-07 07:22+0000\n" -"X-Generator: Launchpad (build 16948)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:55+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ka.po b/openerp/addons/base/i18n/ka.po index 4c83165c302..12f724f8fc2 100644 --- a/openerp/addons/base/i18n/ka.po +++ b/openerp/addons/base/i18n/ka.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:11+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:52+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/kk.po b/openerp/addons/base/i18n/kk.po index c615c2fca92..f893af8ac41 100644 --- a/openerp/addons/base/i18n/kk.po +++ b/openerp/addons/base/i18n/kk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:12+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:55+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ko.po b/openerp/addons/base/i18n/ko.po index dd7f1b00510..6b6b7957605 100644 --- a/openerp/addons/base/i18n/ko.po +++ b/openerp/addons/base/i18n/ko.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:13+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:55+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/lt.po b/openerp/addons/base/i18n/lt.po index 07ee4ad23a7..7069722d47d 100644 --- a/openerp/addons/base/i18n/lt.po +++ b/openerp/addons/base/i18n/lt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:13+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/lv.po b/openerp/addons/base/i18n/lv.po index 396435687cb..65ecd2e72be 100644 --- a/openerp/addons/base/i18n/lv.po +++ b/openerp/addons/base/i18n/lv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-08 05:45+0000\n" -"X-Generator: Launchpad (build 16869)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/mk.po b/openerp/addons/base/i18n/mk.po index dafa062e849..31d0c02d729 100644 --- a/openerp/addons/base/i18n/mk.po +++ b/openerp/addons/base/i18n/mk.po @@ -16,8 +16,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:13+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" "Language: mk\n" #. module: base diff --git a/openerp/addons/base/i18n/mn.po b/openerp/addons/base/i18n/mn.po index 2e114731dc8..4a1b14f5d5d 100644 --- a/openerp/addons/base/i18n/mn.po +++ b/openerp/addons/base/i18n/mn.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-09 06:50+0000\n" -"X-Generator: Launchpad (build 16916)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:56+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/nb.po b/openerp/addons/base/i18n/nb.po index 1c6cd39af30..fe0ceb8fb9c 100644 --- a/openerp/addons/base/i18n/nb.po +++ b/openerp/addons/base/i18n/nb.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:13+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/nl.po b/openerp/addons/base/i18n/nl.po index b3e5afffd5c..a68358a9799 100644 --- a/openerp/addons/base/i18n/nl.po +++ b/openerp/addons/base/i18n/nl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-14 06:58+0000\n" -"X-Generator: Launchpad (build 16963)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:51+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/nl_BE.po b/openerp/addons/base/i18n/nl_BE.po index 6dc8f15506f..bd154c4e340 100644 --- a/openerp/addons/base/i18n/nl_BE.po +++ b/openerp/addons/base/i18n/nl_BE.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:17+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:04+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/pl.po b/openerp/addons/base/i18n/pl.po index eeca9b28a53..28d26b4bac4 100644 --- a/openerp/addons/base/i18n/pl.po +++ b/openerp/addons/base/i18n/pl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-17 05:44+0000\n" -"X-Generator: Launchpad (build 16831)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/pt.po b/openerp/addons/base/i18n/pt.po index 76afbde170b..7f1f2e9764f 100644 --- a/openerp/addons/base/i18n/pt.po +++ b/openerp/addons/base/i18n/pt.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-03-21 06:51+0000\n" -"X-Generator: Launchpad (build 16967)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:57+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/pt_BR.po b/openerp/addons/base/i18n/pt_BR.po index 9649e050f0a..277788aeb64 100644 --- a/openerp/addons/base/i18n/pt_BR.po +++ b/openerp/addons/base/i18n/pt_BR.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:16+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:02+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ro.po b/openerp/addons/base/i18n/ro.po index 5eb162874eb..a68c6c5ae5f 100644 --- a/openerp/addons/base/i18n/ro.po +++ b/openerp/addons/base/i18n/ro.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-23 07:44+0000\n" -"X-Generator: Launchpad (build 16926)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ru.po b/openerp/addons/base/i18n/ru.po index de07ddc1135..a2547c4bba0 100644 --- a/openerp/addons/base/i18n/ru.po +++ b/openerp/addons/base/i18n/ru.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-23 05:47+0000\n" -"X-Generator: Launchpad (build 16872)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sk.po b/openerp/addons/base/i18n/sk.po index 931bd362f9c..ae674fbafa0 100644 --- a/openerp/addons/base/i18n/sk.po +++ b/openerp/addons/base/i18n/sk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-01-06 05:04+0000\n" -"X-Generator: Launchpad (build 16877)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sl.po b/openerp/addons/base/i18n/sl.po index 61771677c61..06f3ce60f19 100644 --- a/openerp/addons/base/i18n/sl.po +++ b/openerp/addons/base/i18n/sl.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:14+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sq.po b/openerp/addons/base/i18n/sq.po index 83131c5fc2e..db8099cca7e 100644 --- a/openerp/addons/base/i18n/sq.po +++ b/openerp/addons/base/i18n/sq.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:09+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:48+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sr.po b/openerp/addons/base/i18n/sr.po index ada202d9d5c..a6257f16089 100644 --- a/openerp/addons/base/i18n/sr.po +++ b/openerp/addons/base/i18n/sr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:14+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:58+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sr@latin.po b/openerp/addons/base/i18n/sr@latin.po index e5ef8917437..d0195138102 100644 --- a/openerp/addons/base/i18n/sr@latin.po +++ b/openerp/addons/base/i18n/sr@latin.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:18+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:07+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/sv.po b/openerp/addons/base/i18n/sv.po index 693da2b8573..08be224f6a1 100644 --- a/openerp/addons/base/i18n/sv.po +++ b/openerp/addons/base/i18n/sv.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-02 06:23+0000\n" -"X-Generator: Launchpad (build 16820)\n" +"X-Launchpad-Export-Date: 2014-04-04 06:59+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/th.po b/openerp/addons/base/i18n/th.po index bda5cd25c3e..ac4eaaf9574 100644 --- a/openerp/addons/base/i18n/th.po +++ b/openerp/addons/base/i18n/th.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2014-02-06 06:23+0000\n" -"X-Generator: Launchpad (build 16916)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/tlh.po b/openerp/addons/base/i18n/tlh.po index cbe11af13b9..4648ba2476c 100644 --- a/openerp/addons/base/i18n/tlh.po +++ b/openerp/addons/base/i18n/tlh.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:15+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/tr.po b/openerp/addons/base/i18n/tr.po index 7ce54b2dee2..df8d3d15374 100644 --- a/openerp/addons/base/i18n/tr.po +++ b/openerp/addons/base/i18n/tr.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:15+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/uk.po b/openerp/addons/base/i18n/uk.po index 345604b4398..f180ead7cda 100644 --- a/openerp/addons/base/i18n/uk.po +++ b/openerp/addons/base/i18n/uk.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:15+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:00+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/ur.po b/openerp/addons/base/i18n/ur.po index 4ecaa9081b0..3d3756ebfb0 100644 --- a/openerp/addons/base/i18n/ur.po +++ b/openerp/addons/base/i18n/ur.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:15+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:01+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/vi.po b/openerp/addons/base/i18n/vi.po index 5b26bb5eb0f..c08fb723378 100644 --- a/openerp/addons/base/i18n/vi.po +++ b/openerp/addons/base/i18n/vi.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:15+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:01+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/zh_CN.po b/openerp/addons/base/i18n/zh_CN.po index 409a866bb55..082b665b9c7 100644 --- a/openerp/addons/base/i18n/zh_CN.po +++ b/openerp/addons/base/i18n/zh_CN.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-11-27 05:39+0000\n" -"X-Generator: Launchpad (build 16845)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:05+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/zh_HK.po b/openerp/addons/base/i18n/zh_HK.po index 0d411f962b9..df3c6a70e63 100644 --- a/openerp/addons/base/i18n/zh_HK.po +++ b/openerp/addons/base/i18n/zh_HK.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-10-08 06:16+0000\n" -"X-Generator: Launchpad (build 16799)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:01+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing diff --git a/openerp/addons/base/i18n/zh_TW.po b/openerp/addons/base/i18n/zh_TW.po index 2a8b1bac99e..fa5e47ab6a1 100644 --- a/openerp/addons/base/i18n/zh_TW.po +++ b/openerp/addons/base/i18n/zh_TW.po @@ -14,8 +14,8 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-12-02 05:51+0000\n" -"X-Generator: Launchpad (build 16856)\n" +"X-Launchpad-Export-Date: 2014-04-04 07:05+0000\n" +"X-Generator: Launchpad (build 16976)\n" #. module: base #: model:ir.module.module,description:base.module_account_check_writing From f48ab8373bddd39951e15d8d2f204cc677e9be56 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 4 Apr 2014 11:19:47 +0200 Subject: [PATCH 078/140] [FIX] fixes a read_group test to use the correct field:interval key when grouping with an interval, and makes sure the sql request properly quote the order statement (without quoting DESC or ASC) (orm.py) bzr revid: ged@openerp.com-20140404091947-z87yg2bc7htovj4q --- openerp/addons/base/tests/test_orm.py | 2 +- openerp/osv/orm.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/tests/test_orm.py b/openerp/addons/base/tests/test_orm.py index fcd81965b8c..9683874f676 100644 --- a/openerp/addons/base/tests/test_orm.py +++ b/openerp/addons/base/tests/test_orm.py @@ -134,7 +134,7 @@ class TestORM(common.TransactionCase): rg = self.partner.read_group(self.cr, self.uid, domain, ['date'], 'date' + ':' + interval) result = {} for r in rg: - result[r['date']] = set(self.partner.search(self.cr, self.uid, r['__domain'])) + result[r['date:' + interval]] = set(self.partner.search(self.cr, self.uid, r['__domain'])) return result self.assertEqual(len(read_group('day')), len(partners_by_day)) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 1c72001c275..d8862591ed8 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2223,7 +2223,8 @@ class BaseModel(object): orderby_terms.append(order_clause) groupby_terms += [order_term.split()[0] for order_term in order_clause.split(',')] else: - orderby_terms.append('"%s"' % order_part) + order = '"%s" %s' % (order_field, '' if len(order_split) == 1 else order_split[1]) + orderby_terms.append(order) elif order_field in aggregated_fields: orderby_terms.append(order_part) else: From 96beccc05ae24c36865bc4ef1639a073f17bf9c7 Mon Sep 17 00:00:00 2001 From: "Foram Katharotiya (OpenERP)" Date: Fri, 4 Apr 2014 11:24:09 +0200 Subject: [PATCH 079/140] [IMP] bring back the tests - backported from little after v7.0 in the trunk lp bug: https://launchpad.net/bugs/1182515 fixed bzr revid: ls@numerigraphe.com-20140404092409-q1c2cwg5m2fav7tn --- addons/stock/__openerp__.py | 9 +- addons/stock/security/stock_security.xml | 2 +- addons/stock/stock_demo.yml | 128 ++++---- addons/stock/test/opening_stock.yml | 92 ++++-- addons/stock/test/shipment.yml | 356 ++++++++++++----------- addons/stock/test/stock_report.yml | 35 ++- addons/stock/test/stock_users.yml | 30 ++ 7 files changed, 372 insertions(+), 280 deletions(-) create mode 100644 addons/stock/test/stock_users.yml diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py index b3d7e30f1ce..dd2a996f6dd 100644 --- a/addons/stock/__openerp__.py +++ b/addons/stock/__openerp__.py @@ -59,7 +59,6 @@ Dashboard / Reports for Warehouse Management will include: 'sequence': 16, 'demo': [ 'stock_demo.xml', -# 'stock_demo.yml', ], 'data': [ 'security/stock_security.xml', @@ -91,9 +90,11 @@ Dashboard / Reports for Warehouse Management will include: 'res_config_view.xml', ], 'test': [ -# 'test/opening_stock.yml', -# 'test/shipment.yml', -# 'test/stock_report.yml', + 'test/stock_users.yml', + 'stock_demo.yml', + 'test/opening_stock.yml', + 'test/shipment.yml', + 'test/stock_report.yml', ], 'installable': True, 'application': True, diff --git a/addons/stock/security/stock_security.xml b/addons/stock/security/stock_security.xml index 10ae6a16d59..e51f20c67c9 100644 --- a/addons/stock/security/stock_security.xml +++ b/addons/stock/security/stock_security.xml @@ -10,7 +10,7 @@ Manager - + diff --git a/addons/stock/stock_demo.yml b/addons/stock/stock_demo.yml index 99565f0c08c..d925ba4dc8e 100644 --- a/addons/stock/stock_demo.yml +++ b/addons/stock/stock_demo.yml @@ -1,99 +1,107 @@ - - !record {model: stock.location, id: location_refrigerator}: - name: Refrigerator + Only stock manager can create location,warehouse and product, so let's check data with giving the access rights of manager +- + !context + uid: 'res_users_stock_manager' +- + !record {model: stock.location, id: location_monitor}: + name: chicago shop usage: internal - - !record {model: stock.location, id: location_delivery_counter}: - name: Delivery Counter + !record {model: stock.location, id: stock_location_output}: + name: Output usage: internal - - !record {model: stock.location, id: location_refrigerator_small}: - name: Small Refrigerator + !record {model: stock.location, id: location_monitor_small}: + name: Small chicago shop usage: internal - location_id: location_refrigerator + location_id: location_monitor - !record {model: stock.location, id: location_opening}: name: opening usage: inventory - - !record {model: stock.location, id: location_convenience_shop}: - name: Convenient Store + !record {model: stock.location, id: stock_location_3}: + name: IT Suppliers usage: supplier - - !record {model: stock.warehouse, id: warehouse_icecream}: - name: Ice Cream Shop - lot_input_id: location_refrigerator - lot_stock_id: location_refrigerator - lot_output_id: location_delivery_counter + !record {model: stock.warehouse, id: stock_warehouse_shop0}: + name: Chicago Warehouse + lot_input_id: location_monitor + lot_stock_id: location_monitor + lot_output_id: stock_location_output - - !record {model: product.product, id: product_icecream}: - default_code: 001 - name: Ice Cream - type: product - categ_id: product.product_category_1 - list_price: 100.0 - standard_price: 70.0 - uom_id: product.product_uom_kgm - uom_po_id: product.product_uom_kgm - procure_method: make_to_stock + !record {model: product.product, id: product_product_6}: + default_code: LCD15 + name: 15” LCD Monitor + type: consu + categ_id: product.product_category_8 + list_price: 1200.0 + standard_price: 800.0 + uom_id: product.product_uom_unit + uom_po_id: product.product_uom_unit property_stock_inventory: location_opening valuation: real_time cost_method: average - property_stock_account_input: account.o_expense - property_stock_account_output: account.o_income - description: Ice cream can be mass-produced and thus is widely available in developed parts of the world. Ice cream can be purchased in large cartons (vats and squrounds) from supermarkets and grocery stores, in smaller quantities from ice cream shops, convenience stores, and milk bars, and in individual servings from small carts or vans at public events. - + property_stock_account_input: account.conf_o_income + property_stock_account_output: account.a_expense - - !record {model: stock.production.lot, id: lot_icecream_0}: - name: Lot0 for Ice cream - product_id: product_icecream + Stock user can handled production lot,inventory and picking, so let's check data with giving the access rights of user - - !record {model: stock.production.lot, id: lot_icecream_1}: - name: Lot1 for Ice cream - product_id: product_icecream + !context + uid: 'res_users_stock_user' - - !record {model: stock.inventory, id: stock_inventory_icecream}: - name: Inventory for icecream + !record {model: stock.production.lot, id: lot_monitor_0}: + name: Lot0 for LCD Monitor + product_id: product_product_6 - - !record {model: stock.inventory.line, id: stock_inventory_line_icecream_lot0}: - product_id: product_icecream - product_uom: product.product_uom_kgm - inventory_id: stock_inventory_icecream + !record {model: stock.production.lot, id: lot_monitor_1}: + name: Lot1 for LCD Monitor + product_id: product_product_6 +- + !record {model: stock.inventory, id: stock_inventory_0}: + name: Starting Inventory + state: draft +- + !record {model: stock.inventory.line, id: stock_inventory_line_3}: + product_id: product_product_6 + product_uom: product.product_uom_unit + inventory_id: stock_inventory_0 product_qty: 50.0 - prod_lot_id: lot_icecream_0 - location_id: location_refrigerator + prod_lot_id: lot_monitor_0 + location_id: location_monitor - - !record {model: stock.inventory.line, id: stock_inventory_line_icecream_lot1}: - product_id: product_icecream - product_uom: product.product_uom_kgm - inventory_id: stock_inventory_icecream + !record {model: stock.inventory.line, id: stock_inventory_line_monitor}: + product_id: product_product_6 + product_uom: product.product_uom_unit + inventory_id: stock_inventory_0 product_qty: 40.0 - prod_lot_id: lot_icecream_1 - location_id: location_refrigerator + prod_lot_id: lot_monitor_1 + location_id: location_monitor - !record {model: stock.picking, id: outgoing_shipment}: type: out - location_dest_id: location_delivery_counter + location_dest_id: stock_location_output - - !record {model: stock.move, id: outgoing_shipment_icecream}: + !record {model: stock.move, id: outgoing_shipment_monitor}: picking_id: outgoing_shipment - product_id: product_icecream - product_uom: product.product_uom_kgm + product_id: product_product_6 + product_uom: product.product_uom_unit product_qty: 130.0 - location_id: location_refrigerator - location_dest_id: location_delivery_counter + location_id: location_monitor + location_dest_id: stock_location_output - !record {model: stock.picking, id: incomming_shipment}: type: in invoice_state: 2binvoiced partner_id: base.res_partner_address_9 - location_dest_id: location_refrigerator + location_dest_id: location_monitor - - !record {model: stock.move, id: incomming_shipment_icecream}: + !record {model: stock.move, id: incomming_shipment_monitor}: picking_id: incomming_shipment - product_id: product_icecream - product_uom: product.product_uom_kgm + product_id: product_product_6 + product_uom: product.product_uom_unit product_qty: 50.0 - location_id: location_convenience_shop - location_dest_id: location_refrigerator + location_id: stock_location_3 + location_dest_id: location_monitor diff --git a/addons/stock/test/opening_stock.yml b/addons/stock/test/opening_stock.yml index 2e3eaeadc74..9efcfd3af99 100644 --- a/addons/stock/test/opening_stock.yml +++ b/addons/stock/test/opening_stock.yml @@ -1,67 +1,87 @@ - - I update the price of the Ice-cream. + Only stock manager can change the price and update stock of products, so let's check data with giving the access rights of manager +- + !context + uid: 'res_users_stock_manager' +- + I update the price of the 15” LCD Monitor. - !python {model: stock.change.standard.price}: | - context.update({'active_model':'product.product', 'active_id': ref('product_icecream'), 'active_ids':[ref('product_icecream')]}) + context.update({'active_model':'product.product', 'active_id': ref('product_product_6'), 'active_ids':[ref('product_product_6')]}) - !record {model: stock.change.standard.price, id: change_price}: - new_price: 120 + new_price: 1500 - !python {model: stock.change.standard.price}: | self.change_price(cr, uid, [ref('change_price')], context=context) - - I check price of Ice-cream after update price. + I check price of 15” LCD Monitor after update price. - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) - assert product.standard_price == 120, "Price is not updated." + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert product.standard_price == 1500, "Price is not updated." - - I update the current stock of the Ice-cream with 10 kgm in Small Refrigerator in lot0. + I update the current stock of the 15” LCD Monitor with 10 unit in stock location shop1 in lot0. - !record {model: stock.change.product.qty, id: change_qty}: - location_id: location_refrigerator_small + location_id: location_monitor_small new_quantity: 10 - product_id: product_icecream - prodlot_id: lot_icecream_1 + product_id: product_product_6 + prodlot_id: lot_monitor_1 - !python {model: stock.change.product.qty}: | self.change_product_qty(cr, uid, [ref('change_qty')], context=context) - - I check available stock of Ice-cream after update stock. + I check available stock of 15” LCD Monitor after update stock. - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) + product = self.browse(cr, uid, ref('product_product_6'), context=context) assert product.qty_available == 10, "Stock is not updated." +- + Stock user can merge inventory, so let's check data with giving the access rights of user. +- + !context + uid: 'res_users_stock_user' - I merge inventory. - !python {model: stock.inventory.merge }: | - context.update({'active_model': 'stock.inventory', 'active_id': ref('stock_inventory_icecream'), 'active_ids': [ref('stock_inventory_icecream')]}) + context.update({'active_model': 'stock.inventory', 'active_id': ref('stock_inventory_0'), 'active_ids': [ref('stock_inventory_0')]}) - !record {model: stock.inventory.merge, id: merge_inventory}: - !python {model: stock.inventory.merge }: | self.do_merge(cr, uid, [ref('merge_inventory')], context=context) +- + Only stock manager cancelled inventory, so let's check data with giving the access rights of manager +- + !context + uid: 'res_users_stock_manager' - I cancel inventory. - !python {model: stock.inventory}: | - self.action_cancel_inventory(cr, uid, [ref('stock_inventory_icecream')]) + self.action_cancel_inventory(cr, uid, [ref('stock_inventory_0')]) +- + stock user can reset inventory, so let's check data with giving the access rights of user +- + !context + uid: 'res_users_stock_user' - I reset to draft inventory. - !python {model: stock.inventory}: | - self.action_cancel_draft(cr, uid, [ref('stock_inventory_icecream')]) + self.action_cancel_draft(cr, uid, [ref('stock_inventory_0')]) - - I confirm physical inventory of Ice-cream which are came in different lots. + I confirm physical inventory of 15” LCD Monitor which are came in different lots. - !python {model: stock.inventory}: | - self.action_confirm(cr, uid, [ref('stock_inventory_icecream')], context=context) + self.action_confirm(cr, uid, [ref('stock_inventory_0')], context=context) - I check move details after confirmed physical inventory. - !python {model: stock.inventory}: | - inventory = self.browse(cr, uid, ref('stock_inventory_icecream'), context=context) + inventory = self.browse(cr, uid, ref('stock_inventory_0'), context=context) assert len(inventory.move_ids) == len(inventory.inventory_line_id), "moves are not correspond." for move_line in inventory.move_ids: for line in inventory.inventory_line_id: @@ -77,15 +97,15 @@ I split inventory line. - !python {model: stock.inventory.line.split}: | - context.update({'active_model': 'stock.inventory.line', 'active_id': ref('stock_inventory_line_icecream_lot0'), 'active_ids': [ref('stock_inventory_line_icecream_lot0')]}) + context.update({'active_model': 'stock.inventory.line', 'active_id': ref('stock_inventory_line_3'), 'active_ids': [ref('stock_inventory_line_3')]}) - !record {model: stock.inventory.line.split, id: split_inventory_lot0}: use_exist: True line_exist_ids: - quantity: 6 - prodlot_id: lot_icecream_0 + prodlot_id: lot_monitor_0 - quantity: 4 - prodlot_id: lot_icecream_0 + prodlot_id: lot_monitor_0 - !python {model: stock.inventory.line.split }: | self.split_lot(cr, uid, [ref('split_inventory_lot0')], context=context) @@ -93,39 +113,49 @@ I fill inventory line. - !python {model: stock.fill.inventory}: | - context.update({'active_model': 'stock.inventory', 'active_id': ref('stock_inventory_icecream'), 'active_ids': [ref('stock_inventory_icecream')]}) + context.update({'active_model': 'stock.inventory', 'active_id': ref('stock_inventory_0'), 'active_ids': [ref('stock_inventory_0')]}) - !record {model: stock.fill.inventory, id: fill_inventory}: - location_id: location_refrigerator + location_id: location_monitor recursive: True - !python {model: stock.fill.inventory }: | self.fill_inventory(cr, uid, [ref('fill_inventory')], context=context) - - Now I check vitual stock of Ice-cream after confirmed physical inventory. + Now I check vitual stock of 15” LCD Monitor after confirmed physical inventory. - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) + product = self.browse(cr, uid, ref('product_product_6'), context=context) assert product.virtual_available == 100, "Vitual stock is not updated." - - I close physical inventory of Ice-cream. + Only stock manager can close physical inventory, so let's check data with giving the access rights of manager +- + !context + uid: 'res_users_stock_manager' +- + I close physical inventory of 15” LCD Monitor. - !python {model: stock.inventory}: | - self.action_done(cr, uid, [ref('stock_inventory_icecream')], context=context) + self.action_done(cr, uid, [ref('stock_inventory_0')], context=context) - - I check closed move and real stock of Ice-cream after closed physical inventory. + Stock user can check closed move and real stock, so let's check data with giving the access rights of user +- + !context + uid: 'res_users_stock_user' +- + I check closed move and real stock of 15” LCD Monitor after closed physical inventory. - !python {model: stock.inventory}: | - inventory = self.browse(cr, uid, ref('stock_inventory_icecream'), context=context) + inventory = self.browse(cr, uid, ref('stock_inventory_0'), context=context) assert inventory.state == 'done', "inventory is not closed." for move_line in inventory.move_ids: assert move_line.state == 'done', "Move is not closed." - product = self.pool.get('product.product').browse(cr, uid, ref('product_icecream'), context=context) + product = self.pool.get('product.product').browse(cr, uid, ref('product_product_6'), context=context) product.qty_available == 100, "Real stock is not updated." - I check stock in lot. - !python {model: stock.production.lot}: | - lot = self.browse(cr, uid, ref('lot_icecream_0'), context=context) + lot = self.browse(cr, uid, ref('lot_monitor_0'), context=context) assert lot.stock_available == 50, "Stock in lot is not correspond." diff --git a/addons/stock/test/shipment.yml b/addons/stock/test/shipment.yml index b30feccdacf..5f2f4686621 100644 --- a/addons/stock/test/shipment.yml +++ b/addons/stock/test/shipment.yml @@ -1,9 +1,14 @@ - - I confirm outgoing shipment of 130 kgm Ice-cream. + Stock manager can only test whole process related to Shipment, so let's check data with stock manager. +- + !context + uid: 'res_users_stock_manager' +- + I confirm outgoing shipment of 130 Unit 15” LCD Monitor. - !workflow {model: stock.picking, action: button_confirm, ref: outgoing_shipment} - - I check shipment details after confirmed. + I check shipment details after confirmation. - !python {model: stock.picking}: | shipment = self.browse(cr, uid, ref("outgoing_shipment")) @@ -12,121 +17,25 @@ assert move_line.state == "confirmed", "Move should be confirmed." - - Now I check vitual stock of Ice-cream after confirmed outgoing shipment. + Now, I check virtual stock of 15” LCD Monitor after confirming outgoing shipment. - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) - product.virtual_available == -30, "Vitual stock is not updated." + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert product.virtual_available == -30, "Virtual stock is not updated." - - I confirm incomming shipment of 50 kgm Ice-cream. + I confirm incoming shipment of 50 Unit 15” LCD Monitor. - !workflow {model: stock.picking, action: button_confirm, ref: incomming_shipment} - - I receive 40kgm Ice-cream so I make backorder of incomming shipment for 40 kgm. -- - !python {model: stock.partial.picking}: | - context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]}) -- - !record {model: stock.partial.picking, id: partial_incomming}: - move_ids: - - quantity: 40 - product_id: product_icecream - product_uom: product.product_uom_kgm - move_id: incomming_shipment_icecream - location_id: location_convenience_shop - location_dest_id: location_refrigerator -- - !python {model: stock.partial.picking }: | - self.do_partial(cr, uid, [ref('partial_incomming')], context=context) -- - I check backorder shipment after received partial shipment. + I split incoming shipment into lots. each lot contain 10 Unit 15” LCD Monitor. - !python {model: stock.picking}: | shipment = self.browse(cr, uid, ref("incomming_shipment")) - backorder = shipment.backorder_id - assert backorder, "Backorder should be created after partial shipment." - assert backorder.state == 'done', "Backorder should be close after received." - for move_line in backorder.move_lines: - assert move_line.product_qty == 40, "Qty in backorder does not correspond." - assert move_line.state == 'done', "Move line of backorder should be closed." -- - I receive another 10kgm Ice-cream. -- - !record {model: stock.partial.picking, id: partial_incomming}: - move_ids: - - quantity: 10 - product_id: product_icecream - product_uom: product.product_uom_kgm - move_id: incomming_shipment_icecream - location_id: location_convenience_shop - location_dest_id: location_refrigerator -- - !python {model: stock.partial.picking }: | - self.do_partial(cr, uid, [ref('partial_incomming')], context=context) - -- - I check incomming shipment after received. -- - !python {model: stock.picking}: | - shipment = self.browse(cr, uid, ref("incomming_shipment")) - assert shipment.state == 'done', "shipment should be close after received." - for move_line in shipment.move_lines: - assert move_line.product_qty == 10, "Qty does not correspond." - assert move_line.product_id.virtual_available == 20, "Virtual stock does not correspond." - assert move_line.state == 'done', "Move line should be closed." - -- - I return last incomming shipment for 10 kgm Ice-cream. -- - !record {model: stock.return.picking, id: return_incomming}: - invoice_state: none -- - !python {model: stock.return.picking }: | - # this work without giving the id of the picking to return, magically, thanks to the context - self.create_returns(cr, uid, [ref('return_incomming')], context=context) -- - I cancel incomming shipment after return it. -- - !python {model: stock.picking}: | - # the cancel is not on the return, but on the incomming shipment (which now has a quantity of 10, thanks to the - # backorder). This situation is a little weird as we returned a move that we finally cancelled... As result, only - # 30Kg from the original 50Kg will be counted in the stock (50 - 10 (cancelled quantity) - 10 (returned quantity)) - self.action_cancel(cr, uid, [ref("incomming_shipment")], context=context) -- - I make invoice of backorder of incomming shipment. -- - !python {model: stock.invoice.onshipping}: | - shipment = self.pool.get('stock.picking').browse(cr, uid, ref("incomming_shipment")) - context.update({'active_model': 'stock.picking', 'active_id': shipment.backorder_id.id, 'active_ids': [shipment.backorder_id.id]}) -- - !record {model: stock.invoice.onshipping, id: invoice_incomming}: - group: False -- - !python {model: stock.invoice.onshipping }: | - self.create_invoice(cr, uid, [ref('invoice_incomming')], context=context) -- - I check invoice state of backorder of incomming shipment. -- - !python {model: stock.picking}: | - shipment = self.browse(cr, uid, ref("incomming_shipment")) - assert shipment.backorder_id.invoice_state == 'invoiced', 'Invoice state is not upadted.' -- - I check available stock after received incomming shipping. -- - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) - assert product.qty_available == 140, "Stock does not correspond." - assert product.virtual_available == 0, "Vitual stock does not correspond." -- - I split incomming shipment into lots. each lot contain 10 kgm Ice-cream. -- - !python {model: stock.picking}: | - shipment = self.browse(cr, uid, ref("incomming_shipment")) - move_ids = [x.id for x in shipment.backorder_id.move_lines] + move_ids = [x.id for x in shipment.move_lines] context.update({'active_model': 'stock.move', 'active_id': move_ids[0], 'active_ids': move_ids}) - - !record {model: stock.move.split, id: split_lot_incomming}: + !record {model: stock.move.split, id: split_lot_incoming}: line_ids: - name: incoming_lot0 quantity: 10 @@ -136,23 +45,123 @@ quantity: 10 - name: incoming_lot3 quantity: 10 - - !python {model: stock.move.split }: | - self.split_lot(cr, uid, [ref('split_lot_incomming')], context=context) + self.split_lot(cr, uid, [ref('split_lot_incoming')], context=context) - - I check move lines after spliting + I check move lines after splitting. - !python {model: stock.move}: | - lot = self.pool.get('stock.move.split').browse(cr, uid, ref('split_lot_incomming'), context=context) + mm = self.browse(cr, uid, ref("incomming_shipment_monitor")) + lot = self.pool.get('stock.move.split').browse(cr, uid, ref('split_lot_incoming'), context=context) lot_ids = self.pool.get('stock.production.lot').search(cr, uid, [('name','in',[x.name for x in lot.line_ids])]) - assert len(lot_ids) == 4, 'lots of incomming shipment are not correspond.' - move_ids = self.search(cr, uid, [('location_dest_id','=',ref('location_refrigerator')),('prodlot_id','in',lot_ids)]) - assert len(move_ids) == 4, 'move lines are not correspond per prodcution lot after splited.' + assert len(lot_ids) == 4, 'lots of incoming shipment are not correspond.' + move_ids = self.search(cr, uid, [('location_dest_id','=',ref('location_monitor')),('prodlot_id','in',lot_ids)]) + assert len(move_ids) == 4, 'move lines are not correspond per production lot after splitting.' for move in self.browse(cr, uid, move_ids, context=context): assert move.prodlot_id.name in ['incoming_lot0', 'incoming_lot1', 'incoming_lot2', 'incoming_lot3'], "lot does not correspond." assert move.product_qty == 10, "qty does not correspond per production lot." - context.update({'active_model':'stock.move', 'active_id':move_ids[0],'active_ids': move_ids}) +- + I receive 40 units of 15” LCD Monitor. +- + !python {model: stock.partial.picking}: | + context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]}) +- + !python {model: stock.partial.picking}: | + partial = [] + for move in self.pool.get('stock.picking').browse(cr, uid, ref("incomming_shipment")).move_lines: + if move.prodlot_id: + partial.append((0, 0, { + 'quantity': move.product_qty, + 'product_id': move.product_id.id, + 'product_uom': move.product_uom.id, + 'move_id': move.id, + 'location_id': move.location_id.id, + 'location_dest_id': move.location_dest_id.id, + 'prodlot_id': move.prodlot_id.id, + 'cost': move.product_id.standard_price + })) + partial_id = self.create(cr, uid, {'move_ids': partial}, context=context) + self.do_partial(cr, uid, [partial_id], context=context) +- + I check backorder shipment after receiving partial shipment. +- + !python {model: stock.picking}: | + shipment = self.browse(cr, uid, ref("incomming_shipment")) + backorder = shipment.backorder_id + assert backorder, "Backorder should be created after partial shipment." + assert backorder.state == 'done', "Backorder should be closed after received." + qty = 0 + for move_line in backorder.move_lines: + assert move_line.state == 'done', "Move line of backorder should be closed." + qty += move_line.product_qty + assert qty == 40, "Qty in backorder does not correspond." +- + I receive another 10 units of 15” LCD Monitor. +- + !record {model: stock.partial.picking, id: partial_incoming}: + move_ids: + - quantity: 10 + product_id: product_product_6 + product_uom: product.product_uom_unit + move_id: incomming_shipment_monitor + location_id: stock_location_3 + location_dest_id: location_monitor +- + !python {model: stock.partial.picking }: | + self.do_partial(cr, uid, [ref('partial_incoming')], context=context) +- + I check incoming shipment after receiving it. +- + !python {model: stock.picking}: | + shipment = self.browse(cr, uid, ref("incomming_shipment")) + assert shipment.state == 'done', "shipment should be closed after receiving." + for move_line in shipment.move_lines: + assert move_line.product_qty == 10, "Qty does not correspond." + assert move_line.product_id.virtual_available == 20, "Virtual stock does not correspond." + assert move_line.state == 'done', "Move line should be closed." +- + I return last incoming shipment for 10 Unit 15” LCD Monitor. +- + !record {model: stock.return.picking, id: return_incoming}: + invoice_state: none +- + !python {model: stock.return.picking }: | + # this work without giving the id of the picking to return, magically, thanks to the context + self.create_returns(cr, uid, [ref('return_incoming')], context=context) +- + I cancel incoming shipment after returning it. +- + !python {model: stock.picking}: | + # the cancel is not on the return, but on the incoming shipment (which now has a quantity of 10, thanks to the + # backorder). This situation is a little weird as we returned a move that we finally cancelled... As result, only + # 30Unit from the original 50Unit will be counted in the stock (50 - 10 (cancelled quantity) - 10 (returned quantity)) + self.action_cancel(cr, uid, [ref("incomming_shipment")], context=context) +- + I make invoice of backorder of incoming shipment. +- + !python {model: stock.invoice.onshipping}: | + shipment = self.pool.get('stock.picking').browse(cr, uid, ref("incomming_shipment")) + context.update({'active_model': 'stock.picking', 'active_id': shipment.backorder_id.id, 'active_ids': [shipment.backorder_id.id]}) +- + !record {model: stock.invoice.onshipping, id: invoice_incoming}: + group: False +- + !python {model: stock.invoice.onshipping }: | + self.create_invoice(cr, uid, [ref('invoice_incoming')], context=context) +- + I check invoice status of backorder of incoming shipment. +- + !python {model: stock.picking}: | + shipment = self.browse(cr, uid, ref("incomming_shipment")) + assert shipment.backorder_id.invoice_state == 'invoiced', 'Invoice state is not updated.' +- + I check available stock after receiving incoming shipping. +- + !python {model: product.product}: | + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert product.qty_available == 140, "Stock does not correspond." + assert product.virtual_available == 0, "Virtual stock does not correspond." - I check the stock valuation account entries. - @@ -161,91 +170,90 @@ account_move_ids = self.search(cr, uid, [('ref','=',incomming_shipment.name)]) assert len(account_move_ids), "account move should be created." account_move = self.browse(cr, uid, account_move_ids[0], context=context) - assert len(account_move.line_id) == len(incomming_shipment.move_lines) + 1, 'accuont entries are not correspond.' + assert len(account_move.line_id) == len(incomming_shipment.move_lines) + 1, 'Accounting entries does not correspond.' for account_move_line in account_move.line_id: for stock_move in incomming_shipment.move_lines: if account_move_line.account_id.id == stock_move.product_id.property_stock_account_input.id: - assert account_move_line.credit == 800.0, "Credit amount does not correspond." + assert account_move_line.credit == 14000.0, "Credit amount does not correspond." assert account_move_line.debit == 0.0, "Debit amount does not correspond." else: assert account_move_line.credit == 0.0, "Credit amount does not correspond." - assert account_move_line.debit == 800.0, "Debit amount does not correspond." -- - I consume 1 kgm ice-cream from each incoming lots into internal production. -- - !record {model: stock.move.consume, id: consume_lot_incomming}: - product_qty: 1 - location_id: location_refrigerator -- - !python {model: stock.move.consume}: | - self.do_move_consume(cr, uid, [ref('consume_lot_incomming')], context=context) -- - I scrap 10 gm ice-cream from each incoming lots into scrap location. -- - !record {model: stock.move.scrap, id: scrap_lot_incomming}: - product_qty: 0.010 -- - !python {model: stock.move.scrap}: | - self.move_scrap(cr, uid, [ref('scrap_lot_incomming')], context=context) -- - I check stock in scrap location and refrigerator location. -- - !python {model: stock.location}: | - ctx = {'product_id': ref('product_icecream')} - refrigerator_location = self.pool.get('stock.location').browse(cr, uid, ref('location_refrigerator'), context=ctx) - assert refrigerator_location.stock_real == 135.96, 'stock does not correspond in refrigerator location.' - scrapped_location = self.browse(cr, uid, ref('stock_location_scrapped'), context=ctx) - assert scrapped_location.stock_real == 0.010*4, 'scraped stock does not correspond in scrap location.' - -- - I check availabile stock after consumed and scraped. -- - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) - assert product.qty_available == 135.96, "Stock does not correspond." - assert round(product.virtual_available, 2) == -4.04, "Vitual stock does not correspond." + assert account_move_line.debit == 14000.0, "Debit amount does not correspond." - I trace all incoming lots. - !python {model: stock.production.lot }: | - lot = self.pool.get('stock.move.split').browse(cr, uid, ref('split_lot_incomming'), context=context) + lot = self.pool.get('stock.move.split').browse(cr, uid, ref('split_lot_incoming'), context=context) lot_ids = self.search(cr, uid, [('name', 'in', [x.name for x in lot.line_ids])]) self.action_traceability(cr, uid, lot_ids, context=context) - - I check outgoing shipment after stock availablity in refrigerator. + I check outgoing shipment after stock availability in Chicago shop. - !python {model: stock.picking}: | shipment = self.browse(cr, uid, ref("outgoing_shipment"), context=context) - self.pool.get('stock.move').action_assign(cr, uid, [x.id for x in shipment.move_lines]) #TOFIX: assignment of move lines should be call before testing assigment otherwise picking never gone in assign state - #TOFIX: shipment should be assigned if stock available - #assert shipment.state == "assigned", "Shipment should be assigned." - #for move_line in shipment.move_lines: - # assert move_line.state == "assigned", "Move should be assigned." + self.pool.get('stock.move').action_assign(cr, uid, [x.id for x in shipment.move_lines]) + assert shipment.state == "assigned", "Shipment should be assigned." + for move_line in shipment.move_lines: + assert move_line.state == "assigned", "Move should be assigned." self.force_assign(cr, uid, [shipment.id]) + context.update({'active_model':'stock.move', 'active_id':shipment.move_lines[0].id,'active_ids': [shipment.move_lines[0].id]}) - - I deliver 5kgm Ice-cream to customer so I make partial deliver + I scrap 4 units of 15” LCD Monitor into scrap location. +- + !record {model: stock.move.scrap, id: scrap_monitor1}: + product_qty: 4 +- + !python {model: stock.move.scrap}: | + self.move_scrap(cr, uid, [ref('scrap_monitor1')], context=context) +- + I consume 4 units of 15” LCD Monitor. +- + !record {model: stock.move.consume, id: consume_monitor1}: + product_qty: 4 + location_id: location_monitor +- + !python {model: stock.move.consume}: | + self.do_move_consume(cr, uid, [ref('consume_monitor1')], context=context) +- + I check stock in scrap location and stock location. +- + !python {model: stock.location}: | + ctx = {'product_id': ref('product_product_6')} + monitor_location = self.pool.get('stock.location').browse(cr, uid, ref('location_monitor'), context=ctx) + assert monitor_location.stock_real == 132.0, 'stock does not correspond in stock location shop0.' + scrapped_location = self.browse(cr, uid, ref('stock_location_scrapped'), context=ctx) + assert scrapped_location.stock_real == 4, 'scraped stock does not correspond in scrap location.' +- + I check available stock after consumed and scraped move. +- + !python {model: product.product}: | + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert product.qty_available == 132.0, "Stock does not correspond." + assert round(product.virtual_available, 2) == -4.00, "Virtual stock does not correspond." +- + I deliver 5 Unit 15” LCD Monitor to customer partially. - !python {model: stock.partial.move}: | - context.update({'active_model': 'stock.move', 'active_id': ref('outgoing_shipment_icecream'), 'active_ids': [ref('outgoing_shipment_icecream')]}) + context.update({'active_model': 'stock.move', 'active_id': ref('outgoing_shipment_monitor'), 'active_ids': [ref('outgoing_shipment_monitor')]}) - - !record {model: stock.partial.move, id: partial_outgoing_icecream}: + !record {model: stock.partial.move, id: partial_outgoing_monitor}: move_ids: - quantity: 5 - product_id: product_icecream - product_uom: product.product_uom_kgm - move_id: outgoing_shipment_icecream - location_id: location_refrigerator - location_dest_id: location_delivery_counter + product_id: product_product_6 + product_uom: product.product_uom_unit + move_id: outgoing_shipment_monitor + location_id: location_monitor + location_dest_id: stock_location_output - !python {model: stock.partial.move }: | - self.do_partial(cr, uid, [ref('partial_outgoing_icecream')], context=context) + self.do_partial(cr, uid, [ref('partial_outgoing_monitor')], context=context) - - I packing outgoing shipment into box per 10kgm with unique tracking lot. + I pack outgoing shipment into box of 10 Unit with unique tracking lot. - !python {model: stock.move}: | stock_split = self.pool.get('stock.split.into') - move = self.browse(cr, uid, ref('outgoing_shipment_icecream'), context=context) + move = self.browse(cr, uid, ref('outgoing_shipment_monitor'), context=context) context.update({'active_model': 'stock.move', 'active_id': move.id, 'active_ids': [move.id]}) total_qty = move.product_qty split_qty = 10 @@ -254,7 +262,7 @@ stock_split.split(cr, uid, [split_id], context=context) total_qty -= split_qty - - I deliver outgoing shipment. + I deliver the outgoing shipment. - !python {model: stock.partial.picking}: | context.update({'active_model': 'stock.picking', 'active_id': ref('outgoing_shipment'), 'active_ids': [ref('outgoing_shipment')]}) @@ -266,7 +274,7 @@ self.do_partial(cr, uid, [ref('partial_outgoing')], context=context) - - I check outgoing shipment after deliver. + I check outgoing shipment after delivery. - !python {model: stock.picking}: | shipment = self.browse(cr, uid, ref("outgoing_shipment"), context=context) @@ -274,9 +282,9 @@ for move_line in shipment.move_lines: assert move_line.state == "done", "Move should be closed." - - I check availaible stock after deliver. + I check available stock after delivery. - !python {model: product.product}: | - product = self.browse(cr, uid, ref('product_icecream'), context=context) - assert round(product.qty_available, 2) == 5.96, "Stock does not correspond." - assert round(product.virtual_available, 2) == -4.04, "Vitual stock does not correspond." + product = self.browse(cr, uid, ref('product_product_6'), context=context) + assert round(product.qty_available, 2) == 6, "Stock does not correspond." + assert round(product.virtual_available, 2) == -4.00, "Virtual stock does not correspond." diff --git a/addons/stock/test/stock_report.yml b/addons/stock/test/stock_report.yml index 5c5932446eb..21ed6046805 100644 --- a/addons/stock/test/stock_report.yml +++ b/addons/stock/test/stock_report.yml @@ -1,41 +1,56 @@ +- + Stock user can print all reports related to stock, so let's check data with giving the access rights of user. +- + !context + uid: 'res_users_stock_user' - I print a stock overview report of location. - !python {model: stock.location}: | - import netsvc, tools, os - (data, format) = netsvc.LocalService('report.lot.stock.overview').create(cr, uid, [ref('location_refrigerator')], {}, {}) + import os + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('location_monitor')], 'lot.stock.overview', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-overview'+format), 'wb+').write(data) - I print a Stock Overview report of location with child location. - !python {model: stock.location}: | - import netsvc, tools, os - (data, format) = netsvc.LocalService('report.lot.stock.overview_all').create(cr, uid, [ref('location_refrigerator')], {}, {}) + import os + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('location_monitor')], 'lot.stock.overview_all', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-overviewall'+format), 'wb+').write(data) - I print a Stock Inventory report. - !python {model: stock.inventory}: | - import netsvc, tools, os - (data, format) = netsvc.LocalService('report.stock.inventory.move').create(cr, uid, [ref('stock_inventory_icecream')], {}, {}) + import os + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('stock_inventory_0')], 'stock.inventory.move', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-stock_inventory_move.'+format), 'wb+').write(data) - I print a outgoing shipment report. - !python {model: stock.picking}: | - import netsvc, tools, os - (data, format) = netsvc.LocalService('report.stock.picking.list').create(cr, uid, [ref('outgoing_shipment')], {}, {}) + import os + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('outgoing_shipment')], 'stock.picking.list', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-picking_list'+format), 'wb+').write(data) - I print stock Report. - !python {model: product.product}: | - import netsvc, tools, os - (data, format) = netsvc.LocalService('report.stock.product.history').create(cr, uid, [ref('product_icecream')], {}, {}) + import os + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref('product_product_6')], 'stock.product.history', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-product_stock_report.'+format), 'wb+').write(data) diff --git a/addons/stock/test/stock_users.yml b/addons/stock/test/stock_users.yml new file mode 100644 index 00000000000..d0c09dc745d --- /dev/null +++ b/addons/stock/test/stock_users.yml @@ -0,0 +1,30 @@ +- + Create a user as 'Stock Manager' +- + !record {model: res.users, id: res_users_stock_manager}: + company_id: base.main_company + name: Stock Manager + login: sam + password: sam + email: stockmanager@yourcompany.com +- + I added groups for Stock Manager. +- + !record {model: res.users, id: res_users_stock_manager}: + groups_id: + - stock.group_stock_manager +- + Create a user as 'Stock User' +- + !record {model: res.users, id: res_users_stock_user}: + company_id: base.main_company + name: Stock User + login: sau + password: sau + email: stockuser@yourcompany.com +- + I added groups for Stock User. +- + !record {model: res.users, id: res_users_stock_user}: + groups_id: + - stock.group_stock_user From 90ddb9f8975d9d99fadd864538f6e9f285d63b79 Mon Sep 17 00:00:00 2001 From: Lionel Sausin Date: Fri, 4 Apr 2014 11:52:02 +0200 Subject: [PATCH 080/140] [FIX] revert to v7 report API bzr revid: ls@numerigraphe.com-20140404095202-wwegxz9qp00o8yuw --- addons/stock/test/stock_report.yml | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/addons/stock/test/stock_report.yml b/addons/stock/test/stock_report.yml index 21ed6046805..effbf2affe2 100644 --- a/addons/stock/test/stock_report.yml +++ b/addons/stock/test/stock_report.yml @@ -7,50 +7,40 @@ I print a stock overview report of location. - !python {model: stock.location}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('location_monitor')], 'lot.stock.overview', {}, {}) + import netsvc, tools, os + (data, format) = netsvc.LocalService('report.lot.stock.overview').create(cr, uid, [ref('location_monitor')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-overview'+format), 'wb+').write(data) - I print a Stock Overview report of location with child location. - !python {model: stock.location}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('location_monitor')], 'lot.stock.overview_all', {}, {}) + import netsvc, tools, os + (data, format) = netsvc.LocalService('report.lot.stock.overview_all').create(cr, uid, [ref('location_monitor')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-overviewall'+format), 'wb+').write(data) - I print a Stock Inventory report. - !python {model: stock.inventory}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('stock_inventory_0')], 'stock.inventory.move', {}, {}) + import netsvc, tools, os + (data, format) = netsvc.LocalService('report.stock.inventory.move').create(cr, uid, [ref('stock_inventory_0')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-stock_inventory_move.'+format), 'wb+').write(data) - I print a outgoing shipment report. - !python {model: stock.picking}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('outgoing_shipment')], 'stock.picking.list', {}, {}) + import netsvc, tools, os + (data, format) = netsvc.LocalService('report.stock.picking.list').create(cr, uid, [ref('outgoing_shipment')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-picking_list'+format), 'wb+').write(data) - I print stock Report. - !python {model: product.product}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref('product_product_6')], 'stock.product.history', {}, {}) + import netsvc, tools, os + (data, format) = netsvc.LocalService('report.stock.product.history').create(cr, uid, [ref('product_product_6')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'stock-product_stock_report.'+format), 'wb+').write(data) From 368afae722724520097390dc77d928f72e2cddc4 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Fri, 4 Apr 2014 12:25:12 +0200 Subject: [PATCH 081/140] [FIX] website_sale: order data refresh problem bzr revid: dle@openerp.com-20140404102512-72x74ys4k6whk8ss --- addons/delivery/sale.py | 12 +++++------- addons/website_sale/controllers/main.py | 5 ++--- addons/website_sale/views/website_sale.xml | 2 +- addons/website_sale_delivery/models/sale_order.py | 15 +++++++++------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/addons/delivery/sale.py b/addons/delivery/sale.py index dbebd01ef1e..c5d032ca8a8 100644 --- a/addons/delivery/sale.py +++ b/addons/delivery/sale.py @@ -58,20 +58,18 @@ class sale_order(osv.Model): result.update(carrier_id=order.carrier_id.id) return result - def _delivery_unset(self, cr, uid, order, context=None): - line_ids = [line.id for line in order.order_line if line.is_delivery] - self.pool['sale.order.line'].unlink(cr, uid, line_ids, context=context) - order.refresh() - return True + def _delivery_unset(self, cr, uid, ids, context=None): + sale_obj = self.pool['sale.order.line'] + line_ids = sale_obj.search(cr, uid, [('order_id', 'in', ids), ('is_delivery', '=', True)],context=context) + sale_obj.unlink(cr, uid, line_ids, context=context) def delivery_set(self, cr, uid, ids, context=None): line_obj = self.pool.get('sale.order.line') grid_obj = self.pool.get('delivery.grid') carrier_obj = self.pool.get('delivery.carrier') acc_fp_obj = self.pool.get('account.fiscal.position') - + self._delivery_unset(cr, uid, ids, context=context) for order in self.browse(cr, uid, ids, context=context): - self._delivery_unset(cr, uid, order, context=context) grid_id = carrier_obj.grid_get(cr, uid, [order.carrier_id.id], order.partner_shipping_id.id) if not grid_id: raise osv.except_osv(_('No Grid Available!'), _('No grid matching for this carrier!')) diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py index 99f39a3c921..78ae0beb7a2 100644 --- a/addons/website_sale/controllers/main.py +++ b/addons/website_sale/controllers/main.py @@ -604,9 +604,8 @@ class Ecommerce(http.Controller): else: shipping_partner_id = order.partner_invoice_id.id - values = { - 'order': sale_order_obj.browse(cr, SUPERUSER_ID, order.id, context=context) - } + values = {} + values['website_sale_order'] = values['order'] = sale_order_obj.browse(cr, SUPERUSER_ID, order.id, context=context) values['errors'] = sale_order_obj._get_errors(cr, uid, order, context=context) values.update(sale_order_obj._get_website_data(cr, uid, order, context=context)) diff --git a/addons/website_sale/views/website_sale.xml b/addons/website_sale/views/website_sale.xml index 446dfb4567e..350d9acdac0 100644 --- a/addons/website_sale/views/website_sale.xml +++ b/addons/website_sale/views/website_sale.xml @@ -885,7 +885,7 @@

    Validate Order

    -

    +

    diff --git a/addons/website_sale_delivery/models/sale_order.py b/addons/website_sale_delivery/models/sale_order.py index 9826d2105f6..e8b34591940 100644 --- a/addons/website_sale_delivery/models/sale_order.py +++ b/addons/website_sale_delivery/models/sale_order.py @@ -64,15 +64,16 @@ class SaleOrder(orm.Model): return False if all(line.product_id.type == "service" for line in order.website_order_line): order.write({'carrier_id': None}, context=context) - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) + self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, [order.id], context=context) return True else: carrier_id = force_carrier_id or order.carrier_id.id - if force_carrier_id or not carrier_id or not carrier_id in self._get_delivery_methods(cr, uid, order, context=context): - self.pool['sale.order']._delivery_unset(cr, SUPERUSER_ID, order, context=context) - carrier_ids = self.pool.get('delivery.carrier').search(cr, uid, [('website_published','=',True)], context=context) - if force_carrier_id: - carrier_ids.insert(0, force_carrier_id) + carrier_ids = self._get_delivery_methods(cr, uid, order, context=context) + if carrier_id not in carrier_ids: + carrier_id = False + else: + carrier_ids.insert(0, carrier_ids.pop(carrier_id)) + if force_carrier_id or not carrier_id or not carrier_id in carrier_ids: for delivery_id in carrier_ids: grid_id = carrier_obj.grid_get(cr, SUPERUSER_ID, [delivery_id], order.partner_shipping_id.id) if grid_id: @@ -81,6 +82,8 @@ class SaleOrder(orm.Model): order.write({'carrier_id': carrier_id}, context=context) if carrier_id: order.delivery_set(context=context) + else: + order._delivery_unset(context=context) return bool(carrier_id) From dc8246eb03b37d2be7bff497f656cd183ba8a5c9 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Fri, 4 Apr 2014 13:23:08 +0200 Subject: [PATCH 082/140] [ADD] sale_layout module allowing to set categories and subtotals on invoice and sale order bzr revid: sle@openerp.com-20140404112308-aopihnefnf55b4er --- addons/account/views/report_invoice.xml | 2 +- addons/sale/views/report_saleorder.xml | 2 +- addons/sale_layout/__init__.py | 1 + addons/sale_layout/__openerp__.py | 44 ++++++ .../data/sale_layout_category_data.xml | 20 +++ addons/sale_layout/models/__init__.py | 1 + addons/sale_layout/models/sale_layout.py | 137 ++++++++++++++++++ .../sale_layout/security/ir.model.access.csv | 5 + .../views/report_invoice_layouted.xml | 65 +++++++++ .../views/report_quotation_layouted.xml | 70 +++++++++ .../views/sale_layout_category_view.xml | 120 +++++++++++++++ .../views/sale_layout_template.xml | 42 ++++++ 12 files changed, 507 insertions(+), 2 deletions(-) create mode 100644 addons/sale_layout/__init__.py create mode 100644 addons/sale_layout/__openerp__.py create mode 100644 addons/sale_layout/data/sale_layout_category_data.xml create mode 100644 addons/sale_layout/models/__init__.py create mode 100644 addons/sale_layout/models/sale_layout.py create mode 100644 addons/sale_layout/security/ir.model.access.csv create mode 100644 addons/sale_layout/views/report_invoice_layouted.xml create mode 100644 addons/sale_layout/views/report_quotation_layouted.xml create mode 100644 addons/sale_layout/views/sale_layout_category_view.xml create mode 100644 addons/sale_layout/views/sale_layout_template.xml diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml index bc0dc5e92a2..437c9726bf3 100644 --- a/addons/account/views/report_invoice.xml +++ b/addons/account/views/report_invoice.xml @@ -54,7 +54,7 @@ Amount - + diff --git a/addons/sale/views/report_saleorder.xml b/addons/sale/views/report_saleorder.xml index c6f237e3ac3..40c8afa045d 100644 --- a/addons/sale/views/report_saleorder.xml +++ b/addons/sale/views/report_saleorder.xml @@ -64,7 +64,7 @@ Price - + diff --git a/addons/sale_layout/__init__.py b/addons/sale_layout/__init__.py new file mode 100644 index 00000000000..bff786c0885 --- /dev/null +++ b/addons/sale_layout/__init__.py @@ -0,0 +1 @@ +import models diff --git a/addons/sale_layout/__openerp__.py b/addons/sale_layout/__openerp__.py new file mode 100644 index 00000000000..b8fcefc6adc --- /dev/null +++ b/addons/sale_layout/__openerp__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# 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 . +# +############################################################################## + +{ + 'name': 'Sale Layout', + 'version': '1.0', + 'sequence': 14, + 'summary': 'Sale Layout, page-break, subtotals, separators, report', + 'description': """ +Manage your sales reports +========================= +With this module you can personnalize the sale order and invoice report with +separators, page-breaks or subtotals. + """, + 'author': 'OpenERP SA', + 'website': 'http://www.openerp.com', + 'depends': ['sale', 'report'], + 'category': 'Sale', + 'data': ['views/sale_layout_category_view.xml', + 'views/report_invoice_layouted.xml', + 'views/report_quotation_layouted.xml', + 'views/sale_layout_template.xml', + 'security/ir.model.access.csv'], + 'demo': ['data/sale_layout_category_data.xml'], + 'installable': True, +} diff --git a/addons/sale_layout/data/sale_layout_category_data.xml b/addons/sale_layout/data/sale_layout_category_data.xml new file mode 100644 index 00000000000..858654e427f --- /dev/null +++ b/addons/sale_layout/data/sale_layout_category_data.xml @@ -0,0 +1,20 @@ + + + + + Services + + + + 1 + + + + Material + + + + 10 + + + diff --git a/addons/sale_layout/models/__init__.py b/addons/sale_layout/models/__init__.py new file mode 100644 index 00000000000..9e9b002e402 --- /dev/null +++ b/addons/sale_layout/models/__init__.py @@ -0,0 +1 @@ +import sale_layout diff --git a/addons/sale_layout/models/sale_layout.py b/addons/sale_layout/models/sale_layout.py new file mode 100644 index 00000000000..d6e7e435b99 --- /dev/null +++ b/addons/sale_layout/models/sale_layout.py @@ -0,0 +1,137 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2014-Today OpenERP SA (). +# +# 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 . +# +############################################################################## + +from openerp.osv import osv, fields +from itertools import groupby + + +def grouplines(self, ordered_lines, sortkey): + """Return lines from a specified invoice or sale order grouped by category""" + grouped_lines = [] + for key, valuesiter in groupby(ordered_lines, sortkey): + group = {} + group['category'] = key + group['lines'] = list(v for v in valuesiter) + + if 'subtotal' in key and key.subtotal is True: + group['subtotal'] = sum(line.price_subtotal for line in group['lines']) + grouped_lines.append(group) + + return grouped_lines + + +class SaleLayoutCategory(osv.Model): + _name = 'sale_layout.category' + _order = 'sequence' + _columns = { + 'name': fields.char('Name', required=True), + 'sequence': fields.integer('Sequence', required=True), + 'subtotal': fields.boolean('Add subtotal'), + 'separator': fields.boolean('Add separator'), + 'pagebreak': fields.boolean('Add pagebreak') + } + + _defaults = { + 'subtotal': True, + 'separator': True, + 'pagebreak': False, + 'sequence': 10 + } + + # We want to forbid edit of a category if it is already linked to a report. + def _check(self, cr, uid, ids): + for cat in self.browse(cr, uid, ids): + invoice_obj = self.pool.get('account.invoice.line') + sale_obj = self.pool.get('sale.order.line') + ids = invoice_obj.search(cr, uid, [('sale_layout_cat_id', '=', cat.id)]) + ids += sale_obj.search(cr, uid, [('sale_layout_cat_id', '=', cat.id)]) + + if len(ids) > 0: + return False + + return True + + _constraints = [( + _check, + 'This category could not be modified nor deleted because it is still used in an invoice or' + ' a sale report.', ['name'] + )] + + +class AccountInvoice(osv.Model): + _inherit = 'account.invoice' + + def sale_layout_lines(self, cr, uid, ids, context, invoice_id, *args, **kwargs): + """ + Returns invoice lines from a specified invoice ordered by + sale_layout_category sequence. Used in sale_layout module. + + :Parameters: + -'invoice_id' (int): specify the concerned invoice. + """ + ordered_lines = self.browse(cr, uid, invoice_id, context=context).invoice_line + # We chose to group first by category model and, if not present, by invoice name + sortkey = lambda x: x.sale_layout_cat_id if x.sale_layout_cat_id else '' + + return grouplines(self, ordered_lines, sortkey) + + +class AccountInvoiceLine(osv.Model): + _inherit = 'account.invoice.line' + _columns = { + 'sale_layout_cat_id': fields.many2one('sale_layout.category', + 'Layout Category'), + 'categ_sequence': fields.related('sale_layout_cat_id', + 'sequence', type='integer', + string='Layout Sequence', store=True) + # Store is intentionally set in order to keep the "historic" order. + } + _order = 'invoice_id, categ_sequence, sequence, id' + + +class SaleOrder(osv.Model): + _inherit = 'sale.order' + + def sale_layout_lines(self, cr, uid, ids, context, order_id, *args, **kwargs): + """ + Returns order lines from a specified sale ordered by + sale_layout_category sequence. Used in sale_layout module. + + :Parameters: + -'order_id' (int): specify the concerned sale order. + """ + ordered_lines = self.browse(cr, uid, order_id, context=context).order_line + sortkey = lambda x: x.sale_layout_cat_id if x.sale_layout_cat_id else '' + + return grouplines(self, ordered_lines, sortkey) + + +class SaleOrderLine(osv.Model): + _inherit = 'sale.order.line' + _columns = { + 'sale_layout_cat_id': fields.many2one('sale_layout.category', + 'Layout Category'), + 'categ_sequence': fields.related('sale_layout_cat_id', + 'sequence', type='integer', + string='Layout Sequence', store=True) + # Store is intentionally set in order to keep the "historic" order. + } + _order = 'order_id, categ_sequence, sequence, id' diff --git a/addons/sale_layout/security/ir.model.access.csv b/addons/sale_layout/security/ir.model.access.csv new file mode 100644 index 00000000000..119fce977d1 --- /dev/null +++ b/addons/sale_layout/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +report_layout_category_1,report_layout_category_1,model_sale_layout_category,base.group_sale_manager,1,1,1,1 +report_layout_category_2,report_layout_category_2,model_sale_layout_category,account.group_account_manager,1,1,1,1 +report_layout_category_3,report_layout_category_3,model_sale_layout_category,base.group_sale_salesman,1,1,1,O +report_layout_category_4,report_layout_category_4,model_sale_layout_category,base.group_sale_salesman_all_leads,1,1,1,0 diff --git a/addons/sale_layout/views/report_invoice_layouted.xml b/addons/sale_layout/views/report_invoice_layouted.xml new file mode 100644 index 00000000000..4c0b1929484 --- /dev/null +++ b/addons/sale_layout/views/report_invoice_layouted.xml @@ -0,0 +1,65 @@ + + + + + + diff --git a/addons/sale_layout/views/report_quotation_layouted.xml b/addons/sale_layout/views/report_quotation_layouted.xml new file mode 100644 index 00000000000..ad04e271e7d --- /dev/null +++ b/addons/sale_layout/views/report_quotation_layouted.xml @@ -0,0 +1,70 @@ + + + + + + diff --git a/addons/sale_layout/views/sale_layout_category_view.xml b/addons/sale_layout/views/sale_layout_category_view.xml new file mode 100644 index 00000000000..08f892c127e --- /dev/null +++ b/addons/sale_layout/views/sale_layout_category_view.xml @@ -0,0 +1,120 @@ + + + + + + sale.order.form.inherit_1 + sale.order + + + + + + + + + + + + sale.order.line.form.inherit_2 + sale.order + + + + + + + + + + + + + account.invoice.form.inherit_1 + account.invoice + + + + + + + + + + + + account.invoice.line.form.inherit_2 + account.invoice.line + + + + + + + + + + + + + report.configuration.form.view + sale_layout.category + +
    + + + + + + + +
    +
    +
    + + + report.configuration.form.view + sale_layout.category + + + + + + + + + + + + + report.configuration.search.view + sale_layout.category + + + + + + + + + + + + + + Report Configuration + sale_layout.category + form + tree,form + + + +
    +
    diff --git a/addons/sale_layout/views/sale_layout_template.xml b/addons/sale_layout/views/sale_layout_template.xml new file mode 100644 index 00000000000..7b39ea4c632 --- /dev/null +++ b/addons/sale_layout/views/sale_layout_template.xml @@ -0,0 +1,42 @@ + + + + + + + + + From eb41be40bfcc46eabaae6435b5703e9f23382f81 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 4 Apr 2014 13:42:16 +0200 Subject: [PATCH 083/140] [FIX] fixes an incorrect call to read_group (the groupby argument should be a list of groupbys and should not be a list with an empty string (addon gamification) bzr revid: ged@openerp.com-20140404114216-35wqvkegnpnn7mil --- addons/gamification/models/goal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index 8e79c43c8a6..925b05de5ab 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -279,7 +279,7 @@ class gamification_goal(osv.Model): if goal.definition_id.computation_mode == 'sum': field_name = goal.definition_id.field_id.name - res = obj.read_group(cr, uid, domain, [field_name], [''], context=context) + res = obj.read_group(cr, uid, domain, [field_name], [field_name], context=context) new_value = res and res[0][field_name] or 0.0 else: # computation mode = count From 870fed2bb9a320f3b859565bb7918f32361dced4 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 4 Apr 2014 13:45:43 +0200 Subject: [PATCH 084/140] [IMP] puts the closure 'process_groupby' in read_group in a separate method. (orm.py) bzr revid: ged@openerp.com-20140404114543-nw7yx87h1dbkbhtf --- openerp/osv/orm.py | 57 ++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index d8862591ed8..5d09e3851af 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2233,6 +2233,31 @@ class BaseModel(object): self._name, order_part) return groupby_terms, orderby_terms + def _read_group_process_groupby(self, gb, fget, query): + print "==="*20 + print gb + split = gb.split(':') + field_type = fget[split[0]]['type'] + gb_function = split[1] if len(split) == 2 else None + temporal = field_type in ('date', 'datetime') + tz_convert = field_type == 'datetime' and context.get('tz') in pytz.all_timezones + qualified_field = self._inherits_join_calc(split[0], query) + if temporal: + if tz_convert: + qualified_field = "timezone('%s', timezone('UTC',%s))" % (context.get('tz', 'UTC'), qualified_field) + qualified_field = "date_trunc('%s', %s)" % (gb_function or 'month', qualified_field) + if field_type == 'boolean': + qualified_field = "coalesce(%s,false)" % qualified_field + return { + 'field': split[0], + 'groupby': gb, + 'type': field_type, + 'display_format': display_formats[gb_function or 'month'] if temporal else None, + 'interval': time_intervals[gb_function or 'month'] if temporal else None, + 'tz_convert': tz_convert, + 'qualified_field': qualified_field + } + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context={}, orderby=False, lazy=True): """ Get the list of records in list view grouped by the given ``groupby`` fields @@ -2286,30 +2311,9 @@ class BaseModel(object): 'year': dateutil.relativedelta.relativedelta(years=1) } - def process_groupby (gb): - split = gb.split(':') - field_type = fget[split[0]]['type'] - gb_function = split[1] if len(split) == 2 else None - temporal = field_type in ('date', 'datetime') - tz_convert = field_type == 'datetime' and context.get('tz') in pytz.all_timezones - qualified_field = self._inherits_join_calc(split[0], query) - if temporal: - if tz_convert: - qualified_field = "timezone('%s', timezone('UTC',%s))" % (context.get('tz', 'UTC'), qualified_field) - qualified_field = "date_trunc('%s', %s)" % (gb_function or 'month', qualified_field) - if field_type == 'boolean': - qualified_field = "coalesce(%s,false)" % qualified_field - return { - 'field': split[0], - 'groupby': gb, - 'type': field_type, - 'display_format': display_formats[gb_function or 'month'] if temporal else None, - 'interval': time_intervals[gb_function or 'month'] if temporal else None, - 'tz_convert': tz_convert, - 'qualified_field': qualified_field - } - - annotated_groupbys = map(process_groupby, groupby[:1] if lazy else groupby) + groupby_list = groupby[:1] if lazy else groupby + annotated_groupbys = [self._read_group_process_groupby(gb, fget, query) + for gb in groupby_list] groupby_fields = [g['field'] for g in annotated_groupbys] order = orderby or ','.join([g['groupby'] for g in annotated_groupbys]) groupby_dict = {gb['groupby']: gb for gb in annotated_groupbys} @@ -2339,7 +2343,10 @@ class BaseModel(object): groupby_terms, orderby_terms = self._read_group_prepare(order, aggregated_fields, annotated_groupbys, query, fget) from_clause, where_clause, where_clause_params = query.get_sql() - count_field = groupby_fields[0] if lazy and (len(groupby_fields) >= 2 or not context.get('group_by_no_leaf')) else '_' + if lazy and (len(groupby_fields) >= 2 or not context.get('group_by_no_leaf')): + count_field = groupby_fields[0] if len(groupby_fields) >= 1 else '_' + else: + count_field = '_' prefix_terms = lambda prefix, terms: (prefix + " " + ",".join(terms)) if terms else '' prefix_term = lambda prefix, term: ('%s %s' % (prefix, term)) if term else '' From 91a78667ba482e7cb248eb85e7a057e2e4100268 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Fri, 4 Apr 2014 14:11:28 +0200 Subject: [PATCH 085/140] [FIX] Report: insert formatLang in the rendering environment if not present; Sale_layout: use formatLang on the subtotal bzr revid: sle@openerp.com-20140404121128-puvr1zs244lit5m2 --- addons/report/models/report.py | 11 +++++++++++ addons/sale_layout/views/sale_layout_template.xml | 6 +++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/addons/report/models/report.py b/addons/report/models/report.py index 723c098ccb2..018fc0b57e2 100644 --- a/addons/report/models/report.py +++ b/addons/report/models/report.py @@ -23,6 +23,7 @@ from openerp.osv import osv from openerp.tools import config from openerp.tools.translate import _ from openerp.addons.web.http import request +from openerp.report.formatter import Formatter import os import time @@ -137,6 +138,16 @@ class Report(osv.Model): website = None if request and hasattr(request, 'website'): website = request.website + + # formatLang method + if not values.get('formatLang'): + formatter = Formatter(cr, uid, self.pool, lang=user.lang) + values.update({ + 'formatLang': formatter.formatLang, + 'digits_fmt': formatter.digits_fmt, + 'get_digits': formatter.get_digits, + }) + values.update({ 'time': time, 'render_doc': render_doc, diff --git a/addons/sale_layout/views/sale_layout_template.xml b/addons/sale_layout/views/sale_layout_template.xml index 7b39ea4c632..c8c83bf2d29 100644 --- a/addons/sale_layout/views/sale_layout_template.xml +++ b/addons/sale_layout/views/sale_layout_template.xml @@ -5,7 +5,7 @@ - + > @@ -22,7 +22,7 @@ Subtotal: - + @@ -31,7 +31,7 @@ - + *** From bae4c6ce408c3cd9cb7491b94e20a0082eb60f40 Mon Sep 17 00:00:00 2001 From: "Foram Katharotiya (OpenERP)" Date: Fri, 4 Apr 2014 14:30:03 +0200 Subject: [PATCH 086/140] [IMP] bring back the tests for MRP - backported from little after v7.0 in the trunk lp bug: https://launchpad.net/bugs/1182515 fixed bzr revid: ls@numerigraphe.com-20140404123003-cdt5zz1vmupbgd1j --- addons/mrp/__openerp__.py | 9 ++++----- addons/mrp/security/ir.model.access.csv | 1 + addons/mrp/security/mrp_security.xml | 1 + addons/mrp/test/cancel_order.yml | 5 +++++ addons/mrp/test/mrp_users.yml | 20 ++++++++++++++++++++ addons/mrp/test/order_demo.yml | 5 +++++ addons/mrp/test/order_process.yml | 5 +++++ 7 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 addons/mrp/test/mrp_users.yml diff --git a/addons/mrp/__openerp__.py b/addons/mrp/__openerp__.py index d33fa4d2622..3157eee57bc 100644 --- a/addons/mrp/__openerp__.py +++ b/addons/mrp/__openerp__.py @@ -74,13 +74,12 @@ Dashboard / Reports for MRP will include: 'res_config_view.xml', ], 'demo': ['mrp_demo.xml'], - #TODO: This yml tests are needed to be completely reviewed again because the product wood panel is removed in product demo as it does not suit for new demo context of computer and consultant company - # so the ymls are too complex to change at this stage 'test': [ 'test/bom_with_service_type_product.yml', -# 'test/order_demo.yml', -# 'test/order_process.yml', -# 'test/cancel_order.yml', + 'test/mrp_users.yml', + 'test/order_demo.yml', + 'test/order_process.yml', + 'test/cancel_order.yml', ], 'installable': True, 'application': True, diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index 7a94b1a660c..2d0a478c33d 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_account_analytic_line_user,account.analytic.line,account.model_account_analytic_line,group_mrp_user,1,1,1,0 access_mrp_workcenter,mrp.workcenter,model_mrp_workcenter,mrp.group_mrp_user,1,0,0,0 access_mrp_routing,mrp.routing,model_mrp_routing,mrp.group_mrp_user,1,0,0,0 access_mrp_routing_workcenter,mrp.routing.workcenter,model_mrp_routing_workcenter,mrp.group_mrp_user,1,0,0,0 diff --git a/addons/mrp/security/mrp_security.xml b/addons/mrp/security/mrp_security.xml index 35aae42b53d..9e5dc919720 100644 --- a/addons/mrp/security/mrp_security.xml +++ b/addons/mrp/security/mrp_security.xml @@ -4,6 +4,7 @@ User + diff --git a/addons/mrp/test/cancel_order.yml b/addons/mrp/test/cancel_order.yml index 9e197156b15..2f721b6c653 100644 --- a/addons/mrp/test/cancel_order.yml +++ b/addons/mrp/test/cancel_order.yml @@ -1,3 +1,8 @@ +- + MRP user can cancelled Production Order, so let's check data with giving the access rights of user. +- + !context + uid: 'res_users_mrp_user' - I first confirm order for PC Assemble SC349. - diff --git a/addons/mrp/test/mrp_users.yml b/addons/mrp/test/mrp_users.yml new file mode 100644 index 00000000000..d18cc51e8e6 --- /dev/null +++ b/addons/mrp/test/mrp_users.yml @@ -0,0 +1,20 @@ +- + Create a user as 'MRP Manager' +- + !record {model: res.users, id: res_users_mrp_manager}: + company_id: base.main_company + name: MRP Manager + login: mam + password: mam + groups_id: + - mrp.group_mrp_manager +- + Create a user as 'MRP User' +- + !record {model: res.users, id: res_users_mrp_user}: + company_id: base.main_company + name: MRP User + login: mau + password: mau + groups_id: + - mrp.group_mrp_user diff --git a/addons/mrp/test/order_demo.yml b/addons/mrp/test/order_demo.yml index ee21fee96df..0e4914390fb 100644 --- a/addons/mrp/test/order_demo.yml +++ b/addons/mrp/test/order_demo.yml @@ -1,3 +1,8 @@ +- + MRP user can create Production Order, so let's check data with giving the access rights of user. +- + !context + uid: 'res_users_mrp_user' - I create Production Order of PC Assemble SC349 to produce 5.0 Unit. - diff --git a/addons/mrp/test/order_process.yml b/addons/mrp/test/order_process.yml index e672517c5a0..32eee92bac0 100644 --- a/addons/mrp/test/order_process.yml +++ b/addons/mrp/test/order_process.yml @@ -1,3 +1,8 @@ +- + MRP user can doing all process related to Production Order, so let's check data with giving the access rights of user. +- + !context + uid: 'res_users_mrp_user' - I compute the production order. - From af64d6cc970c1ac64868e05839e4461ea174ab1f Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 4 Apr 2014 14:36:55 +0200 Subject: [PATCH 087/140] [FIX] changes made at merge time into the trunk - remove offending test bzr revid: ls@numerigraphe.com-20140404123655-9ihrychuho6n6qt2 --- addons/mrp/test/mrp_users.yml | 13 +++++++- addons/mrp/test/order_process.yml | 52 ++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/addons/mrp/test/mrp_users.yml b/addons/mrp/test/mrp_users.yml index d18cc51e8e6..05c4889cf28 100644 --- a/addons/mrp/test/mrp_users.yml +++ b/addons/mrp/test/mrp_users.yml @@ -6,8 +6,14 @@ name: MRP Manager login: mam password: mam + email: mrp_manager@yourcompany.com +- + I added groups for MRP Manager. +- + !record {model: res.users, id: res_users_mrp_manager}: groups_id: - mrp.group_mrp_manager + - account.group_account_user - Create a user as 'MRP User' - @@ -16,5 +22,10 @@ name: MRP User login: mau password: mau + email: mrp_user@yourcompany.com +- + I added groups for MRP User. +- + !record {model: res.users, id: res_users_mrp_user}: groups_id: - - mrp.group_mrp_user + - mrp.group_mrp_user \ No newline at end of file diff --git a/addons/mrp/test/order_process.yml b/addons/mrp/test/order_process.yml index 32eee92bac0..c4050208570 100644 --- a/addons/mrp/test/order_process.yml +++ b/addons/mrp/test/order_process.yml @@ -1,5 +1,5 @@ - - MRP user can doing all process related to Production Order, so let's check data with giving the access rights of user. + MRP user can doing all process related to Production Order, so let's check data with giving the access rights of user. - !context uid: 'res_users_mrp_user' @@ -19,7 +19,7 @@ Now I check workcenter lines. - !python {model: mrp.production}: | - from tools import float_compare + from openerp.tools import float_compare def assert_equals(value1, value2, msg, float_compare=float_compare): assert float_compare(value1, value2, precision_digits=2) == 0, msg order = self.browse(cr, uid, ref("mrp_production_test1"), context=context) @@ -28,6 +28,7 @@ I confirm the Production Order. - !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_test1} + - I check details of Produce Move of Production Order to trace Final Product. - @@ -63,6 +64,16 @@ assert move_line.product_uos.id == order_line.product_uos.id, "UOS is not correspond in 'To consume line'." assert move_line.location_id.id == routing_loc or order.location_src_id.id, "Source location is not correspond in 'To consume line'." assert move_line.location_dest_id.id == source_location_id, "Destination Location is not correspond in 'To consume line'." +- + I consume raw materials and put one material in scrap location due to waste it. +- + !python {model: mrp.production}: | + scrap_location_ids = self.pool.get('stock.location').search(cr, uid, [('scrap_location','=',True)]) + scrap_location_id = scrap_location_ids[0] + order = self.browse(cr, uid, ref("mrp_production_test1")) + for move in order.move_lines: + if move.product_id.id == ref("product.product_product_6"): + move.action_scrap(5.0, scrap_location_id) - I check details of an Internal Shipment after confirmed production order to bring components in Raw Materials Location. - @@ -99,6 +110,11 @@ procurement_ids = procurement.search(cr, uid, [('move_id','=',move_line.id)]) assert procurement_ids, "Procurement should be created for shipment line of raw materials." shipment_procurement = procurement.browse(cr, uid, procurement_ids[0], context=context) + # procurement state should be `confirmed` at this stage, except if mrp_jit is installed, in which + # case it could already be in `running` or `exception` state (not enough stock) + expected_states = ('confirmed', 'running', 'exception') + assert shipment_procurement.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % \ + (shipment_procurement.state, shipment_procurement.product_id.name, expected_states) assert shipment_procurement.date_planned == date_planned, "Planned date is not correspond in procurement." assert shipment_procurement.product_id.id == order_line.product_id.id, "Product is not correspond in procurement." assert shipment_procurement.product_qty == order_line.product_qty, "Qty is not correspond in procurement." @@ -155,17 +171,7 @@ order = self.browse(cr, uid, ref("mrp_production_test1")) assert order.state == 'in_production', 'Production order should be in production State.' - - I consume raw materials and put one material in scrap location due to waste it. -- - !python {model: mrp.production}: | - scrap_location_ids = self.pool.get('stock.location').search(cr, uid, [('scrap_location','=',True)]) - scrap_location_id = scrap_location_ids[0] - order = self.browse(cr, uid, ref("mrp_production_test1")) - for move in order.move_lines: move.action_consume(move.product_qty) - if move.product_id.id == ref("product.product_product_6"): - move.action_scrap(5.0, scrap_location_id) -- I produce product. - !python {model: mrp.product.produce}: | @@ -183,7 +189,10 @@ order = self.browse(cr, uid, ref("mrp_production_test1")) assert order.state == 'done', "Production order should be closed." - - I check Total Costs at End of Production. + I check Total Costs at End of Production as a manager. +- + !context + uid: 'res_users_mrp_manager' - !python {model: mrp.production}: | order = self.browse(cr, uid, ref("mrp_production_test1")) @@ -217,19 +226,26 @@ assert line.product_uom_id.id == wc.product_id.uom_id.id, "UOM is not correspond." - I print a "BOM Structure". +- + !context + uid: 'res_users_mrp_user' - !python {model: mrp.production}: | - import netsvc, tools, os + import os + import openerp.report + from openerp import tools order = self.browse(cr, uid, ref("mrp_production_test1")) - (data, format) = netsvc.LocalService('report.bom.structure').create(cr, uid, [order.bom_id.id], {}, {}) + data, format = openerp.report.render_report(cr, uid, [order.bom_id.id], 'bom.structure', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'mrp-bom_structure_report.'+format), 'wb+').write(data) - I print "Production Order". - !python {model: mrp.production}: | - import netsvc, tools, os - (data, format) = netsvc.LocalService('report.mrp.production.order').create(cr, uid, [ref("mrp_production_test1")], {}, {}) + import os + import openerp.report + from openerp import tools + data, format = openerp.report.render_report(cr, uid, [ref("mrp_production_test1")], 'mrp.production.order', {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'mrp-production_order_report.'+format), 'wb+').write(data) - @@ -239,6 +255,6 @@ ctx = context.copy() ctx.update({'model': 'mrp.workcenter','active_ids': [ref('mrp_workcenter_0'),ref('mrp_workcenter_1')]}) data_dict = {'time_unit': 'day', 'measure_unit': 'hours'} - from tools import test_reports + from openerp.tools import test_reports test_reports.try_report_action(cr, uid, 'action_mrp_workcenter_load_wizard',wiz_data=data_dict, context=ctx, our_module='mrp') From a386aea7d3790f15337fc4a55ea14f635bd4ab5e Mon Sep 17 00:00:00 2001 From: Lionel Sausin Date: Fri, 4 Apr 2014 14:40:36 +0200 Subject: [PATCH 088/140] [FIX] revert to v7 report API bzr revid: ls@numerigraphe.com-20140404124036-1vt0fkakfllj1qax --- addons/mrp/test/order_process.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/addons/mrp/test/order_process.yml b/addons/mrp/test/order_process.yml index c4050208570..bbafe5b6b27 100644 --- a/addons/mrp/test/order_process.yml +++ b/addons/mrp/test/order_process.yml @@ -231,21 +231,17 @@ uid: 'res_users_mrp_user' - !python {model: mrp.production}: | - import os - import openerp.report - from openerp import tools + import netsvc, tools, os order = self.browse(cr, uid, ref("mrp_production_test1")) - data, format = openerp.report.render_report(cr, uid, [order.bom_id.id], 'bom.structure', {}, {}) + (data, format) = netsvc.LocalService('report.bom.structure').create(cr, uid, [order.bom_id.id], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'mrp-bom_structure_report.'+format), 'wb+').write(data) - I print "Production Order". - !python {model: mrp.production}: | - import os - import openerp.report - from openerp import tools - data, format = openerp.report.render_report(cr, uid, [ref("mrp_production_test1")], 'mrp.production.order', {}, {}) + import netsvc, tools, os + (data, format) = netsvc.LocalService('report.mrp.production.order').create(cr, uid, [ref("mrp_production_test1")], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'mrp-production_order_report.'+format), 'wb+').write(data) - @@ -255,6 +251,6 @@ ctx = context.copy() ctx.update({'model': 'mrp.workcenter','active_ids': [ref('mrp_workcenter_0'),ref('mrp_workcenter_1')]}) data_dict = {'time_unit': 'day', 'measure_unit': 'hours'} - from openerp.tools import test_reports + from tools import test_reports test_reports.try_report_action(cr, uid, 'action_mrp_workcenter_load_wizard',wiz_data=data_dict, context=ctx, our_module='mrp') From 39e69876c6109a110f61335ea20fb2ea6d26d475 Mon Sep 17 00:00:00 2001 From: Gery Debongnie Date: Fri, 4 Apr 2014 14:42:32 +0200 Subject: [PATCH 089/140] [IMP] moves some internal function in read_group to become class methods and slightly reorganize them (orm.py) bzr revid: ged@openerp.com-20140404124232-dmyxuv1qf5kperet --- openerp/osv/orm.py | 132 ++++++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 62 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 5d09e3851af..52fec2675a7 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2234,8 +2234,6 @@ class BaseModel(object): return groupby_terms, orderby_terms def _read_group_process_groupby(self, gb, fget, query): - print "==="*20 - print gb split = gb.split(':') field_type = fget[split[0]]['type'] gb_function = split[1] if len(split) == 2 else None @@ -2243,6 +2241,20 @@ class BaseModel(object): tz_convert = field_type == 'datetime' and context.get('tz') in pytz.all_timezones qualified_field = self._inherits_join_calc(split[0], query) if temporal: + display_formats = { + 'day': 'dd MMM YYYY', + 'week': "'W'w YYYY", + 'month': 'MMMM YYYY', + 'quarter': 'QQQ YYYY', + 'year': 'YYYY' + } + time_intervals = { + 'day': dateutil.relativedelta.relativedelta(months=3), + 'week': datetime.timedelta(days=7), + 'month': dateutil.relativedelta.relativedelta(months=1), + 'quarter': dateutil.relativedelta.relativedelta(months=3), + 'year': dateutil.relativedelta.relativedelta(years=1) + } if tz_convert: qualified_field = "timezone('%s', timezone('UTC',%s))" % (context.get('tz', 'UTC'), qualified_field) qualified_field = "date_trunc('%s', %s)" % (gb_function or 'month', qualified_field) @@ -2258,6 +2270,58 @@ class BaseModel(object): 'qualified_field': qualified_field } + def _read_group_prepare_data(self, key, value, groupby_dict): + """ + Helper method to sanitize the data received by read_group. The None + values are converted to False, and the date/datetime are formatted, + and corrected according to the timezones. + """ + value = False if value is None else value + gb = groupby_dict.get(key) + if gb and gb['type'] in ('date', 'datetime') and value: + if isinstance(value, basestring): + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + value = datetime.datetime.strptime(value, dt_format) + if gb['tz_convert']: + value = pytz.timezone(context['tz']).localize(value) + return value + + def _read_group_get_domain(self, groupby, value): + """ + Helper method to construct the domain corresponding to a groupby and + a given value. This is mostly relevant for date/datetime. + """ + if groupby['type'] in ('date', 'datetime') and value: + dt_format = DEFAULT_SERVER_DATETIME_FORMAT if groupby['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT + domain_dt_begin = value + domain_dt_end = value + groupby['interval'] + if groupby['tz_convert']: + domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) + domain_dt_end = domain_dt_end.astimezone(pytz.utc) + return [(groupby['field'], '>=', domain_dt_begin.strftime(dt_format)), + (groupby['field'], '<', domain_dt_end.strftime(dt_format))] + if groupby['type'] == 'many2one' and value: + value = value[0] + return [(groupby['field'], '=', value)] + + def _read_group_format_result(self, data, annotated_groupbys, groupby, groupby_dict, domain, context): + """ + Helper method to format the data contained in the dictianary data by + adding the domain corresponding to its values, the groupbys in the + context and by properly formatting the date/datetime values. + """ + domain_group = [dom for gb in annotated_groupbys for dom in self._read_group_get_domain(gb, data[gb['groupby']])] + result = { '__domain': domain_group + domain } + if len(groupby) - len(annotated_groupbys) >= 1: + result['__context'] = { 'group_by': groupby[len(annotated_groupbys):]} + result.update(data) + for k,v in result.iteritems(): + gb = groupby_dict.get(k) + if gb and gb['type'] in ('date', 'datetime') and v: + result[k] = babel.dates.format_date(v, format=gb['display_format'], locale=context.get('lang', 'en_US')) + del result['id'] + return result + def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context={}, orderby=False, lazy=True): """ Get the list of records in list view grouped by the given ``groupby`` fields @@ -2296,21 +2360,6 @@ class BaseModel(object): fields = fields or self._columns.keys() fget = self.fields_get(cr, uid, fields) groupby = [groupby] if isinstance(groupby, basestring) else groupby - display_formats = { - 'day': 'dd MMM YYYY', - 'week': "'W'w YYYY", - 'month': 'MMMM YYYY', - 'quarter': 'QQQ YYYY', - 'year': 'YYYY' - } - time_intervals = { - 'day': dateutil.relativedelta.relativedelta(months=3), - 'week': datetime.timedelta(days=7), - 'month': dateutil.relativedelta.relativedelta(months=1), - 'quarter': dateutil.relativedelta.relativedelta(months=3), - 'year': dateutil.relativedelta.relativedelta(years=1) - } - groupby_list = groupby[:1] if lazy else groupby annotated_groupbys = [self._read_group_process_groupby(gb, fget, query) for gb in groupby_list] @@ -2371,22 +2420,10 @@ class BaseModel(object): 'offset': prefix_term('OFFSET', int(offset) if limit else None), } cr.execute(query, where_clause_params) + fetched_data = cr.dictfetchall() if not groupby_fields: - return {r.pop('id'): r for r in cr.dictfetchall() } - - def prepare_data(key, value): - value = False if value is None else value - gb = groupby_dict.get(key) - if gb and gb['type'] in ('date', 'datetime') and value: - if isinstance(value, basestring): - dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT - value = datetime.datetime.strptime(value, dt_format) - if gb['tz_convert']: - value = pytz.timezone(context['tz']).localize(value) - return value - - fetched_data = cr.dictfetchall() + return {r.pop('id'): r for r in fetched_data} many2onefields = [gb['field'] for gb in annotated_groupbys if gb['type'] == 'many2one'] if many2onefields: @@ -2396,37 +2433,8 @@ class BaseModel(object): for d in fetched_data: d.update(data_dict[d['id']]) - data = map(lambda r: {k: prepare_data(k,v) for k,v in r.iteritems()}, fetched_data) - - def get_domain(gb, value): - if gb['type'] in ('date', 'datetime') and value: - dt_format = DEFAULT_SERVER_DATETIME_FORMAT if gb['type'] == 'datetime' else DEFAULT_SERVER_DATE_FORMAT - domain_dt_begin = value - domain_dt_end = value + gb['interval'] - if gb['tz_convert']: - domain_dt_begin = domain_dt_begin.astimezone(pytz.utc) - domain_dt_end = domain_dt_end.astimezone(pytz.utc) - return [(gb['field'], '>=', domain_dt_begin.strftime(dt_format)), - (gb['field'], '<', domain_dt_end.strftime(dt_format))] - if gb['type'] == 'many2one' and value: - value = value[0] - return [(gb['field'], '=', value)] - - def format_result (fromquery): - domain_group = [dom for gb in annotated_groupbys for dom in get_domain(gb, fromquery[gb['groupby']])] - result = { '__domain': domain_group + domain } - if len(groupby) - len(annotated_groupbys) >= 1: - result['__context'] = { 'group_by': groupby[len(annotated_groupbys):]} - result.update(fromquery) - for k,v in result.iteritems(): - gb = groupby_dict.get(k) - if gb and gb['type'] in ('date', 'datetime') and v: - result[k] = babel.dates.format_date(v, format=gb['display_format'], locale=context.get('lang', 'en_US')) - del result['id'] - return result - - result = map(format_result, data) - + data = map(lambda r: {k: self._read_group_prepare_data(k,v, groupby_dict) for k,v in r.iteritems()}, fetched_data) + result = [self._read_group_format_result(d, annotated_groupbys, groupby, groupby_dict, domain, context) for d in data] if lazy and groupby_fields[0] in self._group_by_full: # Right now, read_group only fill results in lazy mode (by default). # If you need to have the empty groups in 'eager' mode, then the From 1adc0b785a2e1d6020ecc084eb443096eddf58a9 Mon Sep 17 00:00:00 2001 From: "Foram Katharotiya (OpenERP)" Date: Fri, 4 Apr 2014 14:45:18 +0200 Subject: [PATCH 090/140] [IMP] bring back the tests for mrp_operations - backported from little after v7.0 in the trunk lp bug: https://launchpad.net/bugs/1182515 fixed bzr revid: ls@numerigraphe.com-20140404124518-jv77xw4z0ouoaqlz --- addons/mrp_operations/__openerp__.py | 2 +- .../test/workcenter_operations.yml | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/addons/mrp_operations/__openerp__.py b/addons/mrp_operations/__openerp__.py index 7fedb426edd..12d86e0b532 100644 --- a/addons/mrp_operations/__openerp__.py +++ b/addons/mrp_operations/__openerp__.py @@ -70,7 +70,7 @@ So, that we can compare the theoretic delay and real delay. 'mrp_operations_demo.yml' ], 'test': [ -# 'test/workcenter_operations.yml', + 'test/workcenter_operations.yml', ], 'installable': True, 'auto_install': False, diff --git a/addons/mrp_operations/test/workcenter_operations.yml b/addons/mrp_operations/test/workcenter_operations.yml index c1449657967..f402e1cddd4 100644 --- a/addons/mrp_operations/test/workcenter_operations.yml +++ b/addons/mrp_operations/test/workcenter_operations.yml @@ -1,6 +1,24 @@ +- + Create a user as 'MRP User' +- + !record {model: res.users, id: res_mrp_operation_user}: + company_id: base.main_company + name: MRP User + login: maou + password: maou + email: mrp_operation_user@yourcompany.com +- + I added groups for MRP User. +- + !record {model: res.users, id: res_mrp_operation_user}: + groups_id: + - mrp.group_mrp_user - In order to test mrp_operations with OpenERP, I refer created production order of PC Assemble SC349 - with routing - Manual Component's Assembly to test complete production process with respect of workcenter. + with routing - Manual Component's Assembly to test complete production process with respect of workcenter with giving access rights of MRP User. +- + !context + uid: 'res_mrp_operation_user' - I compute the production order. - @@ -106,7 +124,7 @@ I print a Barcode Report of Operation line. - !python {model: mrp_operations.operation.code}: | - import netsvc, tools, os + from openerp import netsvc, tools (data, format) = netsvc.LocalService('report.mrp.code.barcode').create(cr, uid, [ref('mrp_operations.mrp_op_1'),ref('mrp_operations.mrp_op_2'),ref('mrp_operations.mrp_op_3'),ref('mrp_operations.mrp_op_4'),ref('mrp_operations.mrp_op_5')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'mrp_operations-barcode_report.'+format), 'wb+').write(data) @@ -115,7 +133,7 @@ I print Workcenter's Barcode Report. - !python {model: mrp.workcenter}: | - import netsvc, tools, os + from openerp import netsvc, tools (data, format) = netsvc.LocalService('report.mrp.wc.barcode').create(cr, uid, [ref('mrp.mrp_workcenter_0'),ref('mrp.mrp_workcenter_1')], {}, {}) if tools.config['test_report_directory']: file(os.path.join(tools.config['test_report_directory'], 'mrp_operations-workcenter_barcode_report.'+format), 'wb+').write(data) From bf41efa40b20a96578cddd4b0eaa12e481ff1d1f Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Fri, 4 Apr 2014 14:47:24 +0200 Subject: [PATCH 091/140] [FIX] regression on rpc call to check wkhtmltopdf presence/version bzr revid: sle@openerp.com-20140404124724-dves3liepcbmg6rv --- .../report/static/src/js/qwebactionmanager.js | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/addons/report/static/src/js/qwebactionmanager.js b/addons/report/static/src/js/qwebactionmanager.js index 3910cab4dd7..7e55661be86 100644 --- a/addons/report/static/src/js/qwebactionmanager.js +++ b/addons/report/static/src/js/qwebactionmanager.js @@ -1,6 +1,15 @@ openerp.report = function(instance) { var wkhtmltopdf_state; + var trigger_download = function(session, response, c) { + session.get_file({ + url: '/report/download', + data: {data: JSON.stringify(response)}, + complete: openerp.web.unblockUI, + error: c.rpc_error.bind(c) + }); + } + instance.web.ActionManager = instance.web.ActionManager.extend({ ir_actions_report_xml: function(action, options) { var self = this; @@ -37,15 +46,16 @@ openerp.report = function(instance) { report_url += "&context=" + encodeURIComponent(JSON.stringify(action.context)); } + var response = new Array(); + response[0] = report_url; + response[1] = action.report_type; + var c = openerp.webclient.crashmanager; + if (action.report_type == 'qweb-html') { window.open(report_url, '_blank', 'height=900,width=1280'); instance.web.unblockUI(); } else { // Trigger the download of the pdf/controller report - var c = openerp.webclient.crashmanager; - var response = new Array(); - response[0] = report_url; - response[1] = action.report_type; if (action.report_type == 'qweb-pdf') { (wkhtmltopdf_state = wkhtmltopdf_state || openerp.session.rpc('/report/check_wkhtmltopdf')).then(function (presence) { @@ -54,7 +64,8 @@ openerp.report = function(instance) { self.do_notify(_t('Report'), _t('Unable to find Wkhtmltopdf on this \ system. The report will be shown in html.

    \ wkhtmltopdf.org'), true); - window.open(report_url.substring(12), '_blank', 'height=768,width=1024'); + report_url = report_url.substring(12) + window.open('/report/html/' + report_url, '_blank', 'height=768,width=1024'); instance.web.unblockUI(); return; } else { @@ -65,14 +76,12 @@ openerp.report = function(instance) { target="_blank">wkhtmltopdf.org'), true); } } + return trigger_download(self.session, response, c); }); } - self.session.get_file({ - url: '/report/download', - data: {data: JSON.stringify(response)}, - complete: openerp.web.unblockUI, - error: c.rpc_error.bind(c) - }); + else if (action.report_type == 'controller') { + return trigger_download(self.session, response, c); + } } } else { return self._super(action, options); From 5759df7befefc4ca33a779dafa22cef476f88f0f Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Fri, 4 Apr 2014 14:54:50 +0200 Subject: [PATCH 092/140] [FIX] crm_partner_assign: add discussion subtype to interested/disintered messages, so portal users can see it bzr revid: dle@openerp.com-20140404125450-v94rjpuuse9gkibr --- addons/crm_partner_assign/wizard/crm_channel_interested.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/crm_partner_assign/wizard/crm_channel_interested.py b/addons/crm_partner_assign/wizard/crm_channel_interested.py index 87fd5669008..a23de29d766 100644 --- a/addons/crm_partner_assign/wizard/crm_channel_interested.py +++ b/addons/crm_partner_assign/wizard/crm_channel_interested.py @@ -63,7 +63,7 @@ class crm_lead_forward_to_partner(osv.TransientModel): if wizard.comment: message += '

    %s

    ' % wizard.comment for active_id in context.get('active_ids', []): - lead_obj.message_post(cr, uid, active_id, body=message, context=context) + lead_obj.message_post(cr, uid, active_id, body=message, subtype="mail.mt_comment", context=context) if values: lead_obj.write(cr, SUPERUSER_ID, context.get('active_ids', []), values) if wizard.interested: From 0c07efd1944a3b2ddb6747a75759d1aa0ce22a82 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Fri, 4 Apr 2014 15:01:54 +0200 Subject: [PATCH 093/140] [FIX] Remove bootstrap default min-height on an empty row in the header, added a max-height on the header logo bzr revid: sle@openerp.com-20140404130154-utzdx2gqhfl2bp0n --- addons/report/views/layouts.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/report/views/layouts.xml b/addons/report/views/layouts.xml index 721176738cb..21c385b71c9 100644 --- a/addons/report/views/layouts.xml +++ b/addons/report/views/layouts.xml @@ -67,6 +67,9 @@ .table-condensed > thead > tr > th { border-bottom: 1px solid black !important; } + .zero_min_height { + min-height: 0px !important; + }