Commit 5b8207c4 authored by Luca Cristaldi's avatar Luca Cristaldi

Stable version of the association module

parent 3c6eadf6
from trytond.pool import Pool
from .account import *
from .member import *
from .membership import *
from .configuration import *
from .ir import *
__all__ = ['register']
def register():
Pool.register(
Member, Configuration, MemberSequence,Membership, MembershipPeriod, MembershipFee,MembershipLine,
Member,
Configuration,
MemberSequence,
Membership,
Period,
Fee,
Line,
Move,
GenerateFeeStart,
Cron,
module='association', type_='model')
Pool.register(
PostFee,
GenerateFee,
module='association', type_='wizard')
Pool.register(
module='association', type_='report')
Pool.register(module='association', type_='report')
from trytond.pool import PoolMeta, Pool
__all__ = ['Move']
class Move(metaclass=PoolMeta):
__name__ = 'account.move'
@classmethod
def _get_origin(cls):
return super(Move, cls)._get_origin() + ['association.membership.fee']
\ No newline at end of file
from trytond.exceptions import UserError, UserWarning
from trytond.model.exceptions import ValidationError
......@@ -6,12 +5,14 @@ class PeriodValidationError(ValidationError):
pass
class PeriodDatesError(PeriodValidationError):
class PeriodDateOverlapError(PeriodValidationError):
pass
class DateNotInPeriodError(PeriodValidationError):
pass
class SequenceMissingError(ValidationError):
pass
......@@ -21,4 +22,3 @@ class SequenceMissingError(ValidationError):
# ('No sequence defined for member. You must '
# 'define a sequence or enter the member\'s number.'),
# })
from trytond.pool import PoolMeta
class Cron(metaclass=PoolMeta):
__name__ = 'ir.cron'
@classmethod
def __setup__(cls):
super().__setup__()
cls.method.selection.extend([
('association.membership.fee|generate_fees',
"Generate Fee Lines"),
])
......@@ -52,7 +52,7 @@ class Member(Workflow, ModelSQL, ModelView):
(),
)
],
depends=['leave_date'],
depends=['leave_date', 'state'],
states={'readonly': Eval('state') != 'draft'},
help="When the member joins the association.")
leave_date = fields.Date('Leave Date',
......@@ -64,7 +64,7 @@ class Member(Workflow, ModelSQL, ModelView):
(),
)
],
depends=['join_date'],
depends=['join_date', 'state'],
states={
'readonly':
Eval('state') != 'running',
......@@ -73,18 +73,17 @@ class Member(Workflow, ModelSQL, ModelView):
},
help="When the member leaves the association.")
memberships = fields.One2Many('association.membership.line',
'member',
"Memberships",
# domain=[
# ('start_date', '>=',
# Eval('join_date', None)),
# # ('end_date', '<=',
# # Eval('leave_date', None)),
# ],
depends=['join_date', 'leave_date'],
)
fees = fields.One2Many('association.membership.fee', 'member', 'fee')
memberships = fields.One2Many(
'association.membership.line',
'member',
"Memberships",
depends=['state'],
states={'readonly': Eval('state') != 'draft'})
fees = fields.One2Many('association.membership.fee',
'member',
'fee',
states={'readonly': Eval('state') != 'draft'},
depends=['state'])
#TODO: check via sql verifi method
@classmethod
......@@ -93,7 +92,6 @@ class Member(Workflow, ModelSQL, ModelView):
t = cls.__table__()
cls._sql_constraints = [
('code_uniq', Unique(t, t.code), 'Member code must be unique.'),
# ('party_uniq', Unique(t, t.party), 'Party must be unique.')
]
cls._transitions |= {('draft', 'running'),
('running', 'draft'),
......@@ -101,15 +99,15 @@ class Member(Workflow, ModelSQL, ModelView):
cls._buttons.update({
'draft': {
'invisible': Eval('state').in_(['draft','stopped']),
'invisible': Eval('state').in_(['draft', 'stopped']),
'depends': ['state'],
},
'run': {
'invisible': Eval('state').in_(['stopped','running']),
'invisible': Eval('state').in_(['stopped', 'running']),
'depends': ['state'],
},
'stop': {
'invisible': Eval('state').in_(['draft','stopped']),
'invisible': Eval('state').in_(['draft', 'stopped']),
'depends': ['state'],
},
})
......@@ -163,19 +161,6 @@ class Member(Workflow, ModelSQL, ModelView):
def draft(cls, members):
pass
# @classmethod
# @ModelView.button
# @Workflow.transition('pending')
# def validate_member(cls, members):
# pool = Pool()
# Date = pool.get('ir.date')
# for member in members:
# if not member.request_date:
# member.request_date = Date.today()
# member.join_date = None
# member.leave_date = None
# cls.save(members)
@classmethod
@ModelView.button
@Workflow.transition('running')
......
This diff is collapsed.
......@@ -13,7 +13,7 @@
<field name="name">membership_form</field>
</record>
<record model="ir.action.act_window" id="act_membership_form">
<field name="name">Membership</field>
<field name="name">Memberships</field>
<field name="res_model">association.membership</field>
</record>
<record model="ir.action.act_window.view" id="act_membership_form1">
......@@ -32,7 +32,7 @@
<field name="priority" eval="20" />
<field name="name">membership_period_tree_editable</field>
</record>
<menuitem name="Membership" sequence="20" parent="menu_association" id="menu_membership" action="act_membership_form" />
<menuitem name="Memberships" sequence="20" parent="menu_association" id="menu_membership" action="act_membership_form" icon="tryton-list" />
<!-- membership fee -->
<record model="ir.ui.view" id="membership_fee_view_tree">
<field name="model">association.membership.fee</field>
......@@ -40,6 +40,38 @@
<field name="priority" eval="20" />
<field name="name">membership_fee_tree</field>
</record>
<!-- Fee action genearte move -->
<record model="ir.model.button" id="membership_fee_button">
<field name="name">post_move</field>
<field name="string">move</field>
<field name="model" search="[('model', '=', 'association.membership.fee')]" />
</record>
<record model="ir.action.wizard" id="act_generate_move">
<field name="name">Generate Fee move</field>
<field name="wiz_name">association.membership.fee_move</field>
<field name="model">association.membership.fee</field>
</record>
<record model="ir.action.keyword" id="membership_fee_action_keyword">
<field name="keyword">form_action</field>
<field name="model">association.membership.fee,-1</field>
<field name="action" ref="act_generate_move" />
</record>
<!-- Fee wizard -->
<record model="ir.action.wizard" id="act_membership_fee_create">
<field name="name">Create Fees</field>
<field name="wiz_name">association.membership.fee_create</field>
</record>
<record model="ir.action.keyword" id="act_membership_fee_create_keyword">
<field name="keyword">form_action</field>
<field name="model">association.member,-1</field>
<field name="action" ref="act_membership_fee_create" />
</record>
<menuitem parent="menu_association" sequence="90" action="act_membership_fee_create" id="menu_act_membership_fee_create" />
<record model="ir.ui.view" id="create_membership_fee_view_form">
<field name="model">association.membership.fee_create.start</field>
<field name="type">form</field>
<field name="name">membership_fee_wizard_form</field>
</record>
<!-- membership line -->
<record model="ir.ui.view" id="membership_line_view_tree_editable">
<field name="model">association.membership.line</field>
......@@ -72,10 +104,24 @@
<field name="view" ref="view_membership_period_form" />
<field name="act_window" ref="view_membership_period_tree" />
</record>
<record model="ir.model.button" id="membership_fee_button">
<field name="name">post_move</field>
<field name="string">move</field>
<field name="model" search="[('model', '=', 'association.membership.fee')]" />
<!-- membership fee relate -->
<record model="ir.action.act_window" id="act_fees_form_relate">
<field name="name">Fees</field>
<field name="res_model">association.membership.fee</field>
<field name="domain"
eval="[('member', 'in', Eval('active_ids'))]"
pyson="1" />
</record>
<record model="ir.action.keyword" id="act_open_fees_form_relate">
<field name="keyword">form_relate</field>
<field name="model">association.member,-1</field>
<field name="action" ref="act_fees_form_relate" />
</record>
<!-- Create Fees Cronjob -->
<record model="ir.cron" id="cron_generate_invoice">
<field name="method">association.membership.fee|generate_fees</field>
<field name="interval_number" eval="1"/>
<field name="interval_type">days</field>
</record>
</data>
</tryton>
\ No newline at end of file
......@@ -3,5 +3,11 @@
<record model="ir.message" id="msg_date_non_in_period">
<field name="text">The date is outside the "%(period)s"</field>
</record>
<record model="ir.message" id="msg_overlapping_period">
<field name="text">The period "%(first)s" overlaps with the period "%(second)s"</field>
</record>
<record model="ir.message" id="msg_fee_delete">
<field name="text">You cannot delete the fee "%(fee)s"</field>
</record>
</data>
</tryton>
\ No newline at end of file
......@@ -39,6 +39,7 @@ Create chart of accounts::
>>> _ = create_chart(company)
>>> accounts = get_accounts(company)
>>> receivable = accounts['receivable']
>>> payable = accounts['payable']
>>> revenue = accounts['revenue']
>>> expense = accounts['expense']
>>> account_tax = accounts['tax']
......@@ -48,6 +49,8 @@ Create party::
>>> Party = Model.get('party.party')
>>> party = Party(name='Party')
>>> party.account_payable = payable
>>> party.account_receivable = receivable
>>> party.save()
Create memberships::
......@@ -106,5 +109,6 @@ Test memebrship fee::
>>> member.save()
>>> fee.click('post_move')
>>> fee.move
proteus.Model.get('account.move')(1)
......@@ -74,7 +74,7 @@ Create membership::
>>> overlapping =membership.periods.new(start_date=start_date,end_date=start_date+timedelta,name="overlapping",amount=Decimal(42)).save()
Traceback (most recent call last):
...
trytond.modules.association.exceptions.PeriodDatesError: ('UserError', ('The periods "overlapping" and "period 1" overlap, you must use different dates.', ''))
trytond.modules.association.exceptions.PeriodDateOverlapError: ('UserError', ('The period "overlapping" overlaps with the period "period 1"', ''))
>>> new_date = datetime.date(2020,1,1)
>>> inverted = membership.periods.new(start_date=new_date + timedelta,end_date=start_date,name="inverted",amount=Decimal(42)).save()
Traceback (most recent call last):
......
===============
Member Scenario
===============
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
>>> from operator import attrgetter
>>> 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, create_tax, create_tax_code
>>> from trytond.modules.association.tests.tools import create_period
>>> from decimal import *
>>> today = datetime.date.today()
Install associatio::
Please register or sign in to reply
>>> config = activate_modules('association')
Create company::
>>> _ = create_company()
>>> company = get_company()
Create fiscal year::
>>> fiscalyear = create_fiscalyear(company)
>>> fiscalyear.click('create_period')
>>> period = fiscalyear.periods[0]
Create chart of accounts::
>>> _ = create_chart(company)
>>> accounts = get_accounts(company)
>>> receivable = accounts['receivable']
>>> payable = accounts['payable']
>>> revenue = accounts['revenue']
>>> expense = accounts['expense']
>>> account_tax = accounts['tax']
>>> account_cash = accounts['cash']
Create party::
>>> Party = Model.get('party.party')
>>> party = Party(name='Party')
>>> party.account_payable = payable
>>> party.account_receivable = receivable
>>> party.save()
Create member::
>>> Member = Model.get('association.member')
>>> member = Member()
>>> member.party = party
>>> member.save()
Create membership::
>>> start_date = datetime.date(2018,1,1)
>>> fiscalMonth = 13
>>> timedelta = datetime.timedelta(weeks=4)
>>> Membership = Model.get('association.membership')
>>> Period = Model.get('association.membership.period')
>>> membership1 = Membership()
>>> membership1.party = party
>>> membership1.name = "membership1"
>>> membership1.account_revenue = revenue
>>> datedeltas = [(start_date + timedelta*(n-1) + datetime.timedelta(days=1),start_date + timedelta*n,f"{membership1.name} - {n}") for n in range(1,fiscalMonth+1)]
>>> periods1 = [ membership1.periods.new(start_date=period[0],end_date=period[1], name=period[2], amount=Decimal(42)) for period in datedeltas ]
>>> membership1.save()
>>> start_date = datetime.date(2018,1,1)
>>> membership2 = Membership()
>>> membership2.party = party
>>> membership2.name = "membership2:Electric boogaloo"
>>> membership2.account_revenue = revenue
>>> datedeltas = [(start_date + timedelta*(n-1) + datetime.timedelta(days=1),start_date + timedelta*n,f"{membership2.name} - {n}") for n in range(1,fiscalMonth+1)]
>>> periods2 = [ membership2.periods.new(start_date=period[0],end_date=period[1], name=period[2], amount=Decimal(42)) for period in datedeltas ]
>>> membership2.save()
Add membership to member::
>>> memperships = [ membership1, membership2 ]
>>> _ = [ member.memberships.new(membership=m,start_date = start_date + datetime.timedelta(weeks=4),end_date = start_date + datetime.timedelta(weeks=50)) for m in memperships]
>>> member.join_date = start_date + datetime.timedelta(weeks=6)
>>> member.leave_date = start_date + datetime.timedelta(weeks=35)
>>> member.save()
Create fee lines::
>>> create_fee = Wizard('association.membership.fee_create')
>>> create_fee.form.date = start_date + datetime.timedelta(weeks=40)
>>> create_fee.execute('create_')
......@@ -14,7 +14,7 @@ class AssociationTestCase(ModuleTestCase):
def suite():
suite = test_suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
AssociationTestCase))
AssociationTestCase))
Please register or sign in to reply
suite.addTests(doctest.DocFileSuite('scenario_membership.rst',
tearDown=doctest_teardown, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
......@@ -23,5 +23,8 @@ def suite():
tearDown=doctest_teardown, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
checker=doctest_checker))
suite.addTests(doctest.DocFileSuite('scenario_membership_fee.rst',
tearDown=doctest_teardown, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE,
checker=doctest_checker))
return suite
......@@ -2,5 +2,4 @@
<tree editable="bottom">
<field name="period" />
<field name="paid" />
<button name="post_move" />
</tree>
\ No newline at end of file
<form col="2">
<image name="tryton-info" xexpand="0" xfill="0"/>
<group col="2" xexpand="1" id="create_date">
<label string="Create Membership fees for date"
id="create"/>
<field name="date"/>
</group>
</form>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment