diff --git a/__init__.py b/__init__.py index 4e351ec..55d77fd 100644 --- a/__init__.py +++ b/__init__.py @@ -4,11 +4,16 @@ from trytond.pool import Pool from . import account from . import sale from . import purchase +from . import office +from . import party def register(): Pool.register( account.Rule, + account.AnalyticAccount, + office.Office, + office.OfficeAnalytic, module='analytic_office', type_='model') Pool.register( sale.Sale, @@ -21,3 +26,16 @@ def register(): module='analytic_office', type_='model', depends=['purchase_office', 'analytic_purchase', 'analytic_apply_rule'] ) + Pool.register( + party.Party, + module='analytic_office', type_='model', + depends=['analytic_party']) + Pool.register( + office.SaleLine, + module='analytic_office', type_='model', + depends=['sale_office', 'analytic_sale', 'analytic_party']) + Pool.register( + office.PurchaseLine, + module='analytic_office', type_='model', + depends=['purchase_office', 'analytic_purchase', 'analytic_party'] + ) diff --git a/account.py b/account.py index c486bc5..d8d6534 100644 --- a/account.py +++ b/account.py @@ -16,3 +16,14 @@ class Rule(metaclass=PoolMeta): ('company', '=', Eval('company')) ], depends=['company']) + + +class AnalyticAccount(metaclass=PoolMeta): + + __name__ = 'analytic_account.account' + + offices = fields.Many2Many( + 'company.office-analytic_account.account', 'account', 'office', + 'Offices', + domain=[ + ('company', '=', Eval('context', {}).get('company', -1))]) diff --git a/office.py b/office.py new file mode 100644 index 0000000..2ba8618 --- /dev/null +++ b/office.py @@ -0,0 +1,59 @@ +# The COPYRIGHT file at the top level of this repository contains the full +# copyright notices and license terms. +from trytond.pool import PoolMeta +from trytond.model import fields, ModelSQL +from trytond.pyson import If, Eval +from trytond.transaction import Transaction + + +class Office(metaclass=PoolMeta): + __name__ = 'company.office' + + analytic_accounts = fields.Many2Many( + 'company.office-analytic_account.account', 'office', 'account', + 'Analytic Accounts', + domain=[ + ('type', '=', 'view'), + If(Eval('company', None), + ('company', '=', Eval('company')), + ('company', '=', Eval('context', {}).get('company', -1))), + ], + depends=['company']) + + +class OfficeAnalytic(ModelSQL): + """Office - Analytic Account""" + __name__ = 'company.office-analytic_account.account' + + office = fields.Many2One('company.office', 'Office', select=True, + ondelete='CASCADE') + account = fields.Many2One('analytic_account.account', 'Account', + select=True, ondelete='CASCADE') + + +class SaleLine(metaclass=PoolMeta): + __name__ = 'sale.line' + + @fields.depends('sale', '_parent_sale.office') + def get_party_analytic_account_domain(self, root): + domain = super().get_party_analytic_account_domain(root) + if self.sale and self.sale.office: + domain.append(('parent.offices', '=', self.sale.office.id)) + else: + domain.append(('parent.offices', '=', + Transaction().context.get('office', -1))) + return domain + + +class PurchaseLine(metaclass=PoolMeta): + __name__ = 'purchase.line' + + @fields.depends('purchase', '_parent_purchase.office') + def get_party_analytic_account_domain(self, root): + domain = super().get_party_analytic_account_domain(root) + if self.purchase and self.purchase.office: + domain.append(('parent.offices', '=', self.purchase.office.id)) + else: + domain.append(('parent.offices', '=', + Transaction().context.get('office', -1))) + return domain diff --git a/office.xml b/office.xml new file mode 100644 index 0000000..07538e6 --- /dev/null +++ b/office.xml @@ -0,0 +1,10 @@ + + + + + company.office + + office_form + + \ No newline at end of file diff --git a/party.py b/party.py new file mode 100644 index 0000000..0372650 --- /dev/null +++ b/party.py @@ -0,0 +1,19 @@ +# The COPYRIGHT file at the top level of this repository contains the full +# copyright notices and license terms. +from trytond.pool import PoolMeta +from trytond.pyson import If, Eval + + +class Party(metaclass=PoolMeta): + __name__ = 'party.party' + + @classmethod + def __setup__(cls): + super().__setup__() + cls.analytic_accounts.domain.extend([ + If(Eval('offices'), + ('parent.offices', 'in', Eval('offices')), ()), + (('parent.offices', 'in', + Eval('context', {}).get('offices', [])))]) + if 'offices' not in cls.analytic_accounts.depends: + cls.analytic_accounts.depends.append('offices') diff --git a/party.xml b/party.xml new file mode 100644 index 0000000..0d16d8d --- /dev/null +++ b/party.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/setup.py b/setup.py index 6ee9038..2a1855a 100644 --- a/setup.py +++ b/setup.py @@ -67,6 +67,20 @@ dependency_links = { 'branch': branch, 'series': series }, + 'purchase_office': + 'git+https://gitlab.com/datalifeit/' + 'trytond-purchase_office@%(branch)s' + '#egg=datalife_purchase_office-%(series)s' % { + 'branch': branch, + 'series': series + }, + 'analytic_party': + 'git+https://gitlab.com/datalifeit/' + 'trytond-analytic_party@%(branch)s' + '#egg=datalife_analytic_party-%(series)s' % { + 'branch': branch, + 'series': series + }, } requires = [] @@ -82,8 +96,11 @@ requires.append(get_require_version('trytond')) tests_require = [ get_require_version('proteus'), get_require_version('trytond_analytic_sale'), + get_require_version('trytond_analytic_purchase'), get_require_version('datalife_analytic_apply_rule'), - get_require_version('datalife_sale_office') + get_require_version('datalife_sale_office'), + get_require_version('datalife_purchase_office'), + get_require_version('datalife_analytic_party') ] dependency_links = list(dependency_links.values()) diff --git a/tests/scenario_analytic_office.rst b/tests/scenario_analytic_office.rst index 5cd2f81..a4f1e88 100644 --- a/tests/scenario_analytic_office.rst +++ b/tests/scenario_analytic_office.rst @@ -1,161 +1,159 @@ -================================ -Analytic Company Office Scenario -================================ +======================== +Analytic Office Scenario +======================== Imports:: - >>> import datetime - >>> from dateutil.relativedelta import relativedelta - >>> from decimal import Decimal - >>> from operator import attrgetter - >>> from proteus import Model, Wizard, Report - >>> from trytond.tests.tools import activate_modules, set_user + >>> from proteus import Model, Wizard + >>> from trytond.tests.tools import activate_modules >>> from trytond.modules.company.tests.tools import create_company, \ ... get_company - >>> from trytond.modules.account.tests.tools import create_fiscalyear, \ - ... create_chart, get_accounts - >>> from trytond.modules.account_invoice.tests.tools import \ - ... set_fiscalyear_invoice_sequences, create_payment_term - >>> today = datetime.date.today() + Install analytic_office:: - >>> config = activate_modules(['analytic_sale', 'sale_office', 'analytic_office', 'analytic_apply_rule']) + >>> config = activate_modules(['analytic_office', 'analytic_party']) + Create company:: >>> _ = create_company() >>> company = get_company() -Create sale user:: + +Get user:: >>> User = Model.get('res.user') - >>> Group = Model.get('res.group') - >>> sale_user = User() - >>> sale_user.name = 'Sale' - >>> sale_user.login = 'sale' - >>> sale_user.main_company = company - >>> sale_group, = Group.find([('name', '=', 'Sales')]) - >>> sale_user.groups.append(sale_group) - >>> sale_user.save() + >>> admin = User(config.user) -Create fiscal year:: - >>> fiscalyear = set_fiscalyear_invoice_sequences( - ... create_fiscalyear(company)) - >>> fiscalyear.click('create_period') +Create party:: -Create chart of accounts:: + >>> Party = Model.get('party.party') + >>> party = Party(name='Party') + >>> party.save() - >>> _ = create_chart(company) - >>> accounts = get_accounts(company) - >>> revenue = accounts['revenue'] - >>> expense = accounts['expense'] - -Create branch office:: - - >>> Office = Model.get('company.office') - >>> office1 = Office(name='Office 1') - >>> office1.save() - >>> office2 = Office(name='Office 2') - >>> office2.save() - >>> User = Model.get('res.user') - >>> Group = Model.get('res.group') - >>> user = User(config.user) - >>> user.offices.extend([office1, office2]) - >>> office1 = Office(office1.id) - >>> user.office = office1 - >>> user.save() - >>> set_user(user) - >>> config._context = User.get_preferences(True, {}) Create analytic accounts:: >>> AnalyticAccount = Model.get('analytic_account.account') - >>> root = AnalyticAccount(type='root', name='Root') + >>> root = AnalyticAccount() + >>> root.name = 'Root' + >>> root.code = '1' + >>> root.type = 'root' >>> root.save() - >>> analytic_account = AnalyticAccount(root=root, parent=root, - ... name='Analytic') + >>> view_account = AnalyticAccount() + >>> view_account.name = 'View 1' + >>> view_account.code = '11' + >>> view_account.type = 'view' + >>> view_account.root = root + >>> view_account.parent = root + >>> view_account.save() + >>> analytic_account = AnalyticAccount() + >>> analytic_account.name = 'Analytic 1' + >>> analytic_account.code = '111' + >>> analytic_account.root = root + >>> analytic_account.parent = view_account >>> analytic_account.save() - >>> mandatory_root = AnalyticAccount(type='root', name='Root', - ... mandatory=True) - >>> mandatory_root.save() - >>> mandatory_analytic_account1 = AnalyticAccount(root=mandatory_root, - ... parent=mandatory_root, name='Mandatory Analytic 1') - >>> mandatory_analytic_account1.save() - >>> mandatory_analytic_account2 = AnalyticAccount(root=mandatory_root, - ... parent=mandatory_root, name='Mandatory Analytic 2') - >>> mandatory_analytic_account2.save() - >>> mandatory_analytic_account3 = AnalyticAccount(root=mandatory_root, - ... parent=mandatory_root, name='Mandatory Analytic 3') - >>> mandatory_analytic_account3.save() + >>> view_account2 = AnalyticAccount() + >>> view_account2.name = 'View 2' + >>> view_account2.code = '12' + >>> view_account2.type = 'view' + >>> view_account2.root = root + >>> view_account2.parent = root + >>> view_account2.save() + >>> analytic_account2 = AnalyticAccount() + >>> analytic_account2.name = 'Analytic 2' + >>> analytic_account2.code = '121' + >>> analytic_account2.root = root + >>> analytic_account2.parent = view_account2 + >>> analytic_account2.save() -Create parties:: - >>> Party = Model.get('party.party') - >>> customer = Party(name='Customer') - >>> customer.save() - >>> customer2 = Party(name='Customer 2') - >>> customer2.save() +Create offices:: -Create analytic rules:: + >>> Office = Model.get('company.office') + >>> office = Office() + >>> office.name = 'Office 1' + >>> office.company = company + >>> office.save() + >>> office2 = Office() + >>> office2.name = 'Office 2' + >>> office2.company = company + >>> office2.save() - >>> Rule = Model.get('analytic_account.rule') - >>> rule = Rule() - >>> _, mandatory_entry = rule.analytic_accounts - >>> mandatory_entry.root = mandatory_root - >>> mandatory_entry.account = mandatory_analytic_account3 - >>> rule.save() - >>> rule = Rule(sale=True, party=customer, office=office2) - >>> _, mandatory_entry = rule.analytic_accounts - >>> mandatory_entry.root = mandatory_root - >>> mandatory_entry.account = mandatory_analytic_account1 - >>> rule.save() - >>> rule = Rule(sale=True, office=office1) - >>> _, mandatory_entry = rule.analytic_accounts - >>> mandatory_entry.root = mandatory_root - >>> mandatory_entry.account = mandatory_analytic_account2 - >>> rule.save() -Create account category:: +Add office to admin user and reload context:: - >>> ProductCategory = Model.get('product.category') - >>> account_category = ProductCategory(name="Account Category") - >>> account_category.accounting = True - >>> account_category.account_expense = expense - >>> account_category.account_revenue = revenue - >>> account_category.save() + >>> admin.offices.append(office) + >>> office = Office(office.id) + >>> admin.offices.append(office2) + >>> office2 = Office(office2.id) + >>> admin.office = office + >>> admin.save() + >>> config._context = User.get_preferences(True, config.context) -Create product:: - >>> ProductUom = Model.get('product.uom') - >>> unit, = ProductUom.find([('name', '=', 'Unit')]) - >>> ProductTemplate = Model.get('product.template') - >>> template = ProductTemplate() - >>> template.name = 'product' - >>> template.default_uom = unit - >>> template.type = 'goods' - >>> template.salable = True - >>> template.list_price = Decimal('10') - >>> template.account_category = account_category - >>> template.save() - >>> product, = template.products +Add analytic account to party when account office isn't set:: -Create payment term:: + >>> party.analytic_accounts.append(analytic_account) + >>> analytic_account = AnalyticAccount(analytic_account.id) + >>> party.save() + Traceback (most recent call last): + ... + trytond.exceptions.UserError: The value of the field "Analytic Accounts" on "Party" is not valid according to its domain. - + >>> party.reload() - >>> payment_term = create_payment_term() - >>> payment_term.save() -Sale with analytic accounts:: +Add analytic_account to offices:: - >>> Sale = Model.get('sale.sale') - >>> SaleLine = Model.get('sale.line') - >>> sale = Sale() - >>> sale.party = customer - >>> sale.payment_term = payment_term - >>> sale.office == office1 - True - >>> sale_line = sale.lines.new() - >>> mandatory_entry, = [a for a in sale_line.analytic_accounts if a.required] - >>> mandatory_entry.account == mandatory_analytic_account2 - True \ No newline at end of file + >>> office.analytic_accounts.append(analytic_account) + >>> analytic_account = AnalyticAccount(analytic_account.id) + >>> office.save() + Traceback (most recent call last): + ... + trytond.exceptions.UserError: The value of the field "Analytic Accounts" on "Company branch office" is not valid according to its domain. - + >>> office.reload() + >>> office.analytic_accounts.append(view_account) + >>> view_account = AnalyticAccount(view_account.id) + >>> office.save() + >>> office2.analytic_accounts.append(view_account2) + >>> view_account2 = AnalyticAccount(view_account2.id) + >>> office2.save() + + +Add analytic account Again to party:: + + >>> party.analytic_accounts.append(analytic_account) + >>> analytic_account = AnalyticAccount(analytic_account.id) + >>> party.save() + + +Add wrong office to party:: + + >>> party.offices.append(office2) + >>> office2 = Office(office2.id) + >>> party.save() + Traceback (most recent call last): + ... + trytond.exceptions.UserError: The value of the field "Analytic Accounts" on "Party" is not valid according to its domain. - + + >>> party.reload() + + +Add office to party:: + + >>> party.offices.append(office) + >>> office = Office(office.id) + >>> party.save() + + +Add wrong office2 analytic account to party:: + + >>> party.analytic_accounts.append(analytic_account2) + >>> analytic_account2 = AnalyticAccount(analytic_account2.id) + >>> party.save() + Traceback (most recent call last): + ... + trytond.exceptions.UserError: The value of the field "Analytic Accounts" on "Party" is not valid according to its domain. - + >>> party.reload() diff --git a/tests/scenario_analytic_office_rule.rst b/tests/scenario_analytic_office_rule.rst new file mode 100644 index 0000000..bb07d84 --- /dev/null +++ b/tests/scenario_analytic_office_rule.rst @@ -0,0 +1,161 @@ +================================ +Analytic Office Rule Scenario +================================ + +Imports:: + + >>> import datetime + >>> from dateutil.relativedelta import relativedelta + >>> from decimal import Decimal + >>> from operator import attrgetter + >>> from proteus import Model, Wizard, Report + >>> from trytond.tests.tools import activate_modules, set_user + >>> from trytond.modules.company.tests.tools import create_company, \ + ... get_company + >>> from trytond.modules.account.tests.tools import create_fiscalyear, \ + ... create_chart, get_accounts + >>> from trytond.modules.account_invoice.tests.tools import \ + ... set_fiscalyear_invoice_sequences, create_payment_term + >>> today = datetime.date.today() + +Install analytic_office:: + + >>> config = activate_modules(['analytic_sale', 'sale_office', 'analytic_office', 'analytic_apply_rule']) + +Create company:: + + >>> _ = create_company() + >>> company = get_company() + +Create sale user:: + + >>> User = Model.get('res.user') + >>> Group = Model.get('res.group') + >>> sale_user = User() + >>> sale_user.name = 'Sale' + >>> sale_user.login = 'sale' + >>> sale_user.main_company = company + >>> sale_group, = Group.find([('name', '=', 'Sales')]) + >>> sale_user.groups.append(sale_group) + >>> sale_user.save() + +Create fiscal year:: + + >>> fiscalyear = set_fiscalyear_invoice_sequences( + ... create_fiscalyear(company)) + >>> fiscalyear.click('create_period') + +Create chart of accounts:: + + >>> _ = create_chart(company) + >>> accounts = get_accounts(company) + >>> revenue = accounts['revenue'] + >>> expense = accounts['expense'] + +Create branch office:: + + >>> Office = Model.get('company.office') + >>> office1 = Office(name='Office 1') + >>> office1.save() + >>> office2 = Office(name='Office 2') + >>> office2.save() + >>> User = Model.get('res.user') + >>> Group = Model.get('res.group') + >>> user = User(config.user) + >>> user.offices.extend([office1, office2]) + >>> office1 = Office(office1.id) + >>> user.office = office1 + >>> user.save() + >>> set_user(user) + >>> config._context = User.get_preferences(True, {}) + +Create analytic accounts:: + + >>> AnalyticAccount = Model.get('analytic_account.account') + >>> root = AnalyticAccount(type='root', name='Root') + >>> root.save() + >>> analytic_account = AnalyticAccount(root=root, parent=root, + ... name='Analytic') + >>> analytic_account.save() + >>> mandatory_root = AnalyticAccount(type='root', name='Root', + ... mandatory=True) + >>> mandatory_root.save() + >>> mandatory_analytic_account1 = AnalyticAccount(root=mandatory_root, + ... parent=mandatory_root, name='Mandatory Analytic 1') + >>> mandatory_analytic_account1.save() + >>> mandatory_analytic_account2 = AnalyticAccount(root=mandatory_root, + ... parent=mandatory_root, name='Mandatory Analytic 2') + >>> mandatory_analytic_account2.save() + >>> mandatory_analytic_account3 = AnalyticAccount(root=mandatory_root, + ... parent=mandatory_root, name='Mandatory Analytic 3') + >>> mandatory_analytic_account3.save() + +Create parties:: + + >>> Party = Model.get('party.party') + >>> customer = Party(name='Customer') + >>> customer.save() + >>> customer2 = Party(name='Customer 2') + >>> customer2.save() + +Create analytic rules:: + + >>> Rule = Model.get('analytic_account.rule') + >>> rule = Rule() + >>> _, mandatory_entry = rule.analytic_accounts + >>> mandatory_entry.root = mandatory_root + >>> mandatory_entry.account = mandatory_analytic_account3 + >>> rule.save() + >>> rule = Rule(sale=True, party=customer, office=office2) + >>> _, mandatory_entry = rule.analytic_accounts + >>> mandatory_entry.root = mandatory_root + >>> mandatory_entry.account = mandatory_analytic_account1 + >>> rule.save() + >>> rule = Rule(sale=True, office=office1) + >>> _, mandatory_entry = rule.analytic_accounts + >>> mandatory_entry.root = mandatory_root + >>> mandatory_entry.account = mandatory_analytic_account2 + >>> rule.save() + +Create account category:: + + >>> ProductCategory = Model.get('product.category') + >>> account_category = ProductCategory(name="Account Category") + >>> account_category.accounting = True + >>> account_category.account_expense = expense + >>> account_category.account_revenue = revenue + >>> account_category.save() + +Create product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'goods' + >>> template.salable = True + >>> template.list_price = Decimal('10') + >>> template.account_category = account_category + >>> template.save() + >>> product, = template.products + +Create payment term:: + + >>> payment_term = create_payment_term() + >>> payment_term.save() + +Sale with analytic accounts:: + + >>> Sale = Model.get('sale.sale') + >>> SaleLine = Model.get('sale.line') + >>> sale = Sale() + >>> sale.party = customer + >>> sale.payment_term = payment_term + >>> sale.office == office1 + True + >>> sale_line = sale.lines.new() + >>> mandatory_entry, = [a for a in sale_line.analytic_accounts if a.required] + >>> mandatory_entry.account == mandatory_analytic_account2 + True \ No newline at end of file diff --git a/tests/scenario_analytic_purchase.rst b/tests/scenario_analytic_purchase.rst new file mode 100644 index 0000000..187daad --- /dev/null +++ b/tests/scenario_analytic_purchase.rst @@ -0,0 +1,159 @@ +========================== +Analytic Purchase Scenario +========================== + +Imports:: + + >>> from decimal import Decimal + >>> from proteus import Model, Wizard + >>> from trytond.tests.tools import activate_modules + >>> from trytond.modules.company.tests.tools import create_company, \ + ... get_company + + +Install analytic_party:: + + >>> config = activate_modules(['analytic_office', 'analytic_party', + ... 'analytic_purchase', 'purchase_office']) + + +Create company:: + + >>> _ = create_company() + >>> company = get_company() + + +Get user:: + + >>> User = Model.get('res.user') + >>> admin = User(config.user) + + +Create Supplier:: + + >>> Party = Model.get('party.party') + >>> supplier = Party(name='Supplier') + >>> supplier.save() + + +Create analytic accounts:: + + >>> AnalyticAccount = Model.get('analytic_account.account') + >>> root = AnalyticAccount() + >>> root.name = 'Root' + >>> root.code = '1' + >>> root.type = 'root' + >>> root.save() + >>> view_account = AnalyticAccount() + >>> view_account.name = 'View' + >>> view_account.code = '11' + >>> view_account.type = 'view' + >>> view_account.root = root + >>> view_account.parent = root + >>> view_account.save() + >>> view_account2 = AnalyticAccount() + >>> view_account2.name = 'View 2' + >>> view_account2.code = '12' + >>> view_account2.type = 'view' + >>> view_account2.root = root + >>> view_account2.parent = root + >>> view_account2.save() + >>> analytic_account = AnalyticAccount() + >>> analytic_account.name = 'Analytic 111' + >>> analytic_account.code = '111' + >>> analytic_account.root = root + >>> analytic_account.parent = view_account + >>> analytic_account.save() + >>> analytic_account2 = AnalyticAccount() + >>> analytic_account2.name = 'Analytic 121' + >>> analytic_account2.code = '121' + >>> analytic_account2.root = root + >>> analytic_account2.parent = view_account2 + >>> analytic_account2.save() + + +Create office:: + + >>> Office = Model.get('company.office') + >>> office = Office() + >>> office.name = 'Office 1' + >>> office.company = company + >>> office.save() + >>> office2 = Office() + >>> office2.name = 'Office 2' + >>> office2.company = company + >>> office2.save() + + +Setup offices to users and reload context:: + + >>> admin.offices.append(office) + >>> office = Office(office.id) + >>> admin.offices.append(office2) + >>> office2 = Office(office2.id) + >>> admin.office = office + >>> admin.save() + >>> config._context = User.get_preferences(True, config.context) + + +Add analytic_accounts to offices:: + + >>> office.analytic_accounts.append(view_account) + >>> view_account = AnalyticAccount(view_account.id) + >>> office.save() + >>> office2.analytic_accounts.append(view_account2) + >>> view_account2 = AnalyticAccount(view_account2.id) + >>> office2.save() + + +Add anaytic accounts to supplier:: + + >>> supplier.analytic_accounts.append(analytic_account) + >>> analytic_account = AnalyticAccount(analytic_account.id) + >>> supplier.analytic_accounts.append(analytic_account2) + >>> analytic_account2 = AnalyticAccount(analytic_account2.id) + >>> supplier.save() + + +Create Product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'service' + >>> template.list_price = Decimal('40') + >>> template.purchasable = True + >>> template.save() + >>> product, = template.products + + +Create Purchase:: + + >>> Purchase = Model.get('purchase.purchase') + >>> purchase = Purchase() + >>> purchase.party = supplier + >>> purchase.office = office + >>> pline = purchase.lines.new() + >>> pline.product = product + >>> pline.quantity = 2.0 + >>> entry_acc, = pline.analytic_accounts + >>> entry_acc.account == analytic_account + True + >>> purchase.save() + + +Create purchase with office2:: + + >>> purchase2 = Purchase() + >>> purchase2.party = supplier + >>> purchase2.office = office2 + >>> pline = purchase2.lines.new() + >>> pline.product = product + >>> pline.quantity = 2.0 + >>> entry_acc, = pline.analytic_accounts + >>> entry_acc.account == analytic_account2 + True + >>> purchase2.save() \ No newline at end of file diff --git a/tests/scenario_analytic_sale.rst b/tests/scenario_analytic_sale.rst new file mode 100644 index 0000000..137aab8 --- /dev/null +++ b/tests/scenario_analytic_sale.rst @@ -0,0 +1,159 @@ +====================== +Analytic Sale Scenario +====================== + +Imports:: + + >>> from decimal import Decimal + >>> from proteus import Model, Wizard + >>> from trytond.tests.tools import activate_modules + >>> from trytond.modules.company.tests.tools import create_company, \ + ... get_company + + +Install analytic_office:: + + >>> config = activate_modules(['analytic_office', 'analytic_party', + ... 'analytic_sale', 'sale_office']) + + +Create company:: + + >>> _ = create_company() + >>> company = get_company() + + +Get user:: + + >>> User = Model.get('res.user') + >>> admin = User(config.user) + + +Create Customer:: + + >>> Party = Model.get('party.party') + >>> customer = Party(name='Customer') + >>> customer.save() + + +Create analytic accounts:: + + >>> AnalyticAccount = Model.get('analytic_account.account') + >>> root = AnalyticAccount() + >>> root.name = 'Root' + >>> root.code = '1' + >>> root.type = 'root' + >>> root.save() + >>> view_account = AnalyticAccount() + >>> view_account.name = 'View' + >>> view_account.code = '11' + >>> view_account.type = 'view' + >>> view_account.root = root + >>> view_account.parent = root + >>> view_account.save() + >>> view_account2 = AnalyticAccount() + >>> view_account2.name = 'View 2' + >>> view_account2.code = '12' + >>> view_account2.type = 'view' + >>> view_account2.root = root + >>> view_account2.parent = root + >>> view_account2.save() + >>> analytic_account = AnalyticAccount() + >>> analytic_account.name = 'Analytic 111' + >>> analytic_account.code = '111' + >>> analytic_account.root = root + >>> analytic_account.parent = view_account + >>> analytic_account.save() + >>> analytic_account2 = AnalyticAccount() + >>> analytic_account2.name = 'Analytic 121' + >>> analytic_account2.code = '121' + >>> analytic_account2.root = root + >>> analytic_account2.parent = view_account2 + >>> analytic_account2.save() + + +Create office:: + + >>> Office = Model.get('company.office') + >>> office = Office() + >>> office.name = 'Office 1' + >>> office.company = company + >>> office.save() + >>> office2 = Office() + >>> office2.name = 'Office 2' + >>> office2.company = company + >>> office2.save() + + +Setup offices to users and reload context:: + + >>> admin.offices.append(office) + >>> office = Office(office.id) + >>> admin.offices.append(office2) + >>> office2 = Office(office2.id) + >>> admin.office = office + >>> admin.save() + >>> config._context = User.get_preferences(True, config.context) + + +Add analytic_accounts to offices:: + + >>> office.analytic_accounts.append(view_account) + >>> view_account = AnalyticAccount(view_account.id) + >>> office.save() + >>> office2.analytic_accounts.append(view_account2) + >>> view_account2 = AnalyticAccount(view_account2.id) + >>> office2.save() + + +Add anaytic accounts to customer:: + + >>> customer.analytic_accounts.append(analytic_account) + >>> analytic_account = AnalyticAccount(analytic_account.id) + >>> customer.analytic_accounts.append(analytic_account2) + >>> analytic_account2 = AnalyticAccount(analytic_account2.id) + >>> customer.save() + + +Create Product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'service' + >>> template.list_price = Decimal('40') + >>> template.salable = True + >>> template.save() + >>> product, = template.products + + +Create Sale:: + + >>> Sale = Model.get('sale.sale') + >>> sale = Sale() + >>> sale.party = customer + >>> sale.office = office + >>> sline = sale.lines.new() + >>> sline.product = product + >>> sline.quantity = 2.0 + >>> entry_acc, = sline.analytic_accounts + >>> entry_acc.account == analytic_account + True + >>> sale.save() + + +Create sale with office2:: + + >>> sale2 = Sale() + >>> sale2.party = customer + >>> sale2.office = office2 + >>> sline = sale2.lines.new() + >>> sline.product = product + >>> sline.quantity = 2.0 + >>> entry_acc, = sline.analytic_accounts + >>> entry_acc.account == analytic_account2 + True + >>> sale2.save() \ No newline at end of file diff --git a/tests/test_analytic_office.py b/tests/test_analytic_office.py index 30b934d..12e04c9 100644 --- a/tests/test_analytic_office.py +++ b/tests/test_analytic_office.py @@ -24,4 +24,19 @@ def suite(): tearDown=doctest_teardown, encoding='utf-8', checker=doctest_checker, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_analytic_office_rule.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_analytic_sale.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_analytic_purchase.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) return suite diff --git a/tryton.cfg b/tryton.cfg index 76a3f8e..d8ddfb7 100644 --- a/tryton.cfg +++ b/tryton.cfg @@ -12,7 +12,9 @@ extras_depend: sale_office analytic_purchase purchase_office + analytic_party xml: account.xml - + office.xml + party.xml diff --git a/view/office_form.xml b/view/office_form.xml new file mode 100644 index 0000000..18f4f3d --- /dev/null +++ b/view/office_form.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file