Remove patches from default branch
Force to change branch before to apply patches
This commit is contained in:
parent
42883e71aa
commit
6e286c100f
|
@ -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"/>
|
|
@ -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
|
|
@ -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):
|
|
@ -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
|
@ -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>
|
|
@ -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>
|
|
@ -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',))]]
|
||||
|
|
@ -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',))]]
|
||||
|
|
@ -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',))]]
|
||||
|
|
@ -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
|
|
@ -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([
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -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):
|
|
@ -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):
|
|
@ -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:
|
|
@ -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"
|
|
@ -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)),
|
|
@ -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))
|
||||
+
|
|
@ -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')
|
|
@ -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
|
||||
|
|
@ -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"/>
|
||||
|
|
@ -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)
|
|
@ -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'
|
|
@ -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:
|
|
@ -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);
|
||||
+ }
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -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):
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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')
|
|
@ -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
|
|
@ -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))
|
|
@ -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)
|
|
@ -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)
|
|
@ -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"/>
|
|
@ -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)))
|
||||
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
||||
|
|
@ -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
45
series
|
@ -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
|
|
@ -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,
|
|
@ -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
|
||||
|
|
@ -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))
|
|
@ -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
132
top.diff
|
@ -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)
|
Loading…
Reference in New Issue