Merge pull request '6.8' (#5) from 6.8 into master
Reviewed-on: https://gitea.onecluster.org/OneTeam/trytondo-purchase_shop/pulls/5
This commit is contained in:
commit
6c5d0388fc
|
@ -201,3 +201,7 @@ msgstr "Tiendas"
|
||||||
msgctxt "view:purchase.shop:"
|
msgctxt "view:purchase.shop:"
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr "Usuarios"
|
msgstr "Usuarios"
|
||||||
|
|
||||||
|
msgctxt "field:purchase.shop,invoice_subtype:"
|
||||||
|
msgid "Subtype"
|
||||||
|
msgstr "Tipo de Documento"
|
||||||
|
|
6
party.py
6
party.py
|
@ -2,7 +2,6 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains
|
# The COPYRIGHT file at the top level of this repository contains
|
||||||
# the full copyright notices and license terms.
|
# the full copyright notices and license terms.
|
||||||
from trytond.model import fields
|
from trytond.model import fields
|
||||||
from trytond.pyson import Eval
|
|
||||||
from trytond.pool import PoolMeta
|
from trytond.pool import PoolMeta
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ class Party(metaclass=PoolMeta):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def default_shops():
|
def default_shops():
|
||||||
if Transaction().context.get('shops'):
|
if Transaction().context.get('shops'):
|
||||||
return Transaction().context.get('shops')
|
return Transaction().context.get('shops')
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,6 @@
|
||||||
this repository contains the full copyright notices and license terms. -->
|
this repository contains the full copyright notices and license terms. -->
|
||||||
<tryton>
|
<tryton>
|
||||||
<data>
|
<data>
|
||||||
<record model="ir.ui.view" id="party_view_tree">
|
|
||||||
<field name="model">party.party</field>
|
|
||||||
<field name="inherit" ref="party.party_view_tree"/>
|
|
||||||
<field name="name">party_tree</field>
|
|
||||||
</record>
|
|
||||||
<record model="ir.ui.view" id="party_view_form">
|
<record model="ir.ui.view" id="party_view_form">
|
||||||
<field name="model">party.party</field>
|
<field name="model">party.party</field>
|
||||||
<field name="inherit" ref="party.party_view_form"/>
|
<field name="inherit" ref="party.party_view_form"/>
|
||||||
|
|
32
purchase.py
32
purchase.py
|
@ -7,7 +7,6 @@ from trytond.model import fields
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.pool import Pool, PoolMeta
|
from trytond.pool import Pool, PoolMeta
|
||||||
from trytond.pyson import Bool, Eval
|
from trytond.pyson import Bool, Eval
|
||||||
from trytond.exceptions import UserError
|
|
||||||
|
|
||||||
__all__ = ['Purchase', 'PurchaseLine']
|
__all__ = ['Purchase', 'PurchaseLine']
|
||||||
|
|
||||||
|
@ -15,13 +14,14 @@ __all__ = ['Purchase', 'PurchaseLine']
|
||||||
class Purchase(metaclass=PoolMeta):
|
class Purchase(metaclass=PoolMeta):
|
||||||
__name__ = 'purchase.purchase'
|
__name__ = 'purchase.purchase'
|
||||||
shop = fields.Many2One('purchase.shop', 'Shop', required=True, domain=[
|
shop = fields.Many2One('purchase.shop', 'Shop', required=True, domain=[
|
||||||
('id', 'in', Eval('context', {}).get('shops', [])),
|
('id', 'in', Eval('context', {}).get('shops', [])),
|
||||||
],
|
],
|
||||||
states={
|
states={
|
||||||
'readonly': (Eval('state') != 'draft') | Bool(Eval('number')),
|
'readonly': (Eval('state') != 'draft') | Bool(Eval('number')),
|
||||||
}, depends=['number', 'state'])
|
}, depends=['number', 'state'])
|
||||||
shop_address = fields.Function(fields.Many2One('party.address',
|
shop_address = fields.Function(fields.Many2One('party.address',
|
||||||
'Shop Address'), 'on_change_with_shop_address')
|
'Shop Address'),
|
||||||
|
'on_change_with_shop_address')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
|
@ -77,7 +77,6 @@ class Purchase(metaclass=PoolMeta):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_price_list(cls):
|
def default_price_list(cls):
|
||||||
raise UserError(str(cls))
|
|
||||||
shop = cls.current_shop()
|
shop = cls.current_shop()
|
||||||
if not shop or not shop.price_list:
|
if not shop or not shop.price_list:
|
||||||
return
|
return
|
||||||
|
@ -89,7 +88,7 @@ class Purchase(metaclass=PoolMeta):
|
||||||
if not shop or not shop.address:
|
if not shop or not shop.address:
|
||||||
return
|
return
|
||||||
return shop.address.id
|
return shop.address.id
|
||||||
|
|
||||||
@fields.depends('shop', 'party')
|
@fields.depends('shop', 'party')
|
||||||
def on_change_shop(self):
|
def on_change_shop(self):
|
||||||
if not self.shop:
|
if not self.shop:
|
||||||
|
@ -105,7 +104,7 @@ class Purchase(metaclass=PoolMeta):
|
||||||
@fields.depends('shop')
|
@fields.depends('shop')
|
||||||
def on_change_with_shop_address(self, name=None):
|
def on_change_with_shop_address(self, name=None):
|
||||||
return (self.shop and self.shop.address and
|
return (self.shop and self.shop.address and
|
||||||
self.shop.address.id or None)
|
self.shop.address.id or None)
|
||||||
|
|
||||||
@fields.depends('shop')
|
@fields.depends('shop')
|
||||||
def on_change_party(self):
|
def on_change_party(self):
|
||||||
|
@ -117,7 +116,8 @@ class Purchase(metaclass=PoolMeta):
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_number(cls, purchases):
|
def set_number(cls, purchases):
|
||||||
'''
|
'''
|
||||||
Fill the reference field with the purchase shop or purchase config sequence
|
Fill the reference field with the purchase
|
||||||
|
shop or purchase config sequence
|
||||||
'''
|
'''
|
||||||
for purchase in purchases:
|
for purchase in purchases:
|
||||||
if purchase.number:
|
if purchase.number:
|
||||||
|
@ -128,15 +128,14 @@ class Purchase(metaclass=PoolMeta):
|
||||||
super().set_number(purchases)
|
super().set_number(purchases)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseLine(metaclass=PoolMeta):
|
class PurchaseLine(metaclass=PoolMeta):
|
||||||
__name__ = 'purchase.line'
|
__name__ = 'purchase.line'
|
||||||
|
|
||||||
|
|
||||||
@fields.depends('product', 'unit', 'quantity', 'purchase',
|
@fields.depends('product', 'unit', 'quantity', 'purchase',
|
||||||
'_parent_purchase.party', 'product_supplier',
|
'_parent_purchase.party', 'product_supplier',
|
||||||
'_parent_purchase.shop',
|
'_parent_purchase.shop',
|
||||||
methods=['_get_tax_rule_pattern', '_get_context_purchase_price'])
|
methods=['_get_tax_rule_pattern',
|
||||||
|
'_get_context_purchase_price'])
|
||||||
def on_change_product(self):
|
def on_change_product(self):
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
Product = pool.get('product.product')
|
Product = pool.get('product.product')
|
||||||
|
@ -172,16 +171,17 @@ class PurchaseLine(metaclass=PoolMeta):
|
||||||
|
|
||||||
if self.purchase and self.purchase.party:
|
if self.purchase and self.purchase.party:
|
||||||
product_suppliers = [ps for ps in self.product.product_suppliers
|
product_suppliers = [ps for ps in self.product.product_suppliers
|
||||||
if ps.party == self.purchase.party]
|
if ps.party == self.purchase.party]
|
||||||
if len(product_suppliers) == 1:
|
if len(product_suppliers) == 1:
|
||||||
self.product_supplier, = product_suppliers
|
self.product_supplier, = product_suppliers
|
||||||
if (self.product_supplier
|
if (self.product_supplier
|
||||||
and (self.product_supplier
|
and (self.product_supplier
|
||||||
not in self.product.product_suppliers)):
|
not in self.product.product_suppliers)):
|
||||||
self.product_supplier = None
|
self.product_supplier = None
|
||||||
|
|
||||||
with Transaction().set_context(self._get_context_purchase_price()):
|
with Transaction().set_context(self._get_context_purchase_price()):
|
||||||
self.unit_price = Product.get_purchase_price([self.product],
|
self.unit_price = Product.get_purchase_price(
|
||||||
|
[self.product],
|
||||||
abs(self.quantity or 0))[self.product.id]
|
abs(self.quantity or 0))[self.product.id]
|
||||||
if self.unit_price:
|
if self.unit_price:
|
||||||
self.unit_price = self.unit_price.quantize(
|
self.unit_price = self.unit_price.quantize(
|
||||||
|
|
51
setup.py
51
setup.py
|
@ -26,9 +26,10 @@ def get_require_version(name):
|
||||||
else:
|
else:
|
||||||
require = '%s >= %s.%s, < %s.%s'
|
require = '%s >= %s.%s, < %s.%s'
|
||||||
require %= (name, major_version, minor_version,
|
require %= (name, major_version, minor_version,
|
||||||
major_version, minor_version + 1)
|
major_version, minor_version + 1)
|
||||||
return require
|
return require
|
||||||
|
|
||||||
|
|
||||||
config = ConfigParser()
|
config = ConfigParser()
|
||||||
config.readfp(open('tryton.cfg'))
|
config.readfp(open('tryton.cfg'))
|
||||||
info = dict(config.items('tryton'))
|
info = dict(config.items('tryton'))
|
||||||
|
@ -54,26 +55,30 @@ if minor_version % 2:
|
||||||
dependency_links.append('https://trydevpi.tryton.org/')
|
dependency_links.append('https://trydevpi.tryton.org/')
|
||||||
|
|
||||||
setup(name='%s_%s' % (PREFIX, MODULE),
|
setup(name='%s_%s' % (PREFIX, MODULE),
|
||||||
version=version,
|
version=version,
|
||||||
description='Tryton Purchase Shop Module',
|
description='Tryton Purchase Shop Module',
|
||||||
long_description=read('README'),
|
long_description=read('README'),
|
||||||
author='Alnus Tmp',
|
author='Alnus Tmp',
|
||||||
author_email='alnus@disroot.org',
|
author_email='alnus@disroot.org',
|
||||||
url='https://git.disroot.org/Etrivial/',
|
url='https://git.disroot.org/Etrivial/',
|
||||||
download_url='https://git.disroot.org/Etrivial/trytond-%s' % MODULE,
|
download_url='https://git.disroot.org/Etrivial/trytond-%s' % MODULE,
|
||||||
keywords='',
|
keywords='',
|
||||||
package_dir={'trytond.modules.%s' % MODULE: '.'},
|
package_dir={'trytond.modules.%s' % MODULE: '.'},
|
||||||
packages=[
|
packages=[
|
||||||
'trytond.modules.%s' % MODULE,
|
'trytond.modules.%s' % MODULE,
|
||||||
'trytond.modules.%s.tests' % MODULE,
|
'trytond.modules.%s.tests' % MODULE,
|
||||||
],
|
],
|
||||||
package_data={
|
package_data={
|
||||||
'trytond.modules.%s' % MODULE: (info.get('xml', [])
|
'trytond.modules.%s' % MODULE: (info.get('xml', [])
|
||||||
+ ['tryton.cfg', 'view/*.xml', 'locale/*.po', '*.odt',
|
+ ['tryton.cfg',
|
||||||
'icons/*.svg', 'tests/*.rst']),
|
'view/*.xml',
|
||||||
},
|
'locale/*.po',
|
||||||
|
'*.odt',
|
||||||
|
'icons/*.svg',
|
||||||
|
'tests/*.rst']),
|
||||||
|
},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
'Development Status :: 5 - Production/Stable',
|
'Development Status :: 5 - Production/Stable',
|
||||||
'Environment :: Plugins',
|
'Environment :: Plugins',
|
||||||
'Framework :: Tryton',
|
'Framework :: Tryton',
|
||||||
'Intended Audience :: Developers',
|
'Intended Audience :: Developers',
|
||||||
|
@ -101,7 +106,7 @@ setup(name='%s_%s' % (PREFIX, MODULE),
|
||||||
'Programming Language :: Python :: Implementation :: CPython',
|
'Programming Language :: Python :: Implementation :: CPython',
|
||||||
'Programming Language :: Python :: Implementation :: PyPy',
|
'Programming Language :: Python :: Implementation :: PyPy',
|
||||||
'Topic :: Office/Business',
|
'Topic :: Office/Business',
|
||||||
],
|
],
|
||||||
license='GPL-3',
|
license='GPL-3',
|
||||||
install_requires=requires,
|
install_requires=requires,
|
||||||
dependency_links=dependency_links,
|
dependency_links=dependency_links,
|
||||||
|
@ -115,6 +120,6 @@ setup(name='%s_%s' % (PREFIX, MODULE),
|
||||||
tests_require=tests_require,
|
tests_require=tests_require,
|
||||||
use_2to3=True,
|
use_2to3=True,
|
||||||
convert_2to3_doctests=[
|
convert_2to3_doctests=[
|
||||||
'tests/scenario_purchase_shop.rst',
|
'tests/scenario_purchase_shop.rst',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
175
shop.py
175
shop.py
|
@ -2,84 +2,81 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains
|
# The COPYRIGHT file at the top level of this repository contains
|
||||||
# the full copyright notices and license terms.
|
# the full copyright notices and license terms.
|
||||||
from sql import Null, Table
|
from sql import Null, Table
|
||||||
|
|
||||||
from trytond.model import ModelView, ModelSQL, fields
|
from trytond.model import ModelView, ModelSQL, fields
|
||||||
from trytond.pyson import If, Eval, Id
|
from trytond.pyson import If, Eval, Id
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.pool import Pool, PoolMeta
|
from trytond.pool import Pool
|
||||||
from trytond import backend
|
from trytond import backend
|
||||||
|
|
||||||
__all__ = ['PurchaseShop', 'PurchaseShopResUser', 'PurchaseShopParty']
|
__all__ = ['PurchaseShop', 'PurchaseShopResUser', 'PurchaseShopParty']
|
||||||
|
|
||||||
_digits = (16, 2)
|
_digits = (16, 2)
|
||||||
|
|
||||||
|
|
||||||
class PurchaseShop(ModelSQL, ModelView):
|
class PurchaseShop(ModelSQL, ModelView):
|
||||||
'Purchase Shop'
|
'Purchase Shop'
|
||||||
__name__ = 'purchase.shop'
|
__name__ = 'purchase.shop'
|
||||||
|
|
||||||
name = fields.Char('Shop Name', required=True, select=True)
|
name = fields.Char('Shop Name', required=True, )
|
||||||
users = fields.Many2Many('purchase.shop-res.user', 'shop', 'user', 'Users')
|
users = fields.Many2Many('purchase.shop-res.user', 'shop', 'user', 'Users')
|
||||||
address = fields.Many2One('party.address', 'Address', domain=[
|
address = fields.Many2One('party.address', 'Address', domain=[
|
||||||
('party', '=', Eval('company_party')),
|
('party', '=', Eval('company_party')),
|
||||||
], depends=['company_party'])
|
], depends=['company_party'])
|
||||||
warehouse = fields.Many2One('stock.location', "Warehouse", required=True,
|
warehouse = fields.Many2One('stock.location', "Warehouse", required=True,
|
||||||
domain=[('type', '=', 'warehouse')])
|
domain=[('type', '=', 'warehouse')])
|
||||||
currency = fields.Many2One('currency.currency', 'Currency',)
|
currency = fields.Many2One('currency.currency', 'Currency',)
|
||||||
price_list = fields.Many2One('product.price_list', 'Price List')
|
price_list = fields.Many2One('product.price_list', 'Price List')
|
||||||
payment_term = fields.Many2One('account.invoice.payment_term',
|
payment_term = fields.Many2One('account.invoice.payment_term',
|
||||||
'Payment Term')
|
'Payment Term')
|
||||||
purchase_sequence = fields.Many2One(
|
purchase_sequence = fields.Many2One(
|
||||||
'ir.sequence', 'Purchase Sequence', domain=[
|
'ir.sequence', 'Purchase Sequence', domain=[
|
||||||
('company', 'in', [Eval('company', -1), None]),
|
('company', 'in', [Eval('company', -1), None]),
|
||||||
('sequence_type', '=', Id('purchase', 'sequence_type_purchase')),
|
('sequence_type', '=', Id('purchase', 'sequence_type_purchase')),
|
||||||
],
|
],
|
||||||
depends=['company'])
|
depends=['company'])
|
||||||
purchase_invoice_method = fields.Selection([
|
purchase_invoice_method = fields.Selection([
|
||||||
(None, ''),
|
(None, ''),
|
||||||
('manual', 'Manual'),
|
('manual', 'Manual'),
|
||||||
('order', 'On Order Processed'),
|
('order', 'On Order Processed'),
|
||||||
('shipment', 'On Shipment Sent')
|
('shipment', 'On Shipment Sent')
|
||||||
], 'Purchase Invoice Method')
|
], 'Purchase Invoice Method')
|
||||||
purchase_shipment_method = fields.Selection([
|
purchase_shipment_method = fields.Selection([
|
||||||
(None, ''),
|
(None, ''),
|
||||||
('manual', 'Manual'),
|
('manual', 'Manual'),
|
||||||
('order', 'On Order Processed'),
|
('order', 'On Order Processed'),
|
||||||
('invoice', 'On Invoice Paid'),
|
('invoice', 'On Invoice Paid'),
|
||||||
], 'Purchase Shipment Method')
|
], 'Purchase Shipment Method')
|
||||||
company = fields.Many2One('company.company', 'Company', required=True,
|
company = fields.Many2One('company.company', 'Company', required=True,
|
||||||
domain=[
|
domain=[
|
||||||
('id', If(Eval('context', {}).contains('company'), '=', '!='),
|
('id',
|
||||||
Eval('context', {}).get('company', 0)),
|
If(Eval('context', {}).contains('company'),
|
||||||
], select=True)
|
'=', '!='),
|
||||||
|
Eval('context', {}).get('company', 0)),
|
||||||
|
], )
|
||||||
company_party = fields.Function(fields.Many2One('party.party',
|
company_party = fields.Function(fields.Many2One('party.party',
|
||||||
'Company Party'),
|
'Company Party'),
|
||||||
'on_change_with_company_party')
|
'on_change_with_company_party')
|
||||||
active = fields.Boolean('Active', select=True)
|
active = fields.Boolean('Active', )
|
||||||
analytic_root = fields.Many2One('analytic_account.account','Analytic Root', required=True,
|
analytic_root = fields.Many2One('analytic_account.account',
|
||||||
domain=[
|
'Analytic Root', required=True,
|
||||||
('type', '=', 'root'),
|
domain=[
|
||||||
],
|
('type', '=', 'root'),
|
||||||
depends=['type']
|
]
|
||||||
)
|
)
|
||||||
analytic_account = fields.Many2One('analytic_account.account',
|
analytic_account = fields.Many2One('analytic_account.account',
|
||||||
'Analytic Account', required=True,
|
'Analytic Account', required=True,
|
||||||
domain=[
|
domain=[
|
||||||
('type', '=', 'normal')
|
('type', '=', 'normal')
|
||||||
],
|
]
|
||||||
depends=['analytic_root']
|
)
|
||||||
)
|
|
||||||
partys = fields.Many2Many('purchase.shop_party', 'shop', 'party',
|
partys = fields.Many2Many('purchase.shop_party', 'shop', 'party',
|
||||||
'Partys')
|
'Partys')
|
||||||
withholding_tax = fields.Many2One('account.tax', 'WithholdingTax',
|
withholding_tax = fields.Many2One('account.tax', 'WithholdingTax',
|
||||||
domain=[
|
domain=[
|
||||||
('rate', '<', 0),
|
('rate', '<', 0),
|
||||||
('group.kind', '=', 'purchase'),
|
('group.kind', '=', 'purchase'),
|
||||||
],
|
])
|
||||||
depends=['rate', 'group'])
|
invoice_subtype = fields.Many2One('account.invoice.subtype', "Subtype")
|
||||||
|
|
||||||
default_performance_rate = fields.Numeric('Default Performance Rate', _digits)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __register__(cls, module_name):
|
def __register__(cls, module_name):
|
||||||
|
@ -101,7 +98,8 @@ class PurchaseShop(ModelSQL, ModelView):
|
||||||
if property_exist:
|
if property_exist:
|
||||||
property_ = Table('ir_property')
|
property_ = Table('ir_property')
|
||||||
purchase_sequence_exist = table_h.column_exist('purchase_sequence')
|
purchase_sequence_exist = table_h.column_exist('purchase_sequence')
|
||||||
purchase_invoice_method_exist = table_h.column_exist('purchase_invoice_method')
|
purchase_invoice_method_exist = table_h.column_exist(
|
||||||
|
'purchase_invoice_method')
|
||||||
purchase_shipment_method_exist = table_h.column_exist(
|
purchase_shipment_method_exist = table_h.column_exist(
|
||||||
'purchase_shipment_method')
|
'purchase_shipment_method')
|
||||||
|
|
||||||
|
@ -109,65 +107,66 @@ class PurchaseShop(ModelSQL, ModelView):
|
||||||
if backend.name != 'sqlite':
|
if backend.name != 'sqlite':
|
||||||
# SQLite doesn't support this query as it generates and update
|
# SQLite doesn't support this query as it generates and update
|
||||||
# with an alias (AS) which is not valid on SQLite
|
# with an alias (AS) which is not valid on SQLite
|
||||||
query = shop_table.update(columns=[shop_table.currency],
|
query = shop_table.update(
|
||||||
|
columns=[shop_table.currency],
|
||||||
values=[company_table.currency],
|
values=[company_table.currency],
|
||||||
from_=[company_table],
|
from_=[company_table],
|
||||||
where=((shop_table.company == company_table.id)
|
where=((shop_table.company == company_table.id)
|
||||||
& (shop_table.currency == Null)))
|
& (shop_table.currency == Null)))
|
||||||
cursor.execute(*query)
|
cursor.execute(*query)
|
||||||
|
|
||||||
# Migration to remove Property
|
# Migration to remove Property
|
||||||
if not purchase_sequence_exist and property_exist:
|
if not purchase_sequence_exist and property_exist:
|
||||||
cursor.execute(*property_
|
cursor.execute(*property_
|
||||||
.join(field, condition=property_.field == field.id)
|
.join(field, condition=property_.field == field.id)
|
||||||
.join(model, condition=field.model == model.id)
|
.join(model, condition=field.model == model.id)
|
||||||
.select(
|
.select(
|
||||||
property_.res,
|
property_.res,
|
||||||
property_.value,
|
property_.value,
|
||||||
where=property_.res.like(cls.__name__ + ',%')
|
where=property_.res.like(cls.__name__ + ',%')
|
||||||
& (field.name == 'purchase_sequence')
|
& (field.name == 'purchase_sequence')
|
||||||
& (model.model == cls.__name__)))
|
& (model.model == cls.__name__)))
|
||||||
for res, value in cursor:
|
for res, value in cursor:
|
||||||
id_ = int(res.split(',')[1])
|
id_ = int(res.split(',')[1])
|
||||||
value = int(value.split(',')[1]) if value else None
|
value = int(value.split(',')[1]) if value else None
|
||||||
update.execute(*table.update(
|
update.execute(*table.update(
|
||||||
[table.purchase_sequence],
|
[table.purchase_sequence],
|
||||||
[value],
|
[value],
|
||||||
where=table.id == id_))
|
where=table.id == id_))
|
||||||
if not purchase_invoice_method_exist and property_exist:
|
if not purchase_invoice_method_exist and property_exist:
|
||||||
cursor.execute(*property_
|
cursor.execute(*property_
|
||||||
.join(field, condition=property_.field == field.id)
|
.join(field, condition=property_.field == field.id)
|
||||||
.join(model, condition=field.model == model.id)
|
.join(model, condition=field.model == model.id)
|
||||||
.select(
|
.select(
|
||||||
property_.res,
|
property_.res,
|
||||||
property_.value,
|
property_.value,
|
||||||
where=property_.res.like(cls.__name__ + ',%')
|
where=property_.res.like(cls.__name__ + ',%')
|
||||||
& (field.name == 'purchase_invoice_method')
|
& (field.name == 'purchase_invoice_method')
|
||||||
& (model.model == cls.__name__)))
|
& (model.model == cls.__name__)))
|
||||||
for res, value in cursor:
|
for res, value in cursor:
|
||||||
id_ = int(res.split(',')[1])
|
id_ = int(res.split(',')[1])
|
||||||
value = value.split(',')[1] if value else None
|
value = value.split(',')[1] if value else None
|
||||||
update.execute(*table.update(
|
update.execute(*table.update(
|
||||||
[table.purchase_invoice_method],
|
[table.purchase_invoice_method],
|
||||||
[value],
|
[value],
|
||||||
where=table.id == id_))
|
where=table.id == id_))
|
||||||
if not purchase_shipment_method_exist and property_exist:
|
if not purchase_shipment_method_exist and property_exist:
|
||||||
cursor.execute(*property_
|
cursor.execute(*property_
|
||||||
.join(field, condition=property_.field == field.id)
|
.join(field, condition=property_.field == field.id)
|
||||||
.join(model, condition=field.model == model.id)
|
.join(model, condition=field.model == model.id)
|
||||||
.select(
|
.select(
|
||||||
property_.res,
|
property_.res,
|
||||||
property_.value,
|
property_.value,
|
||||||
where=property_.res.like(cls.__name__ + ',%')
|
where=property_.res.like(cls.__name__ + ',%')
|
||||||
& (field.name == 'purchase_shipment_method')
|
& (field.name == 'purchase_shipment_method')
|
||||||
& (model.model == cls.__name__)))
|
& (model.model == cls.__name__)))
|
||||||
for res, value in cursor:
|
for res, value in cursor:
|
||||||
id_ = int(res.split(',')[1])
|
id_ = int(res.split(',')[1])
|
||||||
value = value.split(',')[1] if value else None
|
value = value.split(',')[1] if value else None
|
||||||
update.execute(*table.update(
|
update.execute(*table.update(
|
||||||
[table.purchase_shipment_method],
|
[table.purchase_shipment_method],
|
||||||
[value],
|
[value],
|
||||||
where=table.id == id_))
|
where=table.id == id_))
|
||||||
|
|
||||||
# Migration from 5.2: do not require price_list
|
# Migration from 5.2: do not require price_list
|
||||||
table_h.not_null_action('price_list', action='remove')
|
table_h.not_null_action('price_list', action='remove')
|
||||||
|
@ -203,15 +202,6 @@ class PurchaseShop(ModelSQL, ModelView):
|
||||||
config = Config(1)
|
config = Config(1)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def default_performance_rate():
|
|
||||||
Config = Pool().get('purchase.configuration')
|
|
||||||
config = Config(1)
|
|
||||||
|
|
||||||
if config.default_performance_rate:
|
|
||||||
return config.default_performance_rate
|
|
||||||
|
|
||||||
|
|
||||||
@fields.depends('company')
|
@fields.depends('company')
|
||||||
def on_change_with_company_party(self, name=None):
|
def on_change_with_company_party(self, name=None):
|
||||||
if self.company and self.company.party:
|
if self.company and self.company.party:
|
||||||
|
@ -225,16 +215,15 @@ class PurchaseShopResUser(ModelSQL):
|
||||||
_table = 'purchase_shop_res_user'
|
_table = 'purchase_shop_res_user'
|
||||||
|
|
||||||
shop = fields.Many2One('purchase.shop', 'Shop', ondelete='CASCADE',
|
shop = fields.Many2One('purchase.shop', 'Shop', ondelete='CASCADE',
|
||||||
select=True, required=True)
|
required=True)
|
||||||
user = fields.Many2One('res.user', 'User', ondelete='RESTRICT',
|
user = fields.Many2One('res.user', 'User', ondelete='RESTRICT',
|
||||||
required=True)
|
required=True)
|
||||||
|
|
||||||
|
|
||||||
class PurchaseShopParty(ModelSQL):
|
class PurchaseShopParty(ModelSQL):
|
||||||
'Purchase Schop Party'
|
'Purchase Schop Party'
|
||||||
__name__ = 'purchase.shop_party'
|
__name__ = 'purchase.shop_party'
|
||||||
shop = fields.Many2One('purchase.shop', 'Shop', ondelete='CASCADE',
|
shop = fields.Many2One('purchase.shop', 'Shop', ondelete='CASCADE',
|
||||||
select=True, required=True)
|
required=True)
|
||||||
party = fields.Many2One('party.party', 'Party', ondelete='CASCADE',
|
party = fields.Many2One('party.party', 'Party', ondelete='CASCADE',
|
||||||
required=True)
|
required=True)
|
||||||
|
|
||||||
|
|
38
stock.py
38
stock.py
|
@ -12,8 +12,8 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||||
__name__ = 'stock.shipment.out'
|
__name__ = 'stock.shipment.out'
|
||||||
|
|
||||||
shop_addresses = fields.Function(fields.Many2Many('party.address', None,
|
shop_addresses = fields.Function(fields.Many2Many('party.address', None,
|
||||||
None, 'Shop Addresses'),
|
None, 'Shop Addresses'),
|
||||||
'on_change_with_shop_addresses')
|
'on_change_with_shop_addresses')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
|
@ -24,13 +24,13 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||||
'OR',
|
'OR',
|
||||||
delivery_addr_domain,
|
delivery_addr_domain,
|
||||||
[('id', 'in', Eval('shop_addresses'))],
|
[('id', 'in', Eval('shop_addresses'))],
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
cls.delivery_address.domain = [
|
cls.delivery_address.domain = [
|
||||||
('id', 'in', Eval('shop_addresses')),
|
('id', 'in', Eval('shop_addresses')),
|
||||||
]
|
]
|
||||||
if 'shop_addresses' not in cls.delivery_address.depends:
|
if 'shop_addresses' not in cls.delivery_address.depends:
|
||||||
cls.delivery_address.depends.append('shop_addresses')
|
cls.delivery_address.depends.add('shop_addresses')
|
||||||
|
|
||||||
@fields.depends('warehouse')
|
@fields.depends('warehouse')
|
||||||
def on_change_with_shop_addresses(self, name=None):
|
def on_change_with_shop_addresses(self, name=None):
|
||||||
|
@ -38,8 +38,8 @@ class ShipmentOut(metaclass=PoolMeta):
|
||||||
if not self.warehouse:
|
if not self.warehouse:
|
||||||
return []
|
return []
|
||||||
warehouse_shops = Shop.search([
|
warehouse_shops = Shop.search([
|
||||||
('warehouse', '=', self.warehouse.id),
|
('warehouse', '=', self.warehouse.id),
|
||||||
])
|
])
|
||||||
return [s.address.id for s in warehouse_shops if s.address]
|
return [s.address.id for s in warehouse_shops if s.address]
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,25 +47,25 @@ class ShipmentOutReturn(metaclass=PoolMeta):
|
||||||
__name__ = 'stock.shipment.out.return'
|
__name__ = 'stock.shipment.out.return'
|
||||||
|
|
||||||
shop_addresses = fields.Function(fields.Many2Many('party.address', None,
|
shop_addresses = fields.Function(fields.Many2Many('party.address', None,
|
||||||
None, 'Shop Addresses'),
|
None, 'Shop Addresses'),
|
||||||
'on_change_with_shop_addresses')
|
'on_change_with_shop_addresses')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(ShipmentOutReturn, cls).__setup__()
|
super(ShipmentOutReturn, cls).__setup__()
|
||||||
delivery_addr_domain = cls.delivery_address.domain[:]
|
contact_addr_domain = cls.contact_address.domain[:]
|
||||||
if delivery_addr_domain:
|
if contact_addr_domain:
|
||||||
cls.delivery_address.domain = [
|
cls.contact_address.domain = [
|
||||||
'OR',
|
'OR',
|
||||||
delivery_addr_domain,
|
contact_addr_domain,
|
||||||
[('id', 'in', Eval('shop_addresses'))],
|
[('id', 'in', Eval('shop_addresses'))],
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
cls.delivery_address.domain = [
|
cls.delivery_address.domain = [
|
||||||
('id', 'in', Eval('shop_addresses')),
|
('id', 'in', Eval('shop_addresses')),
|
||||||
]
|
]
|
||||||
if 'shop_addresses' not in cls.delivery_address.depends:
|
if 'shop_addresses' not in cls.contact_address.depends:
|
||||||
cls.delivery_address.depends.append('shop_addresses')
|
cls.contact_address.depends.add('shop_addresses')
|
||||||
|
|
||||||
@fields.depends('warehouse')
|
@fields.depends('warehouse')
|
||||||
def on_change_with_shop_addresses(self, name=None):
|
def on_change_with_shop_addresses(self, name=None):
|
||||||
|
@ -73,6 +73,6 @@ class ShipmentOutReturn(metaclass=PoolMeta):
|
||||||
if not self.warehouse:
|
if not self.warehouse:
|
||||||
return []
|
return []
|
||||||
warehouse_shops = Shop.search([
|
warehouse_shops = Shop.search([
|
||||||
('warehouse', '=', self.warehouse.id),
|
('warehouse', '=', self.warehouse.id),
|
||||||
])
|
])
|
||||||
return [s.address.id for s in warehouse_shops if s.address]
|
return [s.address.id for s in warehouse_shops if s.address]
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
# This file is part sale_shop module for Tryton.
|
# This file is part sale_shop module for Tryton.
|
||||||
# The COPYRIGHT file at the top level of this repository contains the full
|
# The COPYRIGHT file at the top level of this repository contains the full
|
||||||
# copyright notices and license terms.
|
# copyright notices and license terms.
|
||||||
try:
|
|
||||||
from trytond.modules.sale_shop.tests.test_sale_shop import suite
|
|
||||||
except ImportError:
|
|
||||||
from .test_sale_shop import suite
|
|
||||||
|
|
||||||
__all__ = ['suite']
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
==================
|
==================
|
||||||
Sale Shop Scenario
|
Purchase Shop Scenario
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Imports::
|
Imports::
|
||||||
|
@ -14,12 +14,12 @@ Imports::
|
||||||
... create_chart, get_accounts, create_tax
|
... create_chart, get_accounts, create_tax
|
||||||
>>> from trytond.modules.account_invoice.tests.tools import \
|
>>> from trytond.modules.account_invoice.tests.tools import \
|
||||||
... set_fiscalyear_invoice_sequences, create_payment_term
|
... set_fiscalyear_invoice_sequences, create_payment_term
|
||||||
>>> from trytond.modules.sale_shop.tests.tools import create_shop
|
>>> from trytond.modules.purchase_shop.tests.tools import create_shop
|
||||||
>>> today = datetime.date.today()
|
>>> today = datetime.date.today()
|
||||||
|
|
||||||
Install sale::
|
Install purchase::
|
||||||
|
|
||||||
>>> config = activate_modules('sale_shop')
|
>>> config = activate_modules('purchase_shop')
|
||||||
|
|
||||||
Create company::
|
Create company::
|
||||||
|
|
||||||
|
@ -114,12 +114,12 @@ Create an Inventory::
|
||||||
>>> inventory.state == 'done'
|
>>> inventory.state == 'done'
|
||||||
True
|
True
|
||||||
|
|
||||||
Create Sale Shop::
|
Create Purchase Shop::
|
||||||
|
|
||||||
>>> shop = create_shop(payment_term, product_price_list)
|
>>> shop = create_shop(payment_term, product_price_list)
|
||||||
>>> shop.save()
|
>>> shop.save()
|
||||||
|
|
||||||
Save Sale Shop User::
|
Save Purchase Shop User::
|
||||||
|
|
||||||
>>> User = Model.get('res.user')
|
>>> User = Model.get('res.user')
|
||||||
>>> user, = User.find([])
|
>>> user, = User.find([])
|
||||||
|
@ -128,22 +128,22 @@ Save Sale Shop User::
|
||||||
>>> user.save()
|
>>> user.save()
|
||||||
>>> set_user(user)
|
>>> set_user(user)
|
||||||
|
|
||||||
Sale 5 products::
|
Purchase 5 products::
|
||||||
|
|
||||||
>>> Sale = Model.get('sale.sale')
|
>>> Purchase = Model.get('purchase.purchase')
|
||||||
>>> SaleLine = Model.get('sale.line')
|
>>> PurchaseLine = Model.get('purchase.line')
|
||||||
>>> sale = Sale()
|
>>> purchase = Purchase()
|
||||||
>>> sale.party = customer
|
>>> purchase.party = customer
|
||||||
>>> sale.payment_term = payment_term
|
>>> purchase.payment_term = payment_term
|
||||||
>>> sale.invoice_method = 'shipment'
|
>>> purchase.invoice_method = 'shipment'
|
||||||
>>> sale_line = SaleLine()
|
>>> purchase_line = PurchaseLine()
|
||||||
>>> sale.lines.append(sale_line)
|
>>> purchase.lines.append(purchase_line)
|
||||||
>>> sale_line.product = product
|
>>> purchase_line.product = product
|
||||||
>>> sale_line.quantity = 2.0
|
>>> purchase_line.quantity = 2.0
|
||||||
>>> sale_line = SaleLine()
|
>>> purchase_line = PurchaseLine()
|
||||||
>>> sale.lines.append(sale_line)
|
>>> purchase.lines.append(purchase_line)
|
||||||
>>> sale_line.product = product
|
>>> purchase_line.product = product
|
||||||
>>> sale_line.quantity = 3.0
|
>>> purchase_line.quantity = 3.0
|
||||||
>>> sale.save()
|
>>> purchase.save()
|
||||||
>>> sale.state == 'draft'
|
>>> purchase.state == 'draft'
|
||||||
True
|
True
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# This file is part of the sale_shop module for Tryton.
|
||||||
|
# The COPYRIGHT file at the top level of this repository contains the full
|
||||||
|
# copyright notices and license terms.
|
||||||
|
from trytond.tests.test_tryton import ModuleTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class PurchaseShopTestCase(ModuleTestCase):
|
||||||
|
'Test Sale Shop module'
|
||||||
|
module = 'purchase_shop'
|
||||||
|
|
||||||
|
|
||||||
|
del ModuleTestCase
|
|
@ -1,26 +0,0 @@
|
||||||
# This file is part of the sale_shop module for Tryton.
|
|
||||||
# The COPYRIGHT file at the top level of this repository contains the full
|
|
||||||
# copyright notices and license terms.
|
|
||||||
import unittest
|
|
||||||
import doctest
|
|
||||||
import trytond.tests.test_tryton
|
|
||||||
from trytond.tests.test_tryton import ModuleTestCase
|
|
||||||
from trytond.tests.test_tryton import doctest_teardown
|
|
||||||
from trytond.tests.test_tryton import doctest_checker
|
|
||||||
|
|
||||||
|
|
||||||
class SaleShopTestCase(ModuleTestCase):
|
|
||||||
'Test Sale Shop module'
|
|
||||||
module = 'sale_shop'
|
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
|
||||||
suite = trytond.tests.test_tryton.suite()
|
|
||||||
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
|
|
||||||
SaleShopTestCase))
|
|
||||||
suite.addTests(doctest.DocFileSuite(
|
|
||||||
'scenario_sale_shop.rst',
|
|
||||||
tearDown=doctest_teardown, encoding='utf-8',
|
|
||||||
checker=doctest_checker,
|
|
||||||
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
|
|
||||||
return suite
|
|
|
@ -7,7 +7,7 @@ __all__ = ['create_shop']
|
||||||
|
|
||||||
|
|
||||||
def create_shop(payment_term, product_price_list, name=None, warehouse=None,
|
def create_shop(payment_term, product_price_list, name=None, warehouse=None,
|
||||||
sequence=None, config=None):
|
sequence=None, config=None):
|
||||||
"Create a sale shop"
|
"Create a sale shop"
|
||||||
Shop = Model.get('sale.shop', config=config)
|
Shop = Model.get('sale.shop', config=config)
|
||||||
Sequence = Model.get('ir.sequence', config=config)
|
Sequence = Model.get('ir.sequence', config=config)
|
||||||
|
@ -20,14 +20,14 @@ def create_shop(payment_term, product_price_list, name=None, warehouse=None,
|
||||||
if not warehouse:
|
if not warehouse:
|
||||||
warehouse, = Location.find([
|
warehouse, = Location.find([
|
||||||
('type', '=', 'warehouse'),
|
('type', '=', 'warehouse'),
|
||||||
])
|
])
|
||||||
shop.warehouse = warehouse
|
shop.warehouse = warehouse
|
||||||
shop.price_list = product_price_list
|
shop.price_list = product_price_list
|
||||||
shop.payment_term = payment_term
|
shop.payment_term = payment_term
|
||||||
if not sequence:
|
if not sequence:
|
||||||
sequence, = Sequence.find([
|
sequence, = Sequence.find([
|
||||||
('name', '=', 'Sale'),
|
('name', '=', 'Sale'),
|
||||||
])
|
])
|
||||||
shop.sale_sequence = sequence
|
shop.sale_sequence = sequence
|
||||||
shop.sale_invoice_method = 'shipment'
|
shop.sale_invoice_method = 'shipment'
|
||||||
shop.sale_shipment_method = 'order'
|
shop.sale_shipment_method = 'order'
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
[tryton]
|
[tryton]
|
||||||
version=6.0.0
|
version=6.8.0
|
||||||
depends:
|
depends:
|
||||||
ir
|
ir
|
||||||
res
|
res
|
||||||
purchase_price_list
|
purchase_price_list
|
||||||
analytic_purchase
|
analytic_purchase
|
||||||
account
|
account
|
||||||
|
account_invoice_subtype
|
||||||
|
party
|
||||||
xml:
|
xml:
|
||||||
shop.xml
|
shop.xml
|
||||||
purchase.xml
|
purchase.xml
|
||||||
|
|
|
@ -18,8 +18,6 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
|
||||||
<field name="analytic_account"/>
|
<field name="analytic_account"/>
|
||||||
<label name="withholding_tax"/>
|
<label name="withholding_tax"/>
|
||||||
<field name="withholding_tax"/>
|
<field name="withholding_tax"/>
|
||||||
<label name="default_performance_rate"/>
|
|
||||||
<field name="default_performance_rate"/>
|
|
||||||
<notebook colspan="4">
|
<notebook colspan="4">
|
||||||
<page string="General" id="general">
|
<page string="General" id="general">
|
||||||
<label name="purchase_sequence"/>
|
<label name="purchase_sequence"/>
|
||||||
|
@ -35,6 +33,8 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
|
||||||
<field name="price_list"/>
|
<field name="price_list"/>
|
||||||
<label name="payment_term"/>
|
<label name="payment_term"/>
|
||||||
<field name="payment_term"/>
|
<field name="payment_term"/>
|
||||||
|
<label name="invoice_subtype"/>
|
||||||
|
<field name="invoice_subtype"/>
|
||||||
</page>
|
</page>
|
||||||
<page string="Users" id="users">
|
<page string="Users" id="users">
|
||||||
<field name="users"/>
|
<field name="users"/>
|
||||||
|
|
Loading…
Reference in New Issue