Remove patches from default branch

Force to change branch before to apply patches
This commit is contained in:
Raimon Esteve 2016-05-30 17:10:04 +02:00
parent 42883e71aa
commit 6e286c100f
49 changed files with 8 additions and 4246 deletions

View File

@ -1,11 +0,0 @@
diff --git a/view/account_payment_type_form_view.xml b/view/account_payment_type_form_view.xml
--- a/trytond/trytond/modules/account_bank/view/account_payment_type_form_view.xml
+++ b/trytond/trytond/modules/account_bank/view/account_payment_type_form_view.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<data>
- <xpath expr="/form/field[@name='company']" position="after">
+ <xpath expr="/form/field[@name='active']" position="after">
<label name="account_bank"/>
<field name="account_bank"/>
<label name="party"/>

View File

@ -1,121 +0,0 @@
diff --git a/view/payment_type_tree.xml b/view/payment_type_tree.xml
--- a/trytond/trytond/modules/account_payment_type/view/payment_type_tree.xml
+++ b/trytond/trytond/modules/account_payment_type/view/payment_type_tree.xml
@@ -2,7 +2,6 @@
<tree string="Payment Type">
<field name="name"/>
<field name="code"/>
- <field name="company"/>
<field name="active"/>
<field name="kind"/>
</tree>
diff --git a/view/payment_type_form.xml b/view/payment_type_form.xml
--- a/trytond/trytond/modules/account_payment_type/view/payment_type_form.xml
+++ b/trytond/trytond/modules/account_payment_type/view/payment_type_form.xml
@@ -4,13 +4,10 @@
<field name="name"/>
<label name="code"/>
<field name="code"/>
+ <label name="kind"/>
+ <field name="kind"/>
<label name="active"/>
<field name="active"/>
- <label name="company"/>
- <field name="company" widget="selection"/>
- <label name="kind"/>
- <field name="kind"/>
- <newline/>
<separator name="note" colspan="4"/>
<field name="note" colspan="4"/>
</form>
diff --git a/tests/test_account_payment_type.py b/tests/test_account_payment_type.py
--- a/trytond/trytond/modules/account_payment_type/tests/test_account_payment_type.py
+++ b/trytond/trytond/modules/account_payment_type/tests/test_account_payment_type.py
@@ -78,12 +78,10 @@
payment_payable, = self.payment_type.create([{
'name': 'Payment Payable',
'kind': 'payable',
- 'company': company.id,
}])
payment_receivable, = self.payment_type.create([{
'name': 'Payment Receivable',
'kind': 'receivable',
- 'company': company.id,
}])
move, = self.move.create([{
'period': period.id,
diff --git a/payment_type.xml b/payment_type.xml
--- a/trytond/trytond/modules/account_payment_type/payment_type.xml
+++ b/trytond/trytond/modules/account_payment_type/payment_type.xml
@@ -54,14 +54,5 @@
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
-
- <record model="ir.rule.group" id="rule_group_payment_type">
- <field name="model" search="[('model', '=', 'account.payment.type')]"/>
- <field name="global_p" eval="True"/>
- </record>
- <record model="ir.rule" id="rule_payment_type1">
- <field name="domain">[('company', '=', user.company.id if user.company else None)]</field>
- <field name="rule_group" ref="rule_group_payment_type"/>
- </record>
</data>
</tryton>
diff --git a/payment_type.py b/payment_type.py
--- a/trytond/trytond/modules/account_payment_type/payment_type.py
+++ b/trytond/trytond/modules/account_payment_type/payment_type.py
@@ -1,11 +1,10 @@
# This file is part of account_payment_type module for Tryton.
# The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms.
-
from trytond.model import ModelView, ModelSQL, fields
-from trytond.pyson import Eval, If
from trytond.pool import Pool
from trytond.transaction import Transaction
+from trytond import backend
__all__ = ['PaymentType']
@@ -17,11 +16,6 @@
name = fields.Char('Name', required=True, translate=True)
code = fields.Char('Code')
active = fields.Boolean('Active')
- company = fields.Many2One('company.company', 'Company', required=True,
- select=True, readonly=True, domain=[
- ('id', If(Eval('context', {}).contains('company'), '=', '!='),
- Eval('context', {}).get('company', 0)),
- ])
note = fields.Text('Description', translate=True,
help=('Description of the payment type that will be shown in '
'descriptions'))
@@ -32,6 +26,17 @@
help='The kind of payment type.')
@classmethod
+ def __register__(cls, module_name):
+ TableHandler = backend.get('TableHandler')
+ cursor = Transaction().cursor
+ table = TableHandler(cursor, cls, module_name)
+
+ super(PaymentType, cls).__register__(module_name)
+
+ # Migration from 3.4: drop required on company
+ table.not_null_action('company', action='remove')
+
+ @classmethod
def __setup__(cls):
super(PaymentType, cls).__setup__()
cls._check_modify_fields = set(['kind'])
@@ -49,10 +54,6 @@
def default_active():
return True
- @staticmethod
- def default_company():
- return Transaction().context.get('company')
-
def get_rec_name(self, name):
if self.code:
return '[' + self.code + '] ' + self.name

View File

@ -1,115 +0,0 @@
diff -r 5d7c2958b920 move.py
--- a/trytond/trytond/modules/stock/move.py Mon Nov 23 17:59:15 2015 +0100
+++ b/trytond/trytond/modules/stock/move.py Mon Nov 23 18:09:01 2015 +0100
@@ -607,9 +607,15 @@
@Workflow.transition('assigned')
def assign(cls, moves):
cls.check_origin(moves)
+
+ to_write = []
for move in moves:
move.set_effective_date()
- move.save()
+ to_write.extend(([move], {
+ 'effective_date': move.effective_date,
+ 'state': 'assigned'
+ }))
+ cls.write(*to_write)
@classmethod
@ModelView.button
@@ -661,7 +667,12 @@
@classmethod
def write(cls, *args):
+ pool = Pool()
+ Product = pool.get('product.product')
+ Uom = pool.get('product.uom')
+
actions = iter(args)
+ args = []
for moves, values in zip(actions, actions):
vals_set = set(values)
if cls._deny_modify_assigned & vals_set:
@@ -673,6 +684,27 @@
if move.state in ('done', 'cancel'):
cls.raise_user_error('modify_done_cancel',
(move.rec_name,))
+ if set(['quantity', 'uom', 'product']) & vals_set:
+ int_qty2moves = {}
+ for move in moves:
+ uom = values.get('uom', move.uom)
+ if not isinstance(uom, Uom):
+ uom = Uom(uom)
+ product = values.get('product', move.product)
+ if not isinstance(product, Uom):
+ product = Product(product)
+ internal_quantity = cls._get_internal_quantity(
+ values.get('quantity', move.quantity),
+ uom,
+ product)
+ int_qty2moves.setdefault(
+ internal_quantity, []).append(move)
+ for int_qty, int_qty_moves in int_qty2moves.iteritems():
+ new_values = values.copy()
+ new_values['internal_quantity'] = int_qty
+ args.extend((int_qty_moves, new_values))
+ else:
+ args.extend((moves, values))
super(Move, cls).write(*args)
@@ -680,15 +712,6 @@
for moves, values in zip(actions, actions):
if any(f not in cls._allow_modify_closed_period for f in values):
cls.check_period_closed(moves)
- for move in moves:
- internal_quantity = cls._get_internal_quantity(move.quantity,
- move.uom, move.product)
- if (internal_quantity != move.internal_quantity
- and internal_quantity
- != values.get('internal_quantity')):
- cls.write([move], {
- 'internal_quantity': internal_quantity,
- })
@classmethod
def delete(cls, moves):
diff -r 5d7c2958b920 shipment.py
--- a/trytond/trytond/modules/stock/shipment.py Mon Nov 23 17:59:15 2015 +0100
+++ b/trytond/trytond/modules/stock/shipment.py Mon Nov 23 18:09:01 2015 +0100
@@ -1225,18 +1225,26 @@
Set planned date of moves for the shipments
'''
Move = Pool().get('stock.move')
+ to_write = []
for shipment in shipments:
outgoing_date, inventory_date = shipment._move_planned_date
- Move.write([x for x in shipment.outgoing_moves
+ out_moves_to_write = [x for x in shipment.outgoing_moves
if (x.state not in ('assigned', 'done', 'cancel')
- and x.planned_date != outgoing_date)], {
- 'planned_date': outgoing_date,
- })
- Move.write([x for x in shipment.inventory_moves
+ and x.planned_date != outgoing_date)]
+ if out_moves_to_write:
+ to_write.extend((out_moves_to_write, {
+ 'planned_date': outgoing_date,
+ }))
+
+ inv_moves_to_write = [x for x in shipment.inventory_moves
if (x.state not in ('assigned', 'done', 'cancel')
- and x.planned_date != inventory_date)], {
- 'planned_date': inventory_date,
- })
+ and x.planned_date != inventory_date)]
+ if inv_moves_to_write:
+ to_write.extend((inv_moves_to_write, {
+ 'planned_date': inventory_date,
+ }))
+ if to_write:
+ Move.write(*to_write)
@classmethod
def create(cls, vlist):

8
README Normal file
View File

@ -0,0 +1,8 @@
NaN-TIC patches
===============
Change to branch patches before to apply patch:
* v4.0
* v3.8
* ...

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +0,0 @@
diff -r 32ceadcd01cd move.xml
--- a/trytond/trytond/modules/account/move.xml Mon Feb 02 18:44:16 2015 +0100
+++ b/trytond/trytond/modules/account/move.xml Thu Apr 02 10:58:14 2015 +0200
@@ -259,6 +259,15 @@
<field name="perm_delete" eval="True"/>
</record>
+ <record model="ir.rule.group" id="rule_group_move_line">
+ <field name="model" search="[('model', '=', 'account.move.line')]"/>
+ <field name="global_p" eval="True"/>
+ </record>
+ <record model="ir.rule" id="rule_move_line1">
+ <field name="domain" eval="[('account.company', 'in', Eval('user', {}).get('companies', []))]" pyson="1"/>
+ <field name="rule_group" ref="rule_group_move_line"/>
+ </record>
+
<record model="ir.ui.view" id="reconcile_lines_writeoff_view_form">
<field name="model">account.move.reconcile_lines.writeoff</field>
<field name="type">form</field>

View File

@ -1,240 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Add company domain
issue5104
review19141003
Index: trytond/trytond/modules/analytic_account/account.py
===================================================================
diff -r 0cd556f1c82c account.py
--- a/trytond/trytond/modules/analytic_account/account.py Sun Mar 13 16:19:22 2016 +0100
+++ b/trytond/trytond/modules/analytic_account/account.py Tue Apr 26 18:24:04 2016 +0200
@@ -8,7 +8,7 @@
from trytond import backend
from trytond.model import ModelView, ModelSQL, fields, Unique
from trytond.wizard import Wizard, StateView, StateAction, Button
-from trytond.pyson import Eval, PYSONEncoder
+from trytond.pyson import Eval, If, PYSONEncoder, PYSONDecoder
from trytond.transaction import Transaction
from trytond.pool import Pool
@@ -22,7 +22,7 @@
name = fields.Char('Name', required=True, translate=True, select=True)
code = fields.Char('Code', select=True)
active = fields.Boolean('Active', select=True)
- company = fields.Many2One('company.company', 'Company')
+ company = fields.Many2One('company.company', 'Company', required=True)
currency = fields.Many2One('currency.currency', 'Currency', required=True)
currency_digits = fields.Function(fields.Integer('Currency Digits'),
'on_change_with_currency_digits')
@@ -33,6 +33,7 @@
], 'Type', required=True)
root = fields.Many2One('analytic_account.account', 'Root', select=True,
domain=[
+ ('company', '=', Eval('company')),
('parent', '=', None),
('type', '=', 'root'),
],
@@ -40,7 +41,7 @@
'invisible': Eval('type') == 'root',
'required': Eval('type') != 'root',
},
- depends=['type'])
+ depends=['company', 'type'])
parent = fields.Many2One('analytic_account.account', 'Parent', select=True,
domain=[('parent', 'child_of', Eval('root'))],
states={
@@ -311,19 +312,26 @@
__name__ = 'analytic.account.entry'
origin = fields.Reference('Origin', selection='get_origin', select=True)
root = fields.Many2One('analytic_account.account', 'Root Analytic',
- domain=[('type', '=', 'root')])
+ domain=[
+ ('company', '=', Eval('company')),
+ ('type', '=', 'root'),
+ ],
+ depends=['company'])
account = fields.Many2One('analytic_account.account', 'Account',
ondelete='RESTRICT',
states={
'required': Eval('required', False),
},
domain=[
+ ('company', '=', Eval('company')),
('root', '=', Eval('root')),
('type', '=', 'normal'),
],
- depends=['root', 'required'])
+ depends=['root', 'required', 'company'])
required = fields.Function(fields.Boolean('Required'),
'on_change_with_required')
+ company = fields.Function(fields.Many2One('company.company', 'Company'),
+ 'on_change_with_company', searcher='search_company')
@classmethod
def __register__(cls, module_name):
@@ -386,12 +394,27 @@
return self.root.mandatory
return False
+ @classmethod
+ def default_company(cls):
+ return Transaction().context.get('company')
+
+ def on_change_with_company(self, name=None):
+ return Transaction().context.get('company')
+
+ @classmethod
+ def search_company(cls, name, clause):
+ raise NotImplementedError()
+
class AnalyticMixin(ModelSQL):
analytic_accounts = fields.One2Many('analytic.account.entry', 'origin',
'Analytic Accounts',
size=Eval('analytic_accounts_size', 0),
+ domain=[
+ ('company', If(Eval('context', {}).contains('company'), '=', '!='),
+ Eval('context', {}).get('company', -1)),
+ ],
depends=['analytic_accounts_size'])
analytic_accounts_size = fields.Function(fields.Integer(
'Analytic Accounts Size'), 'get_analytic_accounts_size')
@@ -427,13 +450,19 @@
where=entry.selection == selection_id))
handler.drop_column('analytic_accounts')
- @staticmethod
- def default_analytic_accounts():
+ @classmethod
+ def analytic_accounts_domain(cls):
+ return PYSONDecoder(Transaction().context).decode(
+ PYSONEncoder().encode(cls.analytic_accounts.domain))
+
+ @classmethod
+ def default_analytic_accounts(cls):
pool = Pool()
AnalyticAccount = pool.get('analytic_account.account')
accounts = []
- root_accounts = AnalyticAccount.search([
+ root_accounts = AnalyticAccount.search(
+ cls.analytic_accounts_domain() + [
('parent', '=', None),
])
for account in root_accounts:
@@ -443,11 +472,14 @@
})
return accounts
- @staticmethod
- def default_analytic_accounts_size():
+ @classmethod
+ def default_analytic_accounts_size(cls):
pool = Pool()
AnalyticAccount = pool.get('analytic_account.account')
- return len(AnalyticAccount.search([('type', '=', 'root')]))
+ return len(AnalyticAccount.search(
+ cls.analytic_accounts_domain() + [
+ ('type', '=', 'root'),
+ ]))
@classmethod
def get_analytic_accounts_size(cls, records, name):
@@ -464,12 +496,17 @@
"Check that all mandatory root entries are defined in entries"
pool = Pool()
Account = pool.get('analytic_account.account')
- mandatory_roots = {a for a in Account.search([
+ all_mandatory_roots = {a for a in Account.search([
('type', '=', 'root'),
('mandatory', '=', True),
])}
for analytic in analytics:
analytic_roots = {e.root for e in analytic.analytic_accounts}
+ companies = {e.company for e in analytic.analytic_accounts}
+ mandatory_roots = set()
+ for mandatory in all_mandatory_roots:
+ if mandatory.company in companies:
+ mandatory_roots.add(mandatory)
if not mandatory_roots <= analytic_roots:
cls.raise_user_error('root_account', {
'name': analytic.rec_name,
diff -r 0cd556f1c82c account.xml
--- a/trytond/trytond/modules/analytic_account/account.xml Sun Mar 13 16:19:22 2016 +0100
+++ b/trytond/trytond/modules/analytic_account/account.xml Tue Apr 26 18:24:04 2016 +0200
@@ -124,5 +124,27 @@
<field name="type">tree</field>
<field name="name">analytic_account_entry_tree</field>
</record>
+
+ <record model="ir.rule.group" id="rule_group_account">
+ <field name="model" search="[('model', '=', 'analytic_account.account')]"/>
+ <field name="global_p" eval="True"/>
+ </record>
+ <record model="ir.rule" id="rule_account1">
+ <field name="domain"
+ eval="[('company', '=', Eval('user', {}).get('company', None))]"
+ pyson="1"/>
+ <field name="rule_group" ref="rule_group_account"/>
+ </record>
+
+ <record model="ir.rule.group" id="rule_group_account_entry">
+ <field name="model" search="[('model', '=', 'analytic.account.entry')]"/>
+ <field name="global_p" eval="True"/>
+ </record>
+ <record model="ir.rule" id="rule_account_entry1">
+ <field name="domain"
+ eval="[('company', '=', Eval('user', {}).get('company', None))]"
+ pyson="1"/>
+ <field name="rule_group" ref="rule_group_account_entry"/>
+ </record>
</data>
</tryton>
diff -r 0cd556f1c82c line.py
--- a/trytond/trytond/modules/analytic_account/line.py Sun Mar 13 16:19:22 2016 +0100
+++ b/trytond/trytond/modules/analytic_account/line.py Tue Apr 26 18:24:04 2016 +0200
@@ -24,7 +24,7 @@
currency_digits = fields.Function(fields.Integer('Currency Digits'),
'on_change_with_currency_digits')
company = fields.Function(fields.Many2One('company.company', 'Company'),
- 'on_change_with_company')
+ 'on_change_with_company', searcher='search_company')
account = fields.Many2One('analytic_account.account', 'Account',
required=True, select=True, domain=[
('type', '!=', 'view'),
@@ -104,6 +104,10 @@
if self.move_line:
return self.move_line.account.company.id
+ @classmethod
+ def search_company(cls, name, clause):
+ return [('move_line.account.company',) + tuple(clause[1:])]
+
@staticmethod
def query_get(table):
'''
diff -r 0cd556f1c82c line.xml
--- a/trytond/trytond/modules/analytic_account/line.xml Sun Mar 13 16:19:22 2016 +0100
+++ b/trytond/trytond/modules/analytic_account/line.xml Tue Apr 26 18:24:04 2016 +0200
@@ -67,5 +67,15 @@
<field name="name">move_line_form</field>
</record>
+ <record model="ir.rule.group" id="rule_group_account_line">
+ <field name="model" search="[('model', '=', 'analytic_account.line')]"/>
+ <field name="global_p" eval="True"/>
+ </record>
+ <record model="ir.rule" id="rule_account_line1">
+ <field name="domain"
+ eval="[('company', '=', Eval('user', {}).get('company', None))]"
+ pyson="1"/>
+ <field name="rule_group" ref="rule_group_account_line"/>
+ </record>
</data>
</tryton>

View File

@ -1,48 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Add company domain on analytic entries
issue5104
review24081002
Index: trytond/trytond/modules/analytic_invoice/invoice.py
===================================================================
--- a/trytond/trytond/modules/analytic_invoice/invoice.py
+++ b/trytond/trytond/modules/analytic_invoice/invoice.py
@@ -1,5 +1,6 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
from trytond.pool import PoolMeta, Pool
from trytond.modules.analytic_account import AnalyticMixin
@@ -61,3 +62,24 @@
def _get_origin(cls):
origins = super(AnalyticAccountEntry, cls)._get_origin()
return origins + ['account.invoice.line']
+
+ @fields.depends('origin')
+ def on_change_with_company(self, name=None):
+ pool = Pool()
+ InvoiceLine = pool.get('account.invoice.line')
+ company = super(AnalyticAccountEntry, self).on_change_with_company(
+ name)
+ if isinstance(self.origin, InvoiceLine):
+ if self.origin.invoice:
+ return self.origin.invoice.company.id
+ elif self.origin.company:
+ return self.origin.company.id
+ return company
+
+ @classmethod
+ def search_company(cls, name, clause):
+ return ['OR',
+ [('origin.company',) + tuple(clause[1:]) +
+ tuple(('account.invoice.line',))],
+ [('origin.invoice.company',) + tuple(clause[1:]) +
+ tuple(('account.invoice.line',))]]

View File

@ -1,37 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Add company domain on analytic entries
issue5104
review17201002
Index: trytond/trytond/modules/analytic_purchase/purchase.py
===================================================================
--- a/trytond/trytond/modules/analytic_purchase/purchase.py
+++ b/trytond/trytond/modules/analytic_purchase/purchase.py
@@ -79,3 +79,22 @@
and self.origin.purchase.state in ['cancel', 'draft']):
return False
return required
+
+ @fields.depends('origin')
+ def on_change_with_company(self, name=None):
+ pool = Pool()
+ PurchaseLine = pool.get('purchase.line')
+ company = super(AnalyticAccountEntry, self).on_change_with_company(
+ name)
+ if isinstance(self.origin, PurchaseLine):
+ if self.origin.purchase:
+ return self.origin.purchase.company.id
+ return company
+
+ @classmethod
+ def search_company(cls, name, clause):
+ domain = super(AnalyticAccountEntry, cls).search_company(name, clause)
+ return ['OR',
+ domain,
+ [('origin.purchase.company',) + tuple(clause[1:]) +
+ tuple(('purchase.line',))]]

View File

@ -1,45 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Add company domain on analytic entries
issue5104
review17991002
Index: trytond/trytond/modules/analytic_sale/sale.py
===================================================================
--- a/trytond/trytond/modules/analytic_sale/sale.py
+++ b/trytond/trytond/modules/analytic_sale/sale.py
@@ -1,5 +1,6 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
+from trytond.model import fields
from trytond.pool import Pool, PoolMeta
from trytond.modules.analytic_account import AnalyticMixin
@@ -32,3 +33,22 @@
def _get_origin(cls):
origins = super(AnalyticAccountEntry, cls)._get_origin()
return origins + ['sale.line']
+
+ @fields.depends('origin')
+ def on_change_with_company(self, name=None):
+ pool = Pool()
+ SaleLine = pool.get('sale.line')
+ company = super(AnalyticAccountEntry, self).on_change_with_company(
+ name)
+ if isinstance(self.origin, SaleLine):
+ if self.origin.sale:
+ return self.origin.sale.company.id
+ return company
+
+ @classmethod
+ def search_company(cls, name, clause):
+ domain = super(AnalyticAccountEntry, cls).search_company(name, clause)
+ return ['OR',
+ domain,
+ [('origin.sale.company',) + tuple(clause[1:]) +
+ tuple(('sale.line',))]]

View File

@ -1,24 +0,0 @@
diff -r 75c44f5a88e0 trytond/trytond/protocols/dispatcher.py
--- a/trytond/trytond/protocols/dispatcher.py Mon Jul 20 09:50:24 2015 +0200
+++ b/trytond/trytond/protocols/dispatcher.py Mon Jul 20 10:21:09 2015 +0200
@@ -157,7 +157,19 @@
type, _ = method.split('.', 1)
name = '.'.join(method.split('.')[1:-1])
method = method.split('.')[-1]
- return pool.get(name, type=type), method
+ try:
+ obj = pool.get(name, type=type)
+ except KeyError:
+ if name[:15] == 'babi_execution_':
+ with Transaction().start(pool.database_name, request.user_id,
+ readonly=False):
+ Execution = pool.get('babi.report.execution')
+ execution = Execution(int(name[15:]))
+ execution.validate_model()
+ obj = pool.get(name, type=type)
+ else:
+ raise
+ return obj, method
@app.auth_required

View File

@ -1,12 +0,0 @@
diff -r a87800ef903a move.py
--- a/trytond/trytond/modules/stock/move.py Fri Nov 27 12:13:17 2015 +0100
+++ b/trytond/trytond/modules/stock/move.py Fri Nov 27 12:13:55 2015 +0100
@@ -775,7 +775,7 @@
Date = pool.get('ir.date')
Location = pool.get('stock.location')
- Transaction().cursor.lock(cls._table)
+ # Transaction().cursor.lock(cls._table)
if with_childs:
locations = Location.search([

View File

@ -1,65 +0,0 @@
diff -r 1a22411f9264 trytond/trytond/model/fields/many2many.py
--- a/trytond/trytond/model/fields/many2many.py Thu Jul 16 01:13:45 2015 +0200
+++ b/trytond/trytond/model/fields/many2many.py Mon Jul 20 14:20:18 2015 +0200
@@ -287,6 +287,9 @@
table, _ = tables[None]
name, operator, value = domain[:3]
assert operator not in {'where', 'not where'} or '.' not in name
+ method = getattr(Model, 'domain_%s' % name, None)
+ if method:
+ return method(domain, tables)
if Relation._history and transaction.context.get('_datetime'):
relation = Relation.__table_history__()
diff -r 1a22411f9264 trytond/trytond/model/fields/many2one.py
--- a/trytond/trytond/model/fields/many2one.py Thu Jul 16 01:13:45 2015 +0200
+++ b/trytond/trytond/model/fields/many2one.py Mon Jul 20 14:20:18 2015 +0200
@@ -159,6 +159,9 @@
table, _ = tables[None]
name, operator, value = domain[:3]
+ method = getattr(Model, 'domain_%s' % name, None)
+ if method:
+ return method(domain, tables)
column = self.sql_column(table)
if '.' not in name:
if operator.endswith('child_of') or operator.endswith('parent_of'):
diff -r 1a22411f9264 trytond/trytond/model/fields/one2many.py
--- a/trytond/trytond/model/fields/one2many.py Thu Jul 16 01:13:45 2015 +0200
+++ b/trytond/trytond/model/fields/one2many.py Mon Jul 20 14:20:18 2015 +0200
@@ -232,6 +232,9 @@
table, _ = tables[None]
name, operator, value = domain[:3]
assert operator not in {'where', 'not where'} or '.' not in name
+ method = getattr(Model, 'domain_%s' % name, None)
+ if method:
+ return method(domain, tables)
if Target._history and transaction.context.get('_datetime'):
target = Target.__table_history__()
diff -r 1a22411f9264 trytond/trytond/model/fields/property.py
--- a/trytond/trytond/model/fields/property.py Thu Jul 16 01:13:45 2015 +0200
+++ b/trytond/trytond/model/fields/property.py Mon Jul 20 14:20:18 2015 +0200
@@ -72,6 +72,9 @@
cursor = Transaction().connection.cursor()
name, operator, value = domain
+ method = getattr(Model, 'domain_%s' % name, None)
+ if method:
+ return method(domain, tables)
sql_type = self._field.sql_type().base
diff -r 1a22411f9264 trytond/trytond/model/fields/reference.py
--- a/trytond/trytond/model/fields/reference.py Thu Jul 16 01:13:45 2015 +0200
+++ b/trytond/trytond/model/fields/reference.py Mon Jul 20 14:20:18 2015 +0200
@@ -124,6 +124,9 @@
return super(Reference, self).convert_domain(domain, tables, Model)
pool = Pool()
name, operator, value, target = domain[:4]
+ method = getattr(Model, 'domain_%s' % name, None)
+ if method:
+ return method(domain, tables)
Target = pool.get(target)
table, _ = tables[None]
name, target_name = name.split('.', 1)

View File

@ -1,49 +0,0 @@
diff -r fdfe606e6b87 stock.py
--- a/trytond/trytond/modules/stock_lot/stock.py Thu Feb 19 00:04:21 2015 +0100
+++ b/trytond/trytond/modules/stock_lot/stock.py Mon Oct 05 11:56:24 2015 +0200
@@ -119,16 +119,19 @@
round=False)
if quantity < out_quantity:
outgoing_moves.extend(Move.copy([out_move], default={
- 'quantity': out_quantity - quantity,
+ 'quantity': Uom.round(
+ out_quantity - quantity,
+ out_move.uom.rounding),
}))
Move.write([out_move], {
- 'quantity': quantity,
+ 'quantity': Uom.round(
+ quantity, out_move.uom.rounding),
})
Move.write([out_move], {
'lot': move.lot.id,
})
quantity -= out_quantity
- assert quantity <= 0
+ assert quantity <= move.product.default_uom.rounding
class ShipmentOutReturn:
diff -r 519c1c1a1ca2 shipment.py
--- a/trytond/trytond/modules/stock/shipment.py Mon Oct 05 12:22:18 2015 +0200
+++ b/trytond/trytond/modules/stock/shipment.py Mon Oct 05 12:23:46 2015 +0200
@@ -1177,14 +1177,17 @@
continue
key = cls._sync_inventory_to_outgoing_grouping_key(move,
'outgoing')
- if outgoing_qty.get(key, 0.0) > 0.0:
+ if (outgoing_qty.get(key, 0.0)
+ > move.product.default_uom.rounding):
exc_qty = Uom.compute_qty(move.product.default_uom,
outgoing_qty[key], move.uom)
removed_qty = Uom.compute_qty(move.uom,
min(exc_qty, move.quantity), move.product.default_uom,
round=False)
Move.write([move], {
- 'quantity': max(0.0, move.quantity - exc_qty),
+ 'quantity': max(0.0, Uom.round(
+ move.quantity - exc_qty,
+ move.uom.rounding)),
})
outgoing_qty[key] -= removed_qty

View File

@ -1,21 +0,0 @@
diff --git a/trytond/ir/action.py b/trytond/ir/action.py
--- a/trytond/trytond/ir/action.py
+++ b/trytond/trytond/ir/action.py
@@ -149,13 +149,13 @@
def check_wizard_model(self):
ActionWizard = Pool().get('ir.action.wizard')
if self.action.type == 'ir.action.wizard':
- action_wizard, = ActionWizard.search([
+ action_wizards = ActionWizard.search([
('action', '=', self.action.id),
], limit=1)
- if action_wizard.model:
- if self.model.__name__ != action_wizard.model:
+ if action_wizards and action_wizards[0].model:
+ if self.model.__name__ != action_wizards[0].model:
self.raise_user_error('wrong_wizard_model', (
- action_wizard.rec_name,))
+ action_wizards[0].rec_name,))
@staticmethod
def _convert_vals(vals):

View File

@ -1,15 +0,0 @@
diff -r 1b91a9bc6db1 trytond/protocols/dispatcher.py
--- a/trytond/trytond/protocols/dispatcher.py Mon Nov 09 23:16:42 2015 +0100
+++ b/trytond/trytond/protocols/dispatcher.py Wed Nov 25 08:55:40 2015 +0100
@@ -172,6 +172,11 @@
except DatabaseOperationalError:
transaction.cursor.rollback()
if count and not rpc.readonly:
+ retry = config.getint('database', 'retry')
+ waiting_time = min((retry - count) * (retry - count) * 0.1,
+ 4.0)
+ if waiting_time:
+ time.sleep(waiting_time)
continue
raise
except (NotLogged, ConcurrencyException, UserError, UserWarning):

View File

@ -1,500 +0,0 @@
diff -r 3681a54fda0a trytond/trytond/modules/account_invoice/invoice.py
--- a/trytond/trytond/modules/account_invoice/invoice.py Tue Jul 07 16:46:50 2015 +0200
+++ b/trytond/trytond/modules/account_invoice/invoice.py Tue Jul 07 17:12:14 2015 +0200
@@ -859,34 +859,35 @@
'''
Return move line
'''
- Currency = Pool().get('currency.currency')
- res = {}
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ MoveLine = pool.get('account.move.line')
+ line = MoveLine()
if self.currency.id != self.company.currency.id:
with Transaction().set_context(date=self.currency_date):
- res['amount_second_currency'] = Currency.compute(
+ line.amount_second_currency = Currency.compute(
self.company.currency, amount, self.currency)
- res['second_currency'] = self.currency.id
+ line.amount_second_currency = -line.amount_second_currency
+ line.second_currency = self.currency.id
else:
- res['amount_second_currency'] = None
- res['second_currency'] = None
- if amount <= 0:
- res['debit'], res['credit'] = -amount, 0
+ line.amount_second_currency = None
+ line.second_currency = None
+ if amount >= Decimal('0.0'):
+ line.debit = Decimal('0.0')
+ line.credit = amount
else:
- res['debit'], res['credit'] = 0, amount
- if res['amount_second_currency']:
- res['amount_second_currency'] = (
- res['amount_second_currency'].copy_sign(
- res['debit'] - res['credit']))
- res['account'] = self.account.id
+ line.debit = - amount
+ line.credit = Decimal('0.0')
+ line.account = self.account.id
if self.account.party_required:
- res['party'] = self.party.id
- res['maturity_date'] = date
- res['description'] = self.description
- return res
+ line.party = self.party.id
+ line.maturity_date = date
+ line.description = self.description
+ return line
- def create_move(self):
+ def get_move(self):
'''
- Create account move for the invoice and return the created move
+ Compute account move for the invoice and return the created move
'''
pool = Pool()
Move = pool.get('account.move')
@@ -902,9 +903,9 @@
total = Decimal('0.0')
total_currency = Decimal('0.0')
for line in move_lines:
- total += line['debit'] - line['credit']
- if line['amount_second_currency']:
- total_currency += line['amount_second_currency']
+ total += line.debit - line.credit
+ if line.amount_second_currency:
+ total_currency += line.amount_second_currency
term_lines = self.payment_term.compute(total, self.company.currency,
self.invoice_date)
@@ -912,28 +913,23 @@
if not term_lines:
term_lines = [(Date.today(), total)]
for date, amount in term_lines:
- val = self._get_move_line(date, amount)
- if val['amount_second_currency']:
- remainder_total_currency += val['amount_second_currency']
- move_lines.append(val)
+ line = self._get_move_line(date, amount)
+ if line.amount_second_currency:
+ remainder_total_currency += line.amount_second_currency
+ move_lines.append(line)
if not self.currency.is_zero(remainder_total_currency):
- move_lines[-1]['amount_second_currency'] -= \
+ move_lines[-1].amount_second_currency -= \
remainder_total_currency
-
accounting_date = self.accounting_date or self.invoice_date
period_id = Period.find(self.company.id, date=accounting_date)
- move, = Move.create([{
- 'journal': self.journal.id,
- 'period': period_id,
- 'date': accounting_date,
- 'origin': str(self),
- 'company': self.company.id,
- 'lines': [('create', move_lines)],
- }])
- self.write([self], {
- 'move': move.id,
- })
+ move = Move()
+ move.journal = self.journal
+ move.period = period_id
+ move.date = accounting_date
+ move.origin = self
+ move.company = self.company
+ move.lines = move_lines
return move
def set_number(self):
@@ -970,10 +966,9 @@
with Transaction().set_context(
date=self.invoice_date or Date.today()):
number = Sequence.get_id(sequence.id)
- vals = {'number': number}
+ self.number = number
if not self.invoice_date and self.type == 'out':
- vals['invoice_date'] = Transaction().context['date']
- self.write([self], vals)
+ self.invoice_date = Transaction().context['date']
@classmethod
def check_modify(cls, invoices):
@@ -987,9 +982,12 @@
cls.raise_user_error('modify_invoice', (invoice.rec_name,))
def get_rec_name(self, name):
- return (self.number or unicode(self.id)
- + (self.reference and (' ' + self.reference) or '')
- + ' ' + self.party.rec_name)
+ name = self.number or unicode(self.id)
+ if self.reference:
+ name += ' %s' % self.reference
+ if self.party:
+ name += ' %s' % self.party.rec_name
+ return name
@classmethod
def search_rec_name(cls, name, clause):
@@ -1033,7 +1031,7 @@
all_invoices += invoices
update_tax = [i for i in all_invoices if i.state == 'draft']
super(Invoice, cls).write(*args)
- if update_tax:
+ if update_tax and not Transaction().context.get('skip_update_taxes'):
cls.update_taxes(update_tax)
@classmethod
@@ -1201,18 +1199,16 @@
'''
MoveLine = Pool().get('account.move.line')
- new_invoices = []
- for invoice in invoices:
- new_invoice, = cls.create([invoice._credit()])
- new_invoices.append(new_invoice)
- if refund:
- cls.post([new_invoice])
+ new_invoices = cls.create([i._credit() for i in invoices])
+ cls.update_taxes(new_invoices)
+ if refund:
+ cls.post(new_invoices)
+ for invoice, new_invoice in itertools.izip(invoices, new_invoices):
if new_invoice.state == 'posted':
MoveLine.reconcile([l for l in invoice.lines_to_pay
if not l.reconciliation] +
[l for l in new_invoice.lines_to_pay
if not l.reconciliation])
- cls.update_taxes(new_invoices)
return new_invoices
@classmethod
@@ -1232,10 +1228,16 @@
@ModelView.button
@Workflow.transition('validated')
def validate_invoice(cls, invoices):
+ to_write = []
for invoice in invoices:
if invoice.type == 'in':
invoice.set_number()
- invoice.create_move()
+ move = invoice.get_move()
+ if move != invoice.move:
+ invoice.move = invoice.get_move()
+ to_write.extend(([invoice], invoice._save_values))
+ if to_write:
+ cls.write(*to_write)
@classmethod
@ModelView.button
@@ -1243,14 +1245,29 @@
def post(cls, invoices):
Move = Pool().get('account.move')
- moves = []
+ to_create = []
for invoice in invoices:
invoice.set_number()
- moves.append(invoice.create_move())
- cls.write([i for i in invoices if i.state != 'posted'], {
- 'state': 'posted',
- })
- Move.post([m for m in moves if m.state != 'posted'])
+ move = invoice.get_move()
+ if move != invoice.move:
+ to_create.append(move._save_values)
+ invoices2move = {}
+ if to_create:
+ moves = Move.create(to_create)
+ for move in moves:
+ invoices2move[move.origin.id] = move.id
+ to_write = []
+ for invoice in invoices:
+ values = invoice._save_values
+ if invoice.id in invoices2move:
+ values['move'] = invoices2move[invoice.id]
+ if values:
+ to_write.extend(([invoice], values))
+ if to_write:
+ with Transaction().set_context(skip_update_taxes=True):
+ cls.write(*to_write)
+ cls.write(invoices, {'state': 'posted'})
+ Move.post([i.move for i in invoices if i.move.state != 'posted'])
for invoice in invoices:
if invoice.type == 'out':
invoice.print_invoice()
@@ -1289,14 +1306,17 @@
cancel_moves = []
delete_moves = []
+ to_write = []
for invoice in invoices:
if invoice.move:
if invoice.move.state == 'draft':
delete_moves.append(invoice.move)
elif not invoice.cancel_move:
invoice.cancel_move = invoice.move.cancel()
- invoice.save()
cancel_moves.append(invoice.cancel_move)
+ to_write.extend(([invoice], invoice._save_values))
+ if to_write:
+ cls.write(*to_write)
if delete_moves:
Move.delete(delete_moves)
if cancel_moves:
@@ -1852,6 +1872,7 @@
def _compute_taxes(self):
pool = Pool()
Currency = pool.get('currency.currency')
+ TaxLine = pool.get('account.tax.line')
res = []
if self.type != 'line':
@@ -1869,53 +1890,55 @@
date=self.invoice.currency_date):
amount = Currency.compute(self.invoice.currency,
amount, self.invoice.company.currency)
- res.append({
- 'code': base_code,
- 'amount': amount,
- 'tax': tax['tax'],
- })
+ tax_line = TaxLine()
+ tax_line.code = base_code
+ tax_line.amount = amount
+ tax_line.tax = tax['tax']
+ res.append(tax_line)
return res
def get_move_line(self):
'''
- Return a list of move lines values for invoice line
+ Return a list of move lines instances for invoice line
'''
- Currency = Pool().get('currency.currency')
- res = {}
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ MoveLine = pool.get('account.move.line')
if self.type != 'line':
return []
- res['description'] = self.description
+ line = MoveLine()
+ line.description = self.description
if self.invoice.currency != self.invoice.company.currency:
with Transaction().set_context(date=self.invoice.currency_date):
amount = Currency.compute(self.invoice.currency,
self.amount, self.invoice.company.currency)
- res['amount_second_currency'] = self.amount
- res['second_currency'] = self.invoice.currency.id
+ line.amount_second_currency = self.amount
+ line.second_currency = self.invoice.currency.id
else:
amount = self.amount
- res['amount_second_currency'] = None
- res['second_currency'] = None
+ line.amount_second_currency = None
+ line.second_currency = None
if amount >= 0:
if self.invoice.type == 'out':
- res['debit'], res['credit'] = 0, amount
+ line.debit, line.credit = 0, amount
else:
- res['debit'], res['credit'] = amount, 0
+ line.debit, line.credit = amount, 0
else:
if self.invoice.type == 'out':
- res['debit'], res['credit'] = -amount, 0
+ line.debit, line.credit = -amount, 0
else:
- res['debit'], res['credit'] = 0, -amount
- if res['amount_second_currency']:
- res['amount_second_currency'] = (
- res['amount_second_currency'].copy_sign(
- res['debit'] - res['credit']))
- res['account'] = self.account.id
+ line.debit, line.credit = 0, -amount
+ if line.amount_second_currency:
+ line.amount_second_currency = (
+ line.amount_second_currency.copy_sign(
+ line.debit - line.credit))
+ line.account = self.account.id
if self.account.party_required:
- res['party'] = self.invoice.party.id
+ line.party = self.invoice.party.id
computed_taxes = self._compute_taxes()
if computed_taxes:
- res['tax_lines'] = [('create', [tax for tax in computed_taxes])]
- return [res]
+ line.tax_lines = computed_taxes
+ return [line]
def _credit(self):
'''
@@ -2131,47 +2154,50 @@
def get_move_line(self):
'''
- Return a list of move lines values for invoice tax
+ Return a list of move lines instances for invoice tax
'''
- Currency = Pool().get('currency.currency')
- res = {}
+ pool = Pool()
+ Currency = pool.get('currency.currency')
+ MoveLine = pool.get('account.move.line')
+ TaxLine = pool.get('account.tax.line')
+ line = MoveLine()
if not self.amount:
return []
- res['description'] = self.description
+ line.description = self.description
if self.invoice.currency != self.invoice.company.currency:
with Transaction().set_context(date=self.invoice.currency_date):
amount = Currency.compute(self.invoice.currency, self.amount,
self.invoice.company.currency)
- res['amount_second_currency'] = self.amount
- res['second_currency'] = self.invoice.currency.id
+ line.amount_second_currency = self.amount
+ line.second_currency = self.invoice.currency.id
else:
amount = self.amount
- res['amount_second_currency'] = None
- res['second_currency'] = None
+ line.amount_second_currency = None
+ line.second_currency = None
if amount >= 0:
if self.invoice.type == 'out':
- res['debit'], res['credit'] = 0, amount
+ line.debit, line.credit = 0, amount
else:
- res['debit'], res['credit'] = amount, 0
+ line.debit, line.credit = amount, 0
else:
if self.invoice.type == 'out':
- res['debit'], res['credit'] = -amount, 0
+ line.debit, line.credit = -amount, 0
else:
- res['debit'], res['credit'] = 0, -amount
- if res['amount_second_currency']:
- res['amount_second_currency'] = (
- res['amount_second_currency'].copy_sign(
- res['debit'] - res['credit']))
- res['account'] = self.account.id
+ line.debit, line.credit = 0, -amount
+ if line.amount_second_currency:
+ line.amount_second_currency = (
+ line.amount_second_currency.copy_sign(
+ line.debit - line.credit))
+ line.account = self.account.id
if self.account.party_required:
- res['party'] = self.invoice.party.id
+ line.party = self.invoice.party.id
if self.tax_code:
- res['tax_lines'] = [('create', [{
- 'code': self.tax_code.id,
- 'amount': amount * self.tax_sign,
- 'tax': self.tax and self.tax.id or None
- }])]
- return [res]
+ tax_line = TaxLine()
+ tax_line.code = self.tax_code
+ tax_line.amount = amount * self.tax_sign
+ tax_line.tax = self.tax
+ line.tax_lines = [tax_line]
+ return [line]
def _credit(self):
'''
diff -r 0e69764f2826 trytond/trytond/modules/account_payment_type/invoice.py
--- a/trytond/trytond/modules/account_payment_type/invoice.py Tue Jul 07 10:10:50 2015 +0200
+++ b/trytond/trytond/modules/account_payment_type/invoice.py Tue Jul 07 17:06:02 2015 +0200
@@ -82,7 +82,7 @@
return self.company.party.customer_payment_type.id
def _get_move_line(self, date, amount):
- res = super(Invoice, self)._get_move_line(date, amount)
+ line = super(Invoice, self)._get_move_line(date, amount)
if self.payment_type:
- res['payment_type'] = self.payment_type
- return res
+ line.payment_type = self.payment_type
+ return line
diff -r 6429c9c53cb8 trytond/trytond/modules/account_bank/account.py
--- a/trytond/trytond/modules/account_bank/account.py Tue May 05 14:36:02 2015 +0200
+++ b/trytond/trytond/modules/account_bank/account.py Tue Jul 07 15:36:26 2015 +0200
@@ -179,10 +179,10 @@
'''
Add account bank to move line when post invoice.
'''
- res = super(Invoice, self)._get_move_line(date, amount)
+ line = super(Invoice, self)._get_move_line(date, amount)
if self.bank_account:
- res['bank_account'] = self.bank_account
- return res
+ line.bank_account = self.bank_account
+ return line
@classmethod
def create(cls, vlist):
diff -r 95d77335bdd5 trytond/trytond/modules/analytic_invoice/invoice.py
--- a/trytond/trytond/modules/analytic_invoice/invoice.py Sun Mar 01 15:34:41 2015 +0100
+++ b/trytond/trytond/modules/analytic_invoice/invoice.py Mon Nov 30 14:24:25 2015 +0100
@@ -25,32 +25,33 @@
return result
- def get_analytic_entry(self, entry, value):
- analytic_entry = {}
- analytic_entry['name'] = self.description
- analytic_entry['debit'] = value['debit']
- analytic_entry['credit'] = value['credit']
- analytic_entry['account'] = entry.account.id
- analytic_entry['journal'] = self.invoice.journal.id
- analytic_entry['date'] = (self.invoice.accounting_date or
- self.invoice.invoice_date)
- analytic_entry['reference'] = self.invoice.reference
- analytic_entry['party'] = self.invoice.party.id
- return analytic_entry
+ def get_analytic_entry(self, entry, line):
+ pool = Pool()
+ AnalyticLine = pool.get('analytic_account.line')
+ analytic_line = AnalyticLine()
+ analytic_line.name = self.description
+ analytic_line.debit = line.debit
+ analytic_line.credit = line.credit
+ analytic_line.account = entry.account
+ analytic_line.journal = self.invoice.journal
+ analytic_line.date = (self.invoice.accounting_date
+ or self.invoice.invoice_date)
+ analytic_line.reference = self.invoice.reference
+ analytic_line.party = self.invoice.party
+ return analytic_line
def get_move_line(self):
- values = super(InvoiceLine, self).get_move_line()
+ lines = super(InvoiceLine, self).get_move_line()
if self.analytic_accounts:
- for value in values:
- value['analytic_lines'] = []
- to_create = []
+ for line in lines:
+ analytic_lines = []
for entry in self.analytic_accounts:
if not entry.account:
continue
- to_create.append(self.get_analytic_entry(entry, value))
- if to_create:
- value['analytic_lines'] = [('create', to_create)]
- return values
+ analytic_lines.append(self.get_analytic_entry(entry,
+ line))
+ line.analytic_lines = analytic_lines
+ return lines
class AnalyticAccountEntry:

View File

@ -1,66 +0,0 @@
# HG changeset patch
# User Guillem Barba <guillembarba@gmail.com>
add relate to Credit Notes in Invoices
issue4506
review10091002
Index: invoice.xml
===================================================================
--- .a/trytond/trytond/modules/account_invoice/invoice.xml
+++ .b/trytond/trytond/modules/account_invoice/invoice.xml
@@ -38,6 +38,17 @@
<field name="act_window" ref="act_invoice_form"/>
</record>
+ <record model="ir.action.act_window" id="act_credit_notes_form">
+ <field name="name">Credit Notes</field>
+ <field name="res_model">account.invoice</field>
+ <field name="domain" eval="[('lines.origin.invoice', 'in', Eval('active_ids'), 'account.invoice.line')]" pyson="1"/>
+ </record>
+ <record model="ir.action.keyword" id="act_open_credit_notes_keyword1">
+ <field name="keyword">form_relate</field>
+ <field name="model">account.invoice,-1</field>
+ <field name="action" ref="act_credit_notes_form"/>
+ </record>
+
<record model="ir.action.act_window" id="act_invoice_out_form">
<field name="name">Customer Invoices</field>
<field name="res_model">account.invoice</field>
Index: ca_ES.xml
===================================================================
--- .a/trytond/trytond/modules/account_invoice/locale/ca_ES.po
+++ .b/trytond/trytond/modules/account_invoice/locale/ca_ES.po
@@ -1053,6 +1053,10 @@
msgid "Invoices"
msgstr "Factures"
+msgctxt "model:ir.action,name:act_credit_notes_form"
+msgid "Credit Notes"
+msgstr "Abonaments"
+
msgctxt "model:ir.action,name:act_invoice_in_credit_note_form"
msgid "Supplier Credit Notes"
msgstr "Abonaments de proveïdor"
Index: ca_ES.xml
===================================================================
--- .a/trytond/trytond/modules/account_invoice/locale/es_ES.po
+++ .b/trytond/trytond/modules/account_invoice/locale/es_ES.po
@@ -1045,6 +1045,10 @@
msgid "Invoices"
msgstr "Todas las facturas"
+msgctxt "model:ir.action,name:act_credit_notes_form"
+msgid "Credit Notes"
+msgstr "Abonos"
+
msgctxt "model:ir.action,name:act_invoice_form2"
msgid "Invoices"
msgstr "Facturas"

View File

@ -1,14 +0,0 @@
Index: line.py
===================================================================
--- ./trytond/trytond/modules/analytic_account/line.py
+++ ./trytond/trytond/modules/analytic_account/line.py
@@ -28,7 +28,7 @@
'on_change_with_company')
account = fields.Many2One('analytic_account.account', 'Account',
required=True, select=True, domain=[
- ('type', '!=', 'view'),
+ ('type', 'not in', ['view', 'root']),
['OR',
('company', '=', None),
('company', '=', Eval('company', -1)),

View File

@ -1,23 +0,0 @@
Index: stock.py
===================================================================
--- .a/trytond/trytond/modules/stock_lot/stock.py
+++ .b/trytond/trytond/modules/stock_lot/stock.py
@@ -80,6 +80,20 @@
for move in moves:
move.check_lot()
+ @classmethod
+ def assign_try(cls, moves, with_childs=True, grouping=('product',)):
+ lot_moves = []
+ product_moves = []
+ for move in moves:
+ if move.lot:
+ lot_moves.append(move)
+ else:
+ product_moves.append(move)
+ return (super(Move, cls).assign_try(lot_moves,
+ with_childs=with_childs, grouping=('product', 'lot'))
+ & super(Move, cls).assign_try(product_moves,
+ with_childs=with_childs, grouping=grouping))
+

View File

@ -1,34 +0,0 @@
diff -r dfbbed6b42d5 trytond/trytond/protocols/dispatcher.py
--- a/trytond/trytond/protocols/dispatcher.py Thu Apr 07 00:04:01 2016 +0200
+++ b/trytond/trytond/protocols/dispatcher.py Thu Apr 07 10:50:57 2016 +0200
@@ -212,7 +212,7 @@
logger.error(log_message, *log_args, exc_info=True)
raise
except (ConcurrencyException, UserError, UserWarning):
- logger.debug(log_message, *log_args, exc_info=True)
+ logger.warning(log_message, *log_args, exc_info=True)
raise
except Exception:
logger.error(log_message, *log_args, exc_info=True)
diff -r dfbbed6b42d5 trytond/protocols/jsonrpc.py
--- a/trytond/trytond/protocols/jsonrpc.py Thu Apr 07 00:04:01 2016 +0200
+++ b/trytond/trytond/protocols/jsonrpc.py Thu Apr 07 10:50:57 2016 +0200
@@ -9,6 +9,7 @@
except ImportError:
import json
import base64
+import logging
from werkzeug.wrappers import Response
from werkzeug.utils import cached_property
@@ -123,6 +124,10 @@
try:
return json.loads(self.decoded_data, object_hook=JSONDecoder())
except Exception:
+ exc_type, exc_value = sys.exc_info()[:2]
+ logger = logging.getLogger(__name__)
+ logger.warning('Exception while parsing json: %s (%s)\n %s'
+ % (exc_value, exc_type, traceback.format_exc()))
raise BadRequest('Unable to read JSON request')
else:
raise BadRequest('Not a JSON request')

View File

@ -1,70 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
save tree state when executing actions from list view menu
issue4771
review13181002
Index: tryton/tryton/common/popup_menu.py
===================================================================
--- a/tryton/tryton/common/popup_menu.py
+++ b/tryton/tryton/common/popup_menu.py
@@ -11,7 +11,7 @@
_ = gettext.gettext
-def populate(menu, model, record, title='', field=None):
+def populate(menu, model, record, title='', field=None, parent_screen=None):
'''
Fill menu with the actions of model for the record.
If title is filled, the actions will be put in a submenu.
@@ -37,6 +37,8 @@
return record
def activate(menuitem, action, atype):
+ if parent_screen:
+ parent_screen.save_tree_state()
rec = load(record)
action = Action.evaluate(action, atype, rec)
data = {
Index: tryton/tryton/gui/window/view_form/view/list.py
===================================================================
--- a/tryton/tryton/gui/window/view_form/view/list.py
+++ b/tryton/tryton/gui/window/view_form/view/list.py
@@ -901,7 +901,7 @@
menu = gtk.Menu()
menu.popup(None, None, None, event.button, event.time)
- def pop(menu, group, record):
+ def pop(menu, group, record, screen):
copy_item = gtk.ImageMenuItem('gtk-copy')
copy_item.connect('activate', lambda x: self.on_copy())
menu.append(copy_item)
@@ -915,7 +915,8 @@
break
parent = parent.parent
else:
- populate(menu, group.model_name, record)
+ populate(menu, group.model_name, record,
+ parent_screen=screen)
for col in self.treeview.get_columns():
if not col.get_visible() or not col.name:
continue
@@ -932,10 +933,11 @@
if not model:
continue
label = field.attrs['string']
- populate(menu, model, record_id, title=label, field=field)
+ populate(menu, model, record_id, title=label, field=field,
+ parent_screen=screen)
menu.show_all()
# Delay filling of popup as it can take time
- gobject.idle_add(pop, menu, group, record)
+ gobject.idle_add(pop, menu, group, record, self.screen)
elif event.button == 2:
event.button = 1
event.state |= gtk.gdk.MOD1_MASK

View File

@ -1,29 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Add company access rule for inventories
issue4482
review13891002
Index: trytond/trytond/modules/stock/inventory.xml
===================================================================
--- a/trytond/trytond/modules/stock/inventory.xml
+++ b/trytond/trytond/modules/stock/inventory.xml
@@ -57,6 +57,15 @@
<field name="name">inventory_line_tree</field>
</record>
+ <record model="ir.rule.group" id="rule_group_inventory">
+ <field name="model" search="[('model', '=', 'stock.inventory')]"/>
+ <field name="global_p" eval="True"/>
+ </record>
+ <record model="ir.rule" id="rule_inventory">
+ <field name="domain" eval="[('company', 'in', Eval('user', {}).get('companies', []))]" pyson="1"/>
+ <field name="rule_group" ref="rule_group_inventory"/>
+ </record>
+
<record model="ir.model.access" id="access_inventory">
<field name="model" search="[('model', '=', 'stock.inventory')]"/>
<field name="perm_read" eval="False"/>

View File

@ -1,12 +0,0 @@
diff -r 8635acede28d sale.py
--- .a/trytond/trytond/modules/sale/sale.py Sat Feb 21 19:06:50 2015 +0100
+++ .b/trytond/trytond/modules/sale/sale.py Mon Apr 20 09:32:28 2015 +0200
@@ -951,7 +951,7 @@
if sale.is_done():
if sale.state != 'done':
done.append(sale)
- elif sale.state != 'processing':
+ if sale.state != 'processing':
process.append(sale)
if process:
cls.proceed(process)

View File

@ -1,37 +0,0 @@
diff -r ae376b988766 product.py
--- .a/trytond/trytond/modules/purchase/product.py Mon Oct 20 15:02:51 2014 +0200
+++ .b/trytond/trytond/modules/purchase/product.py Mon Nov 03 13:24:24 2014 +0100
@@ -132,11 +132,14 @@
for product_supplier in product.product_suppliers:
if product_supplier.match(pattern):
pattern = ProductSupplierPrice.get_pattern()
- for price in product_supplier.prices:
- if price.match(quantity, uom, pattern):
- prices[product.id] = price.unit_price
- default_uom = product_supplier.uom
- default_currency = product_supplier.currency
+ price = product.get_supplier_price(product_supplier,
+ quantity, uom, pattern)
+ if price is not None:
+ prices[product.id] = price
+ default_uom = product.purchase_uom
+ default_currency = product_supplier.currency
+ else:
+ price = product.cost_price
break
prices[product.id] = Uom.compute_price(
default_uom, prices[product.id], uom)
@@ -147,6 +150,13 @@
prices[product.id], currency, round=False)
return prices
+ def get_supplier_price(self, product_supplier, quantity, uom, pattern):
+ res = None
+ for price in product_supplier.prices:
+ if price.match(quantity, uom, pattern):
+ res = price.unit_price
+ return res
+
class ProductSupplier(ModelSQL, ModelView, MatchMixin):
'Product Supplier'

View File

@ -1,38 +0,0 @@
diff -r 673658d4acd2 account.py
--- a/trytond/trytond/modules/account_invoice_stock/account.py Tue Sep 22 22:57:05 2015 +0200
+++ b/trytond/trytond/modules/account_invoice_stock/account.py Mon Oct 19 10:43:41 2015 +0200
@@ -34,6 +34,15 @@
self.unit)
return quantity
+ @property
+ def origin_quantity(self):
+ 'The move quantity computed in origin unit'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if not self.origin or not hasattr(self.origin, 'unit'):
+ return self.quantity
+ return Uom.compute_qty(self.unit, self.quantity, self.origin.unit)
+
@classmethod
def copy(cls, lines, default=None):
if default is None:
diff -r 673658d4acd2 stock.py
--- a/trytond/trytond/modules/account_invoice_stock/stock.py Tue Sep 22 22:57:05 2015 +0200
+++ b/trytond/trytond/modules/account_invoice_stock/stock.py Mon Oct 19 10:43:41 2015 +0200
@@ -24,6 +24,15 @@
invoice_line.quantity, self.uom)
return quantity
+ @property
+ def origin_quantity(self):
+ 'The move quantity computed in origin unit'
+ pool = Pool()
+ Uom = pool.get('product.uom')
+ if not self.origin or not hasattr(self.origin, 'unit'):
+ return self.quantity
+ return Uom.compute_qty(self.uom, self.quantity, self.origin.unit)
+
@classmethod
def copy(cls, moves, default=None):
if default is None:

View File

@ -1,71 +0,0 @@
# HG changeset patch
# User Cédric Krier <cedric.krier@b2ck.com>
Disable button during click processing
The click event must be blocked when the screen method is called to limit
double execution. A double execution is still possible if the execution of the
action, which is asynchronous, is not started fast enough.
issue5362
review17881002
Index: src/view/form.js
===================================================================
--- a/public_data/sao/src/view/form.js
+++ b/public_data/sao/src/view/form.js
@@ -361,7 +361,12 @@
},
button_clicked: function(event) {
var button = event.data;
- this.screen.button(button.attributes);
+ button.el.prop('disabled', true);
+ try {
+ this.screen.button(button.attributes);
+ } finally {
+ button.el.prop('disabled', false);
+ }
},
selected_records: function() {
if (this.screen.current_record) {
Index: src/view/tree.js
===================================================================
--- a/public_data/sao/src/view/tree.js
+++ b/public_data/sao/src/view/tree.js
@@ -1509,7 +1509,7 @@
},
render: function(record) {
var button = new Sao.common.Button(this.attributes);
- button.el.click(record, this.button_clicked.bind(this));
+ button.el.click([record, button], this.button_clicked.bind(this));
var fields = jQuery.map(this.screen.model.fields,
function(field, name) {
if ((field.description.loading || 'eager') ==
@@ -1526,7 +1526,8 @@
return button.el;
},
button_clicked: function(event) {
- var record = event.data;
+ var record = event.data[0];
+ var button = event.data[1];
if (record != this.screen.current_record) {
return;
}
@@ -1534,7 +1535,12 @@
if (states.invisible || states.readonly) {
return;
}
- this.screen.button(this.attributes);
+ button.el.prop('disabled', true);
+ try {
+ this.screen.button(this.attributes);
+ } finally {
+ button.el.prop('disabled', false);
+ }
}
});

View File

@ -1,29 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Correctly show reference and party on invoice rec_name
issue4878
review18481003
Index: trytond/trytond/modules/account_invoice/invoice.py
===================================================================
--- a/trytond/trytond/modules/account_invoice/invoice.py
+++ b/trytond/trytond/modules/account_invoice/invoice.py
@@ -942,9 +942,12 @@
cls.raise_user_error('modify_invoice', (invoice.rec_name,))
def get_rec_name(self, name):
- return (self.number or unicode(self.id)
- + (self.reference and (' ' + self.reference) or '')
- + ' ' + self.party.rec_name)
+ name = self.number or unicode(self.id)
+ if self.reference:
+ name += ' %s' % self.reference
+ if self.party:
+ name += ' %s' % self.party.rec_name
+ return name
@classmethod
def search_rec_name(cls, name, clause):

View File

@ -1,38 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Allow to customize productions code
issue5144
review18801002
Index: trytond/trytond/modules/production/production.py
===================================================================
--- a/trytond/trytond/modules/production/production.py
+++ b/trytond/trytond/modules/production/production.py
@@ -446,7 +446,8 @@
vlist = [x.copy() for x in vlist]
config = Config(1)
for values in vlist:
- values['code'] = Sequence.get_id(config.production_sequence.id)
+ if not values.get('code'):
+ values['code'] = Sequence.get_id(config.production_sequence.id)
productions = super(Production, cls).create(vlist)
for production in productions:
production._set_move_planned_date()
@@ -458,6 +459,14 @@
for production in sum(args[::2], []):
production._set_move_planned_date()
+ @classmethod
+ def copy(cls, productions, default=None):
+ if default is None:
+ default = {}
+ default = default.copy()
+ default.setdefault('code', None)
+ return super(Production, cls).copy(productions, default=default)
+
def _get_move_planned_date(self):
"Return the planned dates for input and output moves"
return self.planned_date, self.planned_date

View File

@ -1,75 +0,0 @@
# HG changeset patch
# User Cédric Krier <cedric.krier@b2ck.com>
Execute action synchronously
The clicked event must be blocked when the action is started, so the retrieval
of the action definition should be synchronous to be done inside the
try/finally.
issue5362
review23901002
Index: tryton/action/main.py
===================================================================
--- a/tryton/tryton/action/main.py
+++ b/tryton/tryton/action/main.py
@@ -54,31 +54,16 @@
@staticmethod
def execute(act_id, data, action_type=None, context=None):
- def get_action_type(actions):
- try:
- action, = actions()
- except RPCException:
- return
+ # Must be executed synchronously to avoid double execution
+ # on double click.
+ if not action_type:
+ action, = RPCExecute('model', 'ir.action', 'read', [act_id],
+ ['type'], context=context)
action_type = action['type']
- exec_action(action_type)
-
- def exec_action(action_type):
- def callback(actions):
- try:
- action, = actions()
- except RPCException:
- return
- Action._exec_action(action, data, context=context)
-
- RPCExecute('model', action_type, 'search_read',
- [('action', '=', act_id)], 0, 1, None, None,
- context=context, callback=callback)
-
- if not action_type:
- RPCExecute('model', 'ir.action', 'read', [act_id],
- ['type'], context=context, callback=get_action_type)
- else:
- exec_action(action_type)
+ action, = RPCExecute('model', action_type, 'search_read',
+ [('action', '=', act_id)], 0, 1, None, None,
+ context=context)
+ Action._exec_action(action, data, context=context)
@staticmethod
def _exec_action(action, data=None, context=None):
Index: tryton/gui/window/view_form/view/list_gtk/widget.py
===================================================================
--- a/tryton/tryton/gui/window/view_form/view/list_gtk/widget.py
+++ b/tryton/tryton/gui/window/view_form/view/list_gtk/widget.py
@@ -909,4 +909,8 @@
if state_changes.get('invisible') \
or state_changes.get('readonly'):
return True
- self.view.screen.button(self.attrs)
+ widget.handler_block_by_func(self.button_clicked)
+ try:
+ self.view.screen.button(self.attrs)
+ finally:
+ widget.handler_unblock_by_func(self.button_clicked)

View File

@ -1,31 +0,0 @@
diff -r ad935d7f423e trytond/trytond/modules/stock/location.py
--- a/trytond/trytond/modules/stock/location.py Mon Mar 28 10:34:04 2016 +0200
+++ b/trytond/trytond/modules/stock/location.py Thu Apr 07 11:25:56 2016 +0200
@@ -224,6 +224,11 @@
return [(cls._rec_name,) + tuple(clause[1:])]
@classmethod
+ def _quantity_grouping_and_key(cls):
+ product_id = Transaction().context['product']
+ return ('product', ), (product_id,)
+
+ @classmethod
def get_quantity(cls, locations, name):
pool = Pool()
Product = pool.get('product.product')
@@ -255,12 +260,13 @@
pbl = {}
for sub_locations in grouped_slice(locations):
location_ids = [l.id for l in sub_locations]
+ grouping, key = cls._quantity_grouping_and_key()
with Transaction().set_context(context):
pbl.update(Product.products_by_location(
location_ids=location_ids, product_ids=[product_id],
- with_childs=True))
+ with_childs=True, grouping=grouping))
- return dict((loc.id, pbl.get((loc.id, product_id), 0))
+ return dict((loc.id, pbl.get((loc.id,) + key, 0))
for loc in locations)
@classmethod

View File

@ -1,304 +0,0 @@
diff -r 8513232c6649 trytond/trytond/modules/stock_lot/__init__.py
--- a/trytond/trytond/modules/stock_lot/__init__.py Sat Feb 27 00:34:46 2016 +0100
+++ b/trytond/trytond/modules/stock_lot/__init__.py Thu Apr 07 11:02:06 2016 +0200
@@ -21,4 +21,9 @@
Template,
Product,
TemplateLotType,
+ Location,
+ LotByLocationStart,
module='stock_lot', type_='model')
+ Pool.register(
+ LotByLocation,
+ module='stock_lot', type_='wizard')
diff -r 8513232c6649 locale/ca_ES.po
--- a/trytond/trytond/modules/stock_lot/locale/ca_ES.po Sat Feb 27 00:34:46 2016 +0100
+++ b/trytond/trytond/modules/stock_lot/locale/ca_ES.po Thu Apr 07 11:02:06 2016 +0200
@@ -86,6 +86,14 @@
msgid "Write User"
msgstr "Usuari modificació"
+msgctxt "field:stock.lot.by_location.start,forecast_date:"
+msgid "At Date"
+msgstr "A data"
+
+msgctxt "field:stock.lot.by_location.start,id:"
+msgid "ID"
+msgstr "Identificador"
+
msgctxt "field:stock.lot.type,code:"
msgid "Code"
msgstr "Codi"
@@ -174,6 +182,16 @@
msgid "The type of location for which lot is required"
msgstr "Tipus d'ubicació per la qual el lot és obligatori."
+msgctxt "help:stock.lot.by_location.start,forecast_date:"
+msgid ""
+"Allow to compute expected stock quantities for this date.\n"
+"* An empty value is an infinite date in the future.\n"
+"* A date in the past will provide historical values."
+msgstr ""
+"Permet calcular les quantitats previstes d'estoc per a aquesta data.\n"
+"* Un valor buit és un data infinita en el futur.\n"
+"* Una data en el passat proporcionarà valors històrics."
+
msgctxt "model:ir.action,name:act_lot_form"
msgid "Lots"
msgstr "Lots"
@@ -182,6 +200,10 @@
msgid "Moves"
msgstr "Moviments"
+msgctxt "model:ir.action,name:wizard_lot_by_location"
+msgid "Lot by Locations"
+msgstr "Lots per ubicació"
+
msgctxt "model:ir.ui.menu,name:menu_lot_form"
msgid "Lots"
msgstr "Lots"
@@ -194,6 +216,10 @@
msgid "Stock Lot"
msgstr "Lot"
+msgctxt "model:stock.lot.by_location.start,name:"
+msgid "Lot by Location"
+msgstr "Lot per ubicació"
+
msgctxt "model:stock.lot.type,name:"
msgid "Stock Lot Type"
msgstr "Tipus de lot"
@@ -226,6 +252,10 @@
msgid "Lots"
msgstr "Lots"
+msgctxt "view:stock.lot.by_location.start:"
+msgid "Lot by Location"
+msgstr "Lot per ubicació"
+
msgctxt "view:stock.lot:"
msgid "Lot"
msgstr "Lot"
@@ -241,3 +271,11 @@
msgctxt "view:stock.period.cache.lot:"
msgid "Period Lot Caches"
msgstr "Períodes d'estoc precalculat "
+
+msgctxt "wizard_button:stock.lot.by_location,start,end:"
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgctxt "wizard_button:stock.lot.by_location,start,open:"
+msgid "Open"
+msgstr "Obre"
diff -r 8513232c6649 trytond/trytond/modules/stock_lot/locale/es_ES.po
--- a/trytond/trytond/modules/stock_lot/locale/es_ES.po Sat Feb 27 00:34:46 2016 +0100
+++ b/trytond/trytond/modules/stock_lot/locale/es_ES.po Thu Apr 07 11:02:06 2016 +0200
@@ -86,6 +86,14 @@
msgid "Write User"
msgstr "Usuario modificación"
+msgctxt "field:stock.lot.by_location.start,forecast_date:"
+msgid "At Date"
+msgstr "A fecha"
+
+msgctxt "field:stock.lot.by_location.start,id:"
+msgid "ID"
+msgstr "Identificador"
+
msgctxt "field:stock.lot.type,code:"
msgid "Code"
msgstr "Código"
@@ -174,6 +182,16 @@
msgid "The type of location for which lot is required"
msgstr "El tipo de ubicación en la que el lote es obligatorio."
+msgctxt "help:stock.lot.by_location.start,forecast_date:"
+msgid ""
+"Allow to compute expected stock quantities for this date.\n"
+"* An empty value is an infinite date in the future.\n"
+"* A date in the past will provide historical values."
+msgstr ""
+"Permite calcular las cantidades previstas de stock para esta fecha.\n"
+"* Un valor vacío es un fecha infinita en el futuro.\n"
+"* Una fecha en el pasado proporcionará valores históricos."
+
msgctxt "model:ir.action,name:act_lot_form"
msgid "Lots"
msgstr "Lotes"
@@ -182,6 +200,10 @@
msgid "Moves"
msgstr "Movimientos"
+msgctxt "model:ir.action,name:wizard_lot_by_location"
+msgid "Lot by Locations"
+msgstr "Lotes por ubicación"
+
msgctxt "model:ir.ui.menu,name:menu_lot_form"
msgid "Lots"
msgstr "Lotes"
@@ -194,6 +216,10 @@
msgid "Stock Lot"
msgstr "Lote stock"
+msgctxt "model:stock.lot.by_location.start,name:"
+msgid "Lot by Location"
+msgstr "Lote por ubicación"
+
msgctxt "model:stock.lot.type,name:"
msgid "Stock Lot Type"
msgstr "Tipo lote stock"
@@ -226,6 +252,10 @@
msgid "Lots"
msgstr "Lotes"
+msgctxt "view:stock.lot.by_location.start:"
+msgid "Lot by Location"
+msgstr "Lote por ubicación"
+
msgctxt "view:stock.lot:"
msgid "Lot"
msgstr "Lote"
@@ -241,3 +271,11 @@
msgctxt "view:stock.period.cache.lot:"
msgid "Period Lot Caches"
msgstr "Período lote precalculados"
+
+msgctxt "wizard_button:stock.lot.by_location,start,end:"
+msgid "Cancel"
+msgstr "Cancel·lar"
+
+msgctxt "wizard_button:stock.lot.by_location,start,open:"
+msgid "Open"
+msgstr "Abrir"
diff -r 8513232c6649 trytond/trytond/modules/stock_lot/stock.py
--- a/trytond/trytond/modules/stock_lot/stock.py Sat Feb 27 00:34:46 2016 +0100
+++ b/trytond/trytond/modules/stock_lot/stock.py Thu Apr 07 11:02:06 2016 +0200
@@ -1,15 +1,18 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
+import datetime
from trytond.model import ModelView, ModelSQL, fields
-from trytond.pyson import Eval
+from trytond.pyson import Eval, PYSONEncoder
from trytond.pool import Pool, PoolMeta
from trytond.transaction import Transaction
+from trytond.wizard import Wizard, StateView, StateAction, Button
from trytond.modules.stock import StockMixin
__all__ = ['Lot', 'LotType', 'Move', 'ShipmentIn', 'ShipmentOut',
'ShipmentOutReturn',
'Period', 'PeriodCacheLot',
- 'Inventory', 'InventoryLine']
+ 'Inventory', 'InventoryLine', 'Location', 'LotByLocationStart',
+ 'LotByLocation']
class Lot(ModelSQL, ModelView, StockMixin):
@@ -216,3 +219,74 @@
if move:
move.lot = self.lot
return move
+
+
+class Location:
+ __name__ = 'stock.location'
+ __metaclass__ = PoolMeta
+
+ @classmethod
+ def _quantity_grouping_and_key(cls):
+ if Transaction().context.get('lot'):
+ lot_id = Transaction().context['lot']
+ product_id = Transaction().context['product']
+ return ('product', 'lot'), (product_id, lot_id)
+ return super(Location, cls)._quantity_grouping_and_key()
+
+
+class LotByLocationStart(ModelView):
+ 'Lot by Location'
+ __name__ = 'stock.lot.by_location.start'
+ forecast_date = fields.Date(
+ 'At Date', help=('Allow to compute expected '
+ 'stock quantities for this date.\n'
+ '* An empty value is an infinite date in the future.\n'
+ '* A date in the past will provide historical values.'))
+
+ @staticmethod
+ def default_forecast_date():
+ Date = Pool().get('ir.date')
+ return Date.today()
+
+
+class LotByLocation(Wizard):
+ 'Lot by Location'
+ __name__ = 'stock.lot.by_location'
+ start = StateView('stock.lot.by_location.start',
+ 'stock_lot.lot_by_location_start_view_form', [
+ Button('Cancel', 'end', 'tryton-cancel'),
+ Button('Open', 'open', 'tryton-ok', default=True),
+ ])
+ open = StateAction('stock.act_location_quantity_tree')
+
+ def do_open(self, action):
+ pool = Pool()
+ Lot = pool.get('stock.lot')
+ Lang = pool.get('ir.lang')
+
+ context = {}
+ lot_id = Transaction().context['active_id']
+ context['lot'] = lot_id
+
+ lot = Lot(lot_id)
+ context['product'] = lot.product.id
+
+ if self.start.forecast_date:
+ context['stock_date_end'] = self.start.forecast_date
+ else:
+ context['stock_date_end'] = datetime.date.max
+ action['pyson_context'] = PYSONEncoder().encode(context)
+
+ for code in [Transaction().language, 'en_US']:
+ langs = Lang.search([
+ ('code', '=', code),
+ ])
+ if langs:
+ break
+ lang, = langs
+ date = Lang.strftime(context['stock_date_end'],
+ lang.code, lang.date)
+
+ action['name'] += ' - %s (%s) @ %s' % (lot.rec_name,
+ lot.product.default_uom.rec_name, date)
+ return action, {}
diff -r 8513232c6649 trytond/trytond/modules/stock_lot/stock.xml
--- a/trytond/trytond/modules/stock_lot/stock.xml Sat Feb 27 00:34:46 2016 +0100
+++ b/trytond/trytond/modules/stock_lot/stock.xml Thu Apr 07 11:02:06 2016 +0200
@@ -62,6 +62,28 @@
<field name="action" ref="act_move_form_relate_lot"/>
</record>
+ <record model="ir.action.wizard" id="wizard_lot_by_location">
+ <field name="name">Lot by Locations</field>
+ <field name="wiz_name">stock.lot.by_location</field>
+ <field name="model">stock.lot</field>
+ </record>
+ <record model="ir.action.keyword" id="act_location_quantity_keyword1">
+ <field name="keyword">form_relate</field>
+ <field name="model">stock.lot,-1</field>
+ <field name="action" ref="wizard_lot_by_location"/>
+ </record>
+ <record model="ir.action-res.group"
+ id="wizard_lot_by_location-group_stock">
+ <field name="action" ref="wizard_lot_by_location"/>
+ <field name="group" ref="stock.group_stock"/>
+ </record>
+
+ <record model="ir.ui.view" id="lot_by_location_start_view_form">
+ <field name="model">stock.lot.by_location.start</field>
+ <field name="type">form</field>
+ <field name="name">lot_by_location_start_form</field>
+ </record>
+
<record model="stock.lot.type" id="type_supplier">
<field name="code">supplier</field>
<field name="name">Supplier</field>

View File

@ -1,115 +0,0 @@
diff -r f9ff7d1399d1 stock.py
--- a/trytond/trytond/modules/sale/stock.py Fri Sep 04 16:30:54 2015 +0200
+++ b/trytond/trytond/modules/sale/stock.py Fri Sep 04 16:31:35 2015 +0200
@@ -1,5 +1,6 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
+from itertools import ifilter
from sql import Null
from sql.operators import Concat
@@ -61,6 +62,35 @@
return super(ShipmentOut, cls).draft(shipments)
+ def get_origins(self, name):
+ return ', '.join(set(ifilter(None, (m.origin_name
+ for m in self.outgoing_moves))))
+
+ @classmethod
+ def _sync_inventory_to_outgoing_grouping_key(cls, move, type):
+ pool = Pool()
+ Move = pool.get('stock.move')
+ key = super(ShipmentOut,
+ cls)._sync_inventory_to_outgoing_grouping_key(move, type)
+ if type == 'outgoing':
+ key = tuple([key, move.origin])
+ if (type == 'inventory' and move.origin and
+ isinstance(move.origin, Move)):
+ key = tuple([key, move.origin.origin])
+ return key
+
+ def _get_outgoing_move(self, move):
+ new_move = super(ShipmentOut, self)._get_outgoing_move(move)
+ if new_move:
+ new_move.origin = move
+ return new_move
+
+ def _get_inventory_move(self, move):
+ new_move = super(ShipmentOut, self)._get_inventory_move(move)
+ if new_move:
+ new_move.origin = move
+ return new_move
+
class ShipmentOutReturn:
__name__ = 'stock.shipment.out.return'
@@ -147,6 +177,7 @@
@classmethod
def _get_origin(cls):
models = super(Move, cls)._get_origin()
+ models.append('stock.move')
models.append('sale.line')
return models
diff -r f9ff7d1399d1 tests/scenario_sale.rst
--- a/trytond/trytond/modules/sale/tests/scenario_sale.rst Fri Sep 04 16:30:54 2015 +0200
+++ b/trytond/trytond/modules/sale/tests/scenario_sale.rst Fri Sep 04 16:31:35 2015 +0200
@@ -771,3 +771,57 @@
5.0
>>> stock_move.state
u'draft'
+
+Create a sale with the same products with diferent price to be invoiced on
+shipment and check correctly invoiced::
+
+ >>> sale = Sale()
+ >>> sale.party = customer
+ >>> sale.payment_term = payment_term
+ >>> sale.invoice_method = 'shipment'
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10.0
+ >>> line = sale.lines.new()
+ >>> line.product = product
+ >>> line.quantity = 10.0
+ >>> line.unit_price = Decimal('9.0000')
+ >>> sale.click('quote')
+ >>> sale.click('confirm')
+ >>> sale.click('process')
+ >>> shipment, = sale.shipments
+ >>> config.user = stock_user.id
+ >>> for move in shipment.inventory_moves:
+ ... move.quantity = 5.0
+ >>> shipment.click('assign_try')
+ True
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> config.user = sale_user.id
+ >>> sale.reload()
+ >>> invoice, = sale.invoices
+ >>> _, shipment, = sale.shipments
+ >>> invoice.untaxed_amount
+ Decimal('95.00')
+ >>> first_line, second_line = sorted(invoice.lines,
+ ... key=lambda a: a.unit_price)
+ >>> first_line.unit_price
+ Decimal('9.0000')
+ >>> second_line.unit_price
+ Decimal('10.0000')
+ >>> config.user = stock_user.id
+ >>> shipment.click('assign_try')
+ True
+ >>> shipment.click('pack')
+ >>> shipment.click('done')
+ >>> config.user = sale_user.id
+ >>> sale.reload()
+ >>> _, invoice = sale.invoices
+ >>> invoice.untaxed_amount
+ Decimal('95.00')
+ >>> first_line, second_line = sorted(invoice.lines,
+ ... key=lambda a: a.unit_price)
+ >>> first_line.unit_price
+ Decimal('9.0000')
+ >>> second_line.unit_price
+ Decimal('10.0000')

View File

@ -1,81 +0,0 @@
diff -r 8684df73e037 shipment.py
--- a/trytond/trytond/modules/stock/shipment.py Fri Sep 04 16:29:38 2015 +0200
+++ b/trytond/trytond/modules/stock/shipment.py Fri Sep 04 16:30:32 2015 +0200
@@ -1118,6 +1118,14 @@
unit_price=move.unit_price,
)
+ @staticmethod
+ def _sync_inventory_to_outgoing_grouping_key(move, type):
+ '''
+ Returns the key used to sync inventory and outgoing moves for move
+ Type contains outgoing or incomming to indicate the kind of move
+ '''
+ return move.product.id
+
@classmethod
def _sync_inventory_to_outgoing(cls, shipments, create=True, write=True):
'Synchronise outgoing moves with inventory moves'
@@ -1132,8 +1140,10 @@
continue
quantity = Uom.compute_qty(move.uom, move.quantity,
move.product.default_uom, round=False)
- outgoing_qty.setdefault(move.product.id, 0.0)
- outgoing_qty[move.product.id] += quantity
+ key = cls._sync_inventory_to_outgoing_grouping_key(move,
+ 'outgoing')
+ outgoing_qty.setdefault(key, 0.0)
+ outgoing_qty[key] += quantity
to_create = []
for move in shipment.inventory_moves:
@@ -1141,19 +1151,20 @@
continue
qty_default_uom = Uom.compute_qty(move.uom, move.quantity,
move.product.default_uom, round=False)
+ key = cls._sync_inventory_to_outgoing_grouping_key(move,
+ 'inventory')
# Check if the outgoing move doesn't exist already
- if outgoing_qty.get(move.product.id):
+ if outgoing_qty.get(key):
# If it exist, decrease the sum
- if qty_default_uom <= outgoing_qty[move.product.id]:
- outgoing_qty[move.product.id] -= qty_default_uom
+ if qty_default_uom <= outgoing_qty[key]:
+ outgoing_qty[key] -= qty_default_uom
continue
# Else create the complement
else:
- out_quantity = (qty_default_uom
- - outgoing_qty[move.product.id])
+ out_quantity = (qty_default_uom - outgoing_qty[key])
out_quantity = Uom.compute_qty(
move.product.default_uom, out_quantity, move.uom)
- outgoing_qty[move.product.id] = 0.0
+ outgoing_qty[key] = 0.0
else:
out_quantity = move.quantity
@@ -1171,9 +1182,11 @@
for move in shipment.outgoing_moves:
if move.state == 'cancel':
continue
- if outgoing_qty.get(move.product.id, 0.0) > 0.0:
+ key = cls._sync_inventory_to_outgoing_grouping_key(move,
+ 'outgoing')
+ if outgoing_qty.get(key, 0.0) > 0.0:
exc_qty = Uom.compute_qty(move.product.default_uom,
- outgoing_qty[move.product.id], move.uom)
+ outgoing_qty[key], move.uom)
removed_qty = Uom.compute_qty(move.uom,
min(exc_qty, move.quantity), move.product.default_uom,
round=False)
@@ -1181,7 +1194,7 @@
Move.write([move], {
'quantity': max(0.0, move.quantity - exc_qty),
})
- outgoing_qty[move.product.id] -= removed_qty
+ outgoing_qty[key] -= removed_qty
@classmethod
@ModelView.button

View File

@ -1,19 +0,0 @@
diff -r 90cc3f4c20c9 trytond/trytond/model/modelstorage.py
--- a/trytond/trytond/model/modelstorage.py Tue Sep 22 16:39:45 2015 +0200
+++ b/trytond/trytond/model/modelstorage.py Tue Sep 22 16:40:32 2015 +0200
@@ -952,10 +952,11 @@
if relations:
for sub_relations in grouped_slice(relations):
sub_relations = set(sub_relations)
- finds = Relation.search(['AND',
- [('id', 'in', [r.id for r in sub_relations])],
- domain,
- ])
+ with Transaction().set_user(0):
+ finds = Relation.search(['AND',
+ [('id', 'in', [r.id for r in sub_relations])],
+ domain,
+ ])
if sub_relations != set(finds):
cls.raise_user_error('domain_validation_record',
error_args=cls._get_error_args(field.name))

View File

@ -1,27 +0,0 @@
diff -r 8dec33688c06 trytond/trytond/model/modelsql.py
--- a/trytond/trytond/model/modelsql.py Tue Nov 03 12:20:49 2015 +0100
+++ b/trytond/trytond/model/modelsql.py Wed Nov 11 09:57:58 2015 +0100
@@ -128,6 +128,8 @@
def __register__(cls, module_name):
TableHandler = backend.get('TableHandler')
super(ModelSQL, cls).__register__(module_name)
+ pool = Pool()
+ ModelField = pool.get('ir.model.field')
if cls.table_query():
return
@@ -205,7 +207,13 @@
if isinstance(field, fields.Many2One) \
and field.model_name == cls.__name__ \
and field.left and field.right:
- cls._rebuild_tree(field_name, None, 0)
+ irfields = ModelField.search([
+ ('model.model', '=', field.model_name),
+ ('module', '=', module_name),
+ ('name', 'in', [field.left, field.right]),
+ ])
+ if irfields:
+ cls._rebuild_tree(field_name, None, 0)
for ident, constraint, _ in cls._sql_constraints:
table.add_constraint(ident, constraint)

View File

@ -1,148 +0,0 @@
# HG changeset patch
# User Guillem Barba <guillembarba@gmail.com>
use method to compute balance, credit and debit getters query
issue4543
review6021003
Index: account.py
===================================================================
--- .a/trytond/trytond/modules/analytic_account/account.py
+++ .b/trytond/trytond/modules/analytic_account/account.py
@@ -124,17 +124,8 @@
def get_balance(cls, accounts, name):
res = {}
pool = Pool()
- Line = pool.get('analytic_account.line')
- MoveLine = pool.get('account.move.line')
- Account = pool.get('account.account')
- Company = pool.get('company.company')
Currency = pool.get('currency.currency')
cursor = Transaction().connection.cursor()
- table = cls.__table__()
- line = Line.__table__()
- move_line = MoveLine.__table__()
- a_account = Account.__table__()
- company = Company.__table__()
ids = [a.id for a in accounts]
childs = cls.search([('parent', 'child_of', ids)])
@@ -145,25 +136,12 @@
for account in all_accounts:
id2account[account.id] = account
- line_query = Line.query_get(line)
- cursor.execute(*table.join(line, 'LEFT',
- condition=table.id == line.account
- ).join(move_line, 'LEFT',
- condition=move_line.id == line.move_line
- ).join(a_account, 'LEFT',
- condition=a_account.id == move_line.account
- ).join(company, 'LEFT',
- condition=company.id == a_account.company
- ).select(table.id,
- Sum(Coalesce(line.debit, 0) - Coalesce(line.credit, 0)),
- company.currency,
- where=(table.type != 'view')
- & table.id.in_(all_ids)
- & (table.active == True) & line_query,
- group_by=(table.id, company.currency)))
+ query = cls.query_get(all_ids, [name])
+ cursor.execute(*query)
+
account_sum = {}
id2currency = {}
- for account_id, sum, currency_id in cursor.fetchall():
+ for account_id, currency_id, sum in cursor.fetchall():
account_sum.setdefault(account_id, Decimal('0.0'))
# SQLite uses float for SUM
if not isinstance(sum, Decimal):
@@ -200,17 +178,8 @@
@classmethod
def get_credit_debit(cls, accounts, names):
pool = Pool()
- Line = pool.get('analytic_account.line')
- MoveLine = pool.get('account.move.line')
- Account = pool.get('account.account')
- Company = pool.get('company.company')
Currency = pool.get('currency.currency')
cursor = Transaction().connection.cursor()
- table = cls.__table__()
- line = Line.__table__()
- move_line = MoveLine.__table__()
- a_account = Account.__table__()
- company = Company.__table__()
result = {}
ids = [a.id for a in accounts]
@@ -223,23 +192,8 @@
for account in accounts:
id2account[account.id] = account
- line_query = Line.query_get(line)
- columns = [table.id, company.currency]
- for name in names:
- columns.append(Sum(Coalesce(Column(line, name), 0)))
- cursor.execute(*table.join(line, 'LEFT',
- condition=table.id == line.account
- ).join(move_line, 'LEFT',
- condition=move_line.id == line.move_line
- ).join(a_account, 'LEFT',
- condition=a_account.id == move_line.account
- ).join(company, 'LEFT',
- condition=company.id == a_account.company
- ).select(*columns,
- where=(table.type != 'view')
- & table.id.in_(ids)
- & (table.active == True) & line_query,
- group_by=(table.id, company.currency)))
+ query = cls.query_get(ids, names)
+ cursor.execute(*query)
id2currency = {}
for row in cursor.fetchall():
@@ -263,6 +217,43 @@
result[name][account.id] += account.currency.round(sum)
return result
+ @classmethod
+ def query_get(cls, ids, names):
+ pool = Pool()
+ Line = pool.get('analytic_account.line')
+ MoveLine = pool.get('account.move.line')
+ Account = pool.get('account.account')
+ Company = pool.get('company.company')
+ table = cls.__table__()
+ line = Line.__table__()
+ move_line = MoveLine.__table__()
+ a_account = Account.__table__()
+ company = Company.__table__()
+
+ line_query = Line.query_get(line)
+
+ columns = [table.id, company.currency]
+ for name in names:
+ if name == 'balance':
+ columns.append(
+ Sum(Coalesce(line.debit, 0) - Coalesce(line.credit, 0)))
+ else:
+ columns.append(Sum(Coalesce(Column(line, name), 0)))
+ query = table.join(line, 'LEFT',
+ condition=table.id == line.account
+ ).join(move_line, 'LEFT',
+ condition=move_line.id == line.move_line
+ ).join(a_account, 'LEFT',
+ condition=a_account.id == move_line.account
+ ).join(company, 'LEFT',
+ condition=company.id == a_account.company
+ ).select(*columns,
+ where=(table.type != 'view')
+ & table.id.in_(ids)
+ & table.active & line_query,
+ group_by=(table.id, company.currency))
+ return query
+
def get_rec_name(self, name):
if self.code:
return self.code + ' - ' + unicode(self.name)

View File

@ -1,22 +0,0 @@
Index: trytond/trytond/modules/account_asset/asset.xml
===================================================================
--- a/trytond/trytond/modules/account_asset/asset.xml
+++ b/trytond/trytond/modules/account_asset/asset.xml
@@ -139,6 +139,16 @@
<field name="name">asset_line_tree</field>
</record>
+ <record model="ir.rule.group" id="rule_group_asset_line">
+ <field name="model" search="[('model', '=', 'account.asset.line')]"/>
+ <field name="global_p" eval="True"/>
+ </record>
+ <record model="ir.rule" id="rule_asset_line1">
+ <field name="domain" eval="[('asset.company', 'in', Eval('user', {}).get('companies', []))]" pyson="1"/>
+ <field name="rule_group" ref="rule_group_asset_line"/>
+ </record>
+
+
<record model="ir.model.access" id="access_asset_line">
<field name="model" search="[('model', '=', 'account.asset.line')]"/>
<field name="perm_read" eval="False"/>

View File

@ -1,29 +0,0 @@
# HG changeset patch
# User Sergi Almacellas Abellana <sergi@koolpi.com>
Fix copy of translated fields when records aren't read in order
issue4720
review9231002
Index: trytond/trytond/model/modelstorage.py
===================================================================
--- a/trytond/trytond/model/modelstorage.py
+++ b/trytond/trytond/model/modelstorage.py
@@ -301,11 +301,12 @@
if (not isinstance(f, fields.Function)
or isinstance(f, fields.Property))]
ids = map(int, records)
- datas = cls.read(ids, fields_names=fields_names)
+ datas = dict((d['id'], d) for d in cls.read(ids,
+ fields_names=fields_names))
field_defs = cls.fields_get(fields_names=fields_names)
to_create = []
- for data in datas:
- data = convert_data(field_defs, data)
+ for id in ids:
+ data = convert_data(field_defs, datas[id])
to_create.append(data)
new_records = cls.create(to_create)
new_ids = dict(izip(ids, map(int, new_records)))

View File

@ -1,22 +0,0 @@
diff -r 80fed5f82f06 invoice.py
--- a/trytond/trytond/modules/account_invoice/invoice.py Fri Nov 27 14:42:58 2015 +0100
+++ b/trytond/trytond/modules/account_invoice/invoice.py Fri Nov 27 14:43:25 2015 +0100
@@ -14,7 +14,7 @@
from trytond.wizard import Wizard, StateView, StateTransition, StateAction, \
Button
from trytond import backend
-from trytond.pyson import If, Eval, Bool, Id
+from trytond.pyson import PYSONEncoder, If, Eval, Bool, Id
from trytond.tools import reduce_ids, grouped_slice
from trytond.transaction import Transaction
from trytond.pool import Pool
@@ -2773,6 +2773,9 @@
credit_invoices = Invoice.credit(invoices, refund=refund)
data = {'res_id': [i.id for i in credit_invoices]}
+ action['pyson_domain'] = PYSONEncoder().encode([
+ ('id', 'in', [i.id for i in credit_invoices]),
+ ])
if len(credit_invoices) == 1:
action['views'].reverse()
return action, data

View File

@ -1,13 +0,0 @@
diff -r 7658cd8c2e7f cron.py
--- a/trytond/trytond/modules/company/cron.py Fri Oct 02 08:56:51 2015 +0200
+++ b/trytond/trytond/modules/company/cron.py Mon Nov 23 12:35:33 2015 +0100
@@ -23,7 +23,8 @@
for company in cron.companies:
User.write([cron.user], {
'company': company.id,
- 'main_company': company.id,
+ 'main_company': (company.parent.id if company.parent
+ else company.id),
})
with Transaction().set_context(company=company.id):
super(Cron, cls)._callback(cron)

View File

@ -1,12 +0,0 @@
diff -r 39138b20bd95 purchase.py
--- a/trytond/trytond/modules/purchase/purchase.py Mon Nov 02 16:10:40 2015 +0100
+++ b/trytond/trytond/modules/purchase/purchase.py Wed Nov 11 11:44:30 2015 +0100
@@ -1011,7 +1011,7 @@
break
quantity -= Uom.compute_qty(move.uom, move.quantity, self.unit)
if done:
- if quantity > 0.0:
+ if quantity > self.unit.rounding:
done = False
return done

View File

@ -1,147 +0,0 @@
diff -r 1e58052bb56f public_html/sao/index.html
--- a/public_html/sao/index.html Thu May 12 09:42:53 2016 +0200
+++ b/public_html/sao/index.html Fri May 20 10:17:38 2016 +0200
@@ -25,6 +25,7 @@
<script type="text/javascript" src="dist/tryton-sao.min.js"></script>
<link rel="stylesheet" type="text/css" href="dist/tryton-sao.min.css"
media="screen"/>
+ <link rel="stylesheet" type="text/css" href="theme/nantic/tryton-nantic.css" media="screen"/>
<script type="text/javascript">
if (typeof Sao == 'undefined') {
document.write(unescape('%3cscript type="text/javascript" src="dist/tryton-sao.js"%3e%3c/script%3e'));
@@ -33,22 +34,24 @@
</script>
</head>
<body>
- <nav class="navbar navbar-default" role="navigation" style="margin-bottom: 1px;">
+ <nav class="navbar navbar-default navbar-main" role="navigation" style="margin-bottom: 1px;">
<div class="container-fluid">
- <div class="navbar-header">
+ <div class="navbar-header navbar-header-main">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#user_menu_collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
- <a class="navbar-brand" href="#">Tryton</a>
- <p class="pull-left visible-xs visible-sm navbar-text">
- <button type="button" class="btn btn-primary btn-xs"
- data-toggle="offcanvas">
- Toggle menu
- </button>
- </p>
+ <a class="navbar-brand" href="#">
+ <img alt="Tryton Nan·TIC" src="theme/nantic/logo-w.png" class="logo">
+ </a>
+ <button id="toggle-menu" type="button" class="navbar-toggle collapsed"
+ data-toggle="offcanvas">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
</div>
<div class="collapse navbar-collapse" id="user_menu_collapse">
<ul class="nav navbar-nav">
@@ -81,13 +84,16 @@
jQuery('.row-offcanvas').toggleClass('active');
});
jQuery('#tabs').on('ready', function() {
- if (jQuery(this).find('> .nav-tabs').children().length) {
- jQuery('.row-offcanvas').removeClass('active');
- } else {
- jQuery('.row-offcanvas').addClass('active');
+ if ($(window).width() < 991) {
+ if (jQuery(this).find('> .nav-tabs').children().length) {
+ jQuery('.row-offcanvas').removeClass('active');
+ } else {
+ jQuery('.row-offcanvas').addClass('active');
+ }
}
});
Sao.login();
+ jQuery('#toggle-menu').hide();
});
</script>
</body>
diff -r 1e58052bb56f public_html/sao/offcanvas.css
--- a/public_html/sao/offcanvas.css Thu May 12 09:42:53 2016 +0200
+++ b/public_html/sao/offcanvas.css Fri May 20 10:17:38 2016 +0200
@@ -2,6 +2,47 @@
* Off Canvas
* --------------------------------------------------
*/
+@media screen and (min-width: 991px) {
+ .row-offcanvas {
+ position: relative;
+ -webkit-transition: all .25s ease-out;
+ -o-transition: all .25s ease-out;
+ transition: all .25s ease-out;
+ }
+
+ .row-offcanvas-right {
+ right: 0;
+ }
+
+ .row-offcanvas-left {
+ left: 0;
+ }
+
+ .row-offcanvas-right
+ .sidebar-offcanvas {
+ right: calc(-20% + 7px);
+ }
+
+ .row-offcanvas-left
+ .sidebar-offcanvas {
+ left: calc(-20% + 7.5px);
+ }
+
+ .row-offcanvas-right.active {
+ right: calc(20% + 7.5px);
+ }
+
+ .row-offcanvas-left.active {
+ left: calc(20% + 7.5px);
+ }
+
+ .sidebar-offcanvas {
+ position: absolute;
+ top: 0;
+ width: 20%;
+ }
+}
+
@media screen and (max-width: 991px) {
.row-offcanvas {
position: relative;
diff -r 1e58052bb56f public_html/sao/src/sao.js
--- a/public_html/sao/src/sao.js Thu May 12 09:42:53 2016 +0200
+++ b/public_html/sao/src/sao.js Fri May 20 10:17:38 2016 +0200
@@ -255,6 +255,7 @@
}).then(Sao.get_preferences).then(function(preferences) {
Sao.menu(preferences);
Sao.user_menu(preferences);
+ Sao.toggle_menu();
});
};
@@ -266,6 +267,7 @@
jQuery('#menu').children().remove();
document.title = 'Tryton';
session.do_logout().always(Sao.login);
+ $("#toggle-menu").hide();
});
};
@@ -294,6 +296,10 @@
}).click(Sao.logout).append(Sao.i18n.gettext('Logout')));
};
+ Sao.toggle_menu = function() {
+ $("#toggle-menu").show();
+ };
+
Sao.menu = function(preferences) {
var decoder = new Sao.PYSON.Decoder();
var action = decoder.decode(preferences.pyson_menu);

45
series
View File

@ -1,45 +0,0 @@
sao_nantic_theme.diff
account_move_line_rule.diff
issue154_316.diff
issue10467.diff
issue130_392_10919.diff
issue239_630.diff
issue240_631.diff
fix_wizard_copy.diff
issue6341003_1.diff
issue10391004_1.diff
issue13891002_20001.diff
issue10091002_1.diff
issue6021003_1.diff
stock_supply_production-performance-improvement.diff
top.diff
issue15211002-sale-confirmed-to-done.diff
issue13181002_1.diff
invoice_speedup.diff
babi_multiprocess.diff
domain_field.diff
issue18481003_1.diff
issue4950_stock.diff
issue4950_sale.diff
issue4986.diff
issue16661002_1.diff
workflow-performance.diff
analytic_account.diff
analytic_invoice.diff
analytic_sale.diff
analytic_purchase.diff
tax_active_invisible.diff
# Ignore next patches
#incremental_wait_in_retries.diff
# Uncomment in calfruitos
#fix_rounding_in_sync_inventory_to_outgoing.patch
#024726_account_bank_remove_company.diff
#024726_account_payment_type_remove_company.diff
#stock_lot_improve_sync_inventory_to_outgoing.diff
#stock_lot_fix_pick_product_without_outgoing_moves.diff
#purchase_fix_get_move_done_rounding.diff
#multicompany_cron.diff
#025476_5154_5155_5456_optimize_move_write_assign.diff
#do_not_lock_on_assign_try.diff
#limit_invoices_in_creit_note_action_by_domain.diff

View File

@ -1,12 +0,0 @@
diff -r 65f34a12a887 stock.py
--- a/trytond/trytond/modules/stock_lot/stock.py Mon Nov 02 11:25:25 2015 +0100
+++ b/trytond/trytond/modules/stock_lot/stock.py Mon Nov 02 11:26:16 2015 +0100
@@ -127,7 +127,7 @@
continue
quantity = Uom.compute_qty(move.uom, move.quantity,
move.product.default_uom, round=False)
- outgoing_moves = outgoing_by_product[move.product.id]
+ outgoing_moves = outgoing_by_product.get(move.product.id, [])
while outgoing_moves and quantity > 0:
out_move = outgoing_moves.pop()
out_quantity = Uom.compute_qty(out_move.uom,

View File

@ -1,28 +0,0 @@
diff -r 973556094501 stock.py
--- a/trytond/trytond/modules/stock_lot/stock.py Mon Oct 26 13:23:09 2015 +0100
+++ b/trytond/trytond/modules/stock_lot/stock.py Mon Oct 26 13:45:41 2015 +0100
@@ -133,19 +133,17 @@
out_quantity = Uom.compute_qty(out_move.uom,
out_move.quantity, out_move.product.default_uom,
round=False)
+ out_move_vals = {}
if quantity < out_quantity:
outgoing_moves.extend(Move.copy([out_move], default={
'quantity': Uom.round(
out_quantity - quantity,
out_move.uom.rounding),
}))
- Move.write([out_move], {
- 'quantity': Uom.round(
- quantity, out_move.uom.rounding),
- })
- Move.write([out_move], {
- 'lot': move.lot.id,
- })
+ out_move_vals['quantity'] = Uom.round(quantity,
+ out_move.uom.rounding)
+ out_move_vals['lot'] = move.lot.id
+ Move.write([out_move], out_move_vals)
quantity -= out_quantity
assert quantity <= move.product.default_uom.rounding

View File

@ -1,31 +0,0 @@
diff -r 4af84eb4246d product.py
--- a/trytond/trytond/modules/stock_supply_production/product.py Tue Feb 17 21:08:47 2015 +0100
+++ b/trytond/trytond/modules/stock_supply_production/product.py Wed Apr 15 17:57:32 2015 +0200
@@ -10,8 +10,10 @@
class Product:
__name__ = 'product.product'
- def get_supply_period(self):
- 'Return the supply period for the product'
+ @classmethod
+ def get_supply_periods(cls, products):
+ 'Return the supply period for each product'
pool = Pool()
Configuration = pool.get('production.configuration')
- return int(Configuration(1).supply_period or 0)
+ supply_period = int(Configuration(1).supply_period or 0)
+ return dict((p, supply_period) for p in products)
diff -r 4af84eb4246d production.py
--- a/trytond/trytond/modules/stock_supply_production/production.py Tue Feb 17 21:08:47 2015 +0100
+++ b/trytond/trytond/modules/stock_supply_production/production.py Wed Apr 15 17:57:32 2015 +0200
@@ -87,8 +87,8 @@
product_ids, with_childs=True)
# order product by supply period
- products_period = sorted((p.get_supply_period(), p)
- for p in sub_products)
+ products_period = sorted((sp, p) for p, sp
+ in Product.get_supply_periods(sub_products).iteritems())
for warehouse in warehouses:
quantities = dict((x, pbl.pop((warehouse.id, x), 0))

View File

@ -1,20 +0,0 @@
diff -r e09ed092a99d view/tax_code_list.xml
--- a/trytond/trytond/modules/account/view/tax_code_list.xml Sat Apr 02 15:59:02 2016 +0200
+++ b/trytond/trytond/modules/account/view/tax_code_list.xml Tue Apr 26 16:35:50 2016 +0200
@@ -5,5 +5,5 @@
<field name="name"/>
<field name="code"/>
<field name="company"/>
- <field name="active"/>
+ <field name="active" tree_invisible="1"/>
</tree>
diff -r e09ed092a99d view/tax_list.xml
--- a/trytond/trytond/modules/account/view/tax_list.xml Sat Apr 02 15:59:02 2016 +0200
+++ b/trytond/trytond/modules/account/view/tax_list.xml Tue Apr 26 16:35:50 2016 +0200
@@ -5,5 +5,5 @@
<field name="name"/>
<field name="group"/>
<field name="type"/>
- <field name="active"/>
+ <field name="active" tree_invisible="1"/>
</tree>

132
top.diff
View File

@ -1,132 +0,0 @@
diff -r 649b0805fa93 trytond/protocols/dispatcher.py
--- a/trytond/trytond/protocols/dispatcher.py Fri Feb 20 09:11:59 2015 +0100
+++ b/trytond/trytond/protocols/dispatcher.py Sun Apr 19 03:17:46 2015 +0200
@@ -20,6 +20,8 @@
from trytond.tools import is_instance_method
from trytond.wsgi import app
+import top
+
logger = logging.getLogger(__name__)
ir_configuration = Table('ir_configuration')
@@ -190,6 +192,16 @@
with Transaction().start(pool.database_name, user,
readonly=rpc.readonly) as transaction:
Cache.clean(pool.database_name)
+ action_id = top.add({
+ 'host': request.host,
+ 'port': '',
+ 'protocol': '',
+ 'database_name': pool.database_name,
+ 'user': user,
+ 'object_name': obj.__name__,
+ 'method': method,
+ 'args': repr(args)[:30],
+ })
try:
c_args, c_kwargs, transaction.context, transaction.timestamp \
= rpc.convert(obj, *args, **kwargs)
@@ -217,6 +229,8 @@
except Exception:
logger.error(log_message, *log_args, exc_info=True)
raise
+ finally:
+ top.remove(action_id)
Cache.resets(pool.database_name)
if request.authorization.type == 'session':
try:
diff -r 649b0805fa93 trytond/protocols/top.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/trytond/trytond/protocols/top.py Sun Apr 19 03:18:20 2015 +0200
@@ -0,0 +1,90 @@
+import random
+import signal
+import locale
+import faulthandler
+from operator import itemgetter
+from datetime import datetime
+
+current_actions = {}
+action_id = 0
+
+# Start Printing Tables
+# http://ginstrom.com/scribbles/2007/09/04/pretty-printing-a-table-in-python/
+
+def format_num(num):
+ """Format a number according to given places.
+ Adds commas, etc. Will truncate floats into ints!"""
+
+ try:
+ inum = int(num)
+ return locale.format("%.*f", (0, inum), True)
+
+ except (ValueError, TypeError):
+ return str(num)
+
+def get_max_width(table, index):
+ """Get the maximum width of the given column index"""
+ return max([len(format_num(row[index])) for row in table])
+
+def pprint_table(table):
+ """
+ Prints out a table of data, padded for alignment
+ @param table: The table to print. A list of lists.
+ Each row must have the same number of columns.
+ """
+ col_paddings = []
+
+ for i in range(len(table[0])):
+ col_paddings.append(get_max_width(table, i))
+
+ for row in table:
+ # left col
+ print row[0].ljust(col_paddings[0] + 1),
+ # rest of the cols
+ for i in range(1, len(row)):
+ col = format_num(row[i]).ljust(col_paddings[i] + 2)
+ print col,
+ print
+
+# End Printing Tables
+
+def signal_user_handler(signal, frame):
+ print '-' * 30
+ if current_actions:
+ key = current_actions.keys()[0]
+ header = sorted(current_actions[key].keys())
+ header = ('id', 'database_name', 'user', 'protocol', 'host', 'port',
+ 'timestamp', 'elapsed', 'object_name', 'method', 'args')
+ table = []
+ table.append([x.upper() for x in header])
+
+ for action in sorted(current_actions.values(), key=itemgetter('timestamp')):
+ row = []
+ for key in header:
+ value = action.get(key, '')
+ if key == 'elapsed':
+ value = (datetime.now() - action['timestamp']).total_seconds()
+ if isinstance(value, datetime):
+ value = value.ctime()
+ row.append(value)
+ table.append(row)
+ pprint_table(table)
+ print '=' * 30
+
+signal.signal(signal.SIGUSR1, signal_user_handler)
+faulthandler.register(signal.SIGUSR2)
+
+
+def add(value):
+ action_id = new_id()
+ value['timestamp'] = datetime.now()
+ value['elapsed'] = None
+ value['id'] = str(action_id)
+ current_actions[action_id] = value
+ return action_id
+
+def remove(action_id):
+ del current_actions[action_id]
+
+def new_id():
+ return random.randint(0, 999999)