Merge branch 'golem_resource_pack'
This commit is contained in:
commit
e8d6336bca
19
golem_resource_pack/__init__.py
Normal file
19
golem_resource_pack/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import models, wizard
|
33
golem_resource_pack/__manifest__.py
Normal file
33
golem_resource_pack/__manifest__.py
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
{
|
||||
'name': 'GOLEM resources pack',
|
||||
'summary': 'GOLEM resources pack',
|
||||
'description': ''' GOLEM resources pack ''',
|
||||
'version': '10.0.0.0.4',
|
||||
'category': 'GOLEM',
|
||||
'author': 'Youssef El Ouahby, Fabien Bourgeois',
|
||||
'license': 'AGPL-3',
|
||||
'application': False,
|
||||
'installable': True,
|
||||
'depends': ['golem_resource'],
|
||||
'data': ['views/golem_resource_pack_views.xml',
|
||||
'wizard/golem_pack_rejection_views.xml',
|
||||
'security/ir.model.access.csv']
|
||||
}
|
19
golem_resource_pack/models/__init__.py
Normal file
19
golem_resource_pack/models/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import golem_resource_pack, golem_resource_reservation
|
127
golem_resource_pack/models/golem_resource_pack.py
Normal file
127
golem_resource_pack/models/golem_resource_pack.py
Normal file
@ -0,0 +1,127 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" GOLEM Resource Packs """
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class GolemResourcePack(models.Model):
|
||||
""" GOLEM Resource Pack Model """
|
||||
_name = 'golem.resource.pack'
|
||||
_description = 'GOLEM Resource Pack Model'
|
||||
_inherit = 'mail.thread'
|
||||
|
||||
name = fields.Char(required=True)
|
||||
reservation_ids = fields.One2many('golem.resource.reservation', 'pack_id',
|
||||
readonly=True, string='Reservations',
|
||||
states={'draft': [('readonly', False)]})
|
||||
|
||||
note = fields.Text(help='Notes, optional subject for the reservation, reason',
|
||||
track_visibility='onchange', readonly=True,
|
||||
states={'draft': [('readonly', False)]})
|
||||
|
||||
user_id = fields.Many2one('res.users', required=True, index=True, readonly=True,
|
||||
string='User', default=lambda self: self.env.user)
|
||||
partner_id = fields.Many2one('res.partner', string='On behalf of', required=True,
|
||||
index=True, track_visibility='onchange', readonly=True,
|
||||
states={'draft': [('readonly', False)]})
|
||||
state = fields.Selection([('canceled', 'Canceled'),
|
||||
('draft', 'Draft'),
|
||||
('confirmed', 'Confirmed'),
|
||||
('validated', 'Validated'),
|
||||
('rejected', 'Rejected')],
|
||||
default='draft', compute='_compute_pack_state',
|
||||
track_visibility='onchange')
|
||||
reservation_count = fields.Integer(compute='_compute_reservation_count')
|
||||
rejection_reason = fields.Text(readonly=True, track_visibility='onchange')
|
||||
|
||||
@api.depends('reservation_ids')
|
||||
def _compute_reservation_count(self):
|
||||
for pack in self:
|
||||
pack.reservation_count = len(pack.reservation_ids)
|
||||
|
||||
@api.depends('reservation_ids', 'reservation_ids.state')
|
||||
def _compute_pack_state(self):
|
||||
""" get pack state """
|
||||
for pack in self:
|
||||
if not pack.reservation_ids:
|
||||
pack.state = 'draft'
|
||||
else:
|
||||
reservation_states = pack.mapped('reservation_ids.state')
|
||||
if 'rejected' in reservation_states:
|
||||
pack.state = 'rejected'
|
||||
elif 'canceled' in reservation_states:
|
||||
pack.state = 'canceled'
|
||||
elif 'draft' in reservation_states:
|
||||
pack.state = 'draft'
|
||||
elif 'confirmed' in reservation_states:
|
||||
pack.state = 'confirmed'
|
||||
elif 'validated' in reservation_states:
|
||||
pack.state = 'validated'
|
||||
|
||||
@api.multi
|
||||
def state_confirm(self):
|
||||
""" pack confirm """
|
||||
for pack in self:
|
||||
pack.reservation_ids.state_confirm()
|
||||
|
||||
@api.multi
|
||||
def state_draft(self):
|
||||
""" pack canceled """
|
||||
for pack in self:
|
||||
pack.reservation_ids.state_draft()
|
||||
|
||||
@api.multi
|
||||
def state_canceled(self):
|
||||
""" pack canceled """
|
||||
for pack in self:
|
||||
pack.reservation_ids.state_canceled()
|
||||
|
||||
@api.multi
|
||||
def state_validated(self):
|
||||
""" pack validated """
|
||||
for pack in self:
|
||||
pack.reservation_ids.state_validated()
|
||||
|
||||
@api.multi
|
||||
def state_rejected(self):
|
||||
""" Wizard call for pack reject """
|
||||
self.ensure_one()
|
||||
pack_id = self[0]
|
||||
return {'name' : _('Please enter the rejection reason'),
|
||||
'type' : 'ir.actions.act_window',
|
||||
'res_model' : 'golem.pack.rejection.wizard',
|
||||
'context': {'default_pack_id': pack_id.id},
|
||||
'view_mode': 'form',
|
||||
'target': 'new'}
|
||||
|
||||
@api.constrains('partner_id')
|
||||
def set_reservation_partner(self):
|
||||
""" Set reservation partner """
|
||||
for pack in self:
|
||||
pack.reservation_ids.write({'partner_id': pack.partner_id.id})
|
||||
|
||||
@api.constrains('reservation_ids')
|
||||
def check_reservation_partner(self):
|
||||
""" Check reservation partner """
|
||||
for pack in self:
|
||||
if len(pack.reservation_ids.mapped('partner_id')) > 1:
|
||||
raise ValidationError(_('Pack partner should be the same for '
|
||||
'all reservations'))
|
29
golem_resource_pack/models/golem_resource_reservation.py
Normal file
29
golem_resource_pack/models/golem_resource_reservation.py
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" GOLEM Resource Reservation """
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class GolemResourceReservation(models.Model):
|
||||
""" GOLEM Resource Reservation Model """
|
||||
_inherit = 'golem.resource.reservation'
|
||||
|
||||
pack_id = fields.Many2one('golem.resource.pack', 'Reservation Pack',
|
||||
index=True)
|
3
golem_resource_pack/security/ir.model.access.csv
Normal file
3
golem_resource_pack/security/ir.model.access.csv
Normal file
@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_golem_resource_pack_user,Access GOLEM Resource Pack User,model_golem_resource_pack,golem_base.group_golem_user,1,1,1,0
|
||||
access_golem_resource_pack_manager,Access GOLEM Resource Pack Manager,model_golem_resource_pack,golem_base.group_golem_manager,1,1,1,1
|
|
19
golem_resource_pack/tests/__init__.py
Normal file
19
golem_resource_pack/tests/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import test_golem_resource_pack
|
145
golem_resource_pack/tests/test_golem_resource_pack.py
Normal file
145
golem_resource_pack/tests/test_golem_resource_pack.py
Normal file
@ -0,0 +1,145 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" GOLEM Resource Pack testing """
|
||||
|
||||
import logging
|
||||
from odoo.tests.common import TransactionCase
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestGolemResourcePack(TransactionCase):
|
||||
""" GOLEM Resource Reservation testing """
|
||||
|
||||
def setUp(self, *args, **kwargs):
|
||||
""" Bootstrap Resource Reservation """
|
||||
super(TestGolemResourcePack, self).setUp(*args, **kwargs)
|
||||
|
||||
self.resource = self.env['golem.resource'].create({
|
||||
'name': 'Resource',
|
||||
'avaibility_start': '2018-01-01',
|
||||
'avaibility_stop': '2020-01-01',
|
||||
'availibility_24_7': True
|
||||
})
|
||||
self.resource_val = self.env['golem.resource'].create({
|
||||
'name': 'Resource to validate',
|
||||
'avaibility_start': '2018-01-01',
|
||||
'avaibility_stop': '2020-01-01',
|
||||
'validation_required': True,
|
||||
'availibility_24_7': True
|
||||
})
|
||||
|
||||
self.partner = self.env['res.partner'].create({'firstname': 'John',
|
||||
'lastname': 'DOE',
|
||||
'is_company': False})
|
||||
|
||||
reservation_obj = self.env['golem.resource.reservation']
|
||||
self.reservation_1 = reservation_obj.create({
|
||||
'resource_id': self.resource.id,
|
||||
'date_start': '2018-02-05 11:00:00',
|
||||
'date_stop': '2018-02-05 12:00:00',
|
||||
'partner_id': self.partner.id
|
||||
})
|
||||
self.reservation_2 = reservation_obj.create({
|
||||
'resource_id': self.resource.id,
|
||||
'date_start': '2018-02-06 11:00:00',
|
||||
'date_stop': '2018-02-06 12:00:00',
|
||||
'partner_id': self.partner.id
|
||||
})
|
||||
self.reservation_3 = reservation_obj.create({
|
||||
'resource_id': self.resource_val.id,
|
||||
'date_start': '2018-02-05 11:00:00', # is monday
|
||||
'date_stop': '2018-02-05 12:00:00',
|
||||
'partner_id': self.partner.id
|
||||
})
|
||||
self.pack_obj = self.env['golem.resource.pack']
|
||||
self.pack_data = {
|
||||
'name': 'Pack Test',
|
||||
'partner_id': self.partner.id
|
||||
}
|
||||
|
||||
|
||||
def test_pack_basic(self):
|
||||
""" Test pack bases """
|
||||
pack = self.pack_obj.create(self.pack_data)
|
||||
self.assertFalse(pack.reservation_ids)
|
||||
self.assertFalse(self.reservation_1.pack_id)
|
||||
pack.reservation_ids = [(4, self.reservation_1.id, 0),
|
||||
(4, self.reservation_2.id, 0)]
|
||||
self.assertEqual(pack.reservation_ids[0].state, "draft")
|
||||
self.assertEqual(self.reservation_1.pack_id.id, pack.id)
|
||||
self.assertEqual(pack.state, "draft")
|
||||
self.assertEqual(pack.reservation_count, 2)
|
||||
#confirm pack ==> all validated
|
||||
pack.state_confirm()#no validation required
|
||||
self.assertEqual(pack.reservation_ids[0].state, "validated")
|
||||
self.assertEqual(pack.state, "validated")
|
||||
#pack draft ==> all draft
|
||||
pack.state_draft()
|
||||
self.assertEqual(pack.reservation_ids[0].state, "draft")
|
||||
self.assertEqual(pack.state, "draft")
|
||||
# confirm pack and draft reservation ==> pack draft
|
||||
pack.state_confirm()
|
||||
pack.reservation_ids[0].state_draft()
|
||||
self.assertEqual(pack.reservation_ids[0].state, "draft")
|
||||
self.assertEqual(pack.state, "draft")
|
||||
#confirm reservation ==> pack validated
|
||||
pack.reservation_ids[0].state_confirm()
|
||||
self.assertEqual(pack.reservation_ids[0].state, "validated")
|
||||
self.assertEqual(pack.state, "validated")
|
||||
pack.reservation_ids = [(5, 0, 0)]
|
||||
self.assertFalse(pack.reservation_ids)
|
||||
self.assertEqual(pack.reservation_count, 0)
|
||||
|
||||
|
||||
def test_pack_validation(self):
|
||||
""" Test pack validation """
|
||||
pack = self.pack_obj.create(self.pack_data)
|
||||
self.assertFalse(pack.reservation_ids)
|
||||
self.assertFalse(self.reservation_1.pack_id)
|
||||
pack.reservation_ids = [(4, self.reservation_1.id, 0),
|
||||
(4, self.reservation_3.id, 0)]
|
||||
self.assertEqual(pack.reservation_ids[0].state, "draft")
|
||||
self.assertEqual(self.reservation_1.pack_id.id, pack.id)
|
||||
self.assertEqual(pack.state, "draft")
|
||||
pack.state_confirm()#validation required
|
||||
self.assertEqual(pack.state, "confirmed")
|
||||
pack.state_validated()
|
||||
self.assertEqual(pack.state, "validated")
|
||||
self.assertEqual(pack.reservation_ids[0].state, "validated")
|
||||
self.assertEqual(pack.reservation_ids[1].state, "validated")
|
||||
|
||||
def test_pack_rejection(self):
|
||||
""" test pack rejection """
|
||||
pack = self.pack_obj.create(self.pack_data)
|
||||
self.assertFalse(pack.reservation_ids)
|
||||
self.assertFalse(self.reservation_1.pack_id)
|
||||
pack.reservation_ids = [(4, self.reservation_1.id, 0),
|
||||
(4, self.reservation_3.id, 0)]
|
||||
self.assertEqual(pack.reservation_ids[0].state, "draft")
|
||||
self.assertEqual(self.reservation_1.pack_id.id, pack.id)
|
||||
self.assertEqual(pack.state, "draft")
|
||||
pack.state_confirm()#validation required
|
||||
rej_wizard = self.env['golem.pack.rejection.wizard'].create({
|
||||
'pack_id': pack.id,
|
||||
'reason' : 'reason1'
|
||||
})
|
||||
rej_wizard.reject()
|
||||
self.assertEqual(pack.state, "rejected")
|
||||
self.assertEqual(self.reservation_3.state, "rejected")
|
||||
self.assertEqual(pack.rejection_reason, 'reason1')
|
90
golem_resource_pack/views/golem_resource_pack_views.xml
Normal file
90
golem_resource_pack/views/golem_resource_pack_views.xml
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- Trees -->
|
||||
<record model="ir.ui.view" id="golem_resource_pack_view_tree">
|
||||
<field name="name">GOLEM Resource Pack Tree</field>
|
||||
<field name="model">golem.resource.pack</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree colors="black: state=='draft'; blue: state=='validated'; green : state=='validated'; grey: state=='canceled'; orange: state=='rejected'">
|
||||
<field name="name" />
|
||||
<field name="partner_id" />
|
||||
<field name="state" />
|
||||
<field name="reservation_count" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Forms -->
|
||||
<record model="ir.ui.view" id="golem_resource_pack_view_form">
|
||||
<field name="name">GOLEM Resource Pack Form</field>
|
||||
<field name="model">golem.resource.pack</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
<button name="state_confirm" type="object" string="Confirm" class="oe_highlight"
|
||||
attrs="{'invisible': ['|', ('state', 'not in', 'draft'), ('id', '=', False)]}" />
|
||||
<button name="state_canceled" type="object"
|
||||
string="Cancel" states="confirmed,validated" />
|
||||
<button name="state_draft" type="object" string="Set to draft"
|
||||
states="canceled,confirmed,validated,rejected" />
|
||||
<button name="state_validated" type="object" string="Validate"
|
||||
states="confirmed" class="oe_highlight"
|
||||
groups="golem_base.group_golem_manager" />
|
||||
<button name="state_rejected" type="object" string="Reject"
|
||||
states="confirmed" class="oe_highlight"
|
||||
groups="golem_base.group_golem_manager" />
|
||||
<field name="state" widget="statusbar" />
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group name="general" string="Pack" colspan="2">
|
||||
<field name="id" invisible="1"/>
|
||||
<field name="user_id" />
|
||||
<field name="partner_id" />
|
||||
<field name="note" />
|
||||
<field name="rejection_reason"
|
||||
attrs="{'invisible': [('state', '!=', 'rejected')]}"/>
|
||||
</group>
|
||||
<group colspan="2" name="reservations">
|
||||
<field name="reservation_ids" widget="many2many"
|
||||
context="{'default_partner_id' : partner_id, 'default_pack_id': active_id, 'search_default_state_draft': 1, 'search_default_partner_id': partner_id}" />
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers" />
|
||||
<field name="message_ids" widget="mail_thread" />
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Actions -->
|
||||
<act_window id="golem_resource_pack_action" name="Reservation Pack"
|
||||
res_model="golem.resource.pack" view_mode="tree,form" />
|
||||
|
||||
<!-- Menus -->
|
||||
<menuitem id="golem_resource_packs_menu" name="Reservation Packs"
|
||||
parent="golem_resource.golem_resource_menu" action="golem_resource_pack_action"
|
||||
sequence="20" />
|
||||
|
||||
</data>
|
||||
</odoo>
|
19
golem_resource_pack/wizard/__init__.py
Normal file
19
golem_resource_pack/wizard/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import golem_pack_rejection
|
37
golem_resource_pack/wizard/golem_pack_rejection.py
Normal file
37
golem_resource_pack/wizard/golem_pack_rejection.py
Normal file
@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" GOLEM Resources Pack management """
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
class GolemReservationRejectionWizard(models.TransientModel):
|
||||
"""GOLEM Resource wizard : refusal reason for a pack """
|
||||
_name = "golem.pack.rejection.wizard"
|
||||
|
||||
pack_id = fields.Many2one('golem.resource.pack', required=True)
|
||||
reason = fields.Text(required=True)
|
||||
|
||||
@api.multi
|
||||
def reject(self):
|
||||
""" Sets pack status to rejected and add reason """
|
||||
self.ensure_one()
|
||||
rdata = {'state': 'rejected',
|
||||
'rejection_reason': self[0].reason}
|
||||
self[0].pack_id.reservation_ids.filtered(lambda r: r.state == 'confirmed').write(rdata)
|
||||
self[0].pack_id.rejection_reason = self[0].reason
|
43
golem_resource_pack/wizard/golem_pack_rejection_views.xml
Normal file
43
golem_resource_pack/wizard/golem_pack_rejection_views.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<!-- Forms -->
|
||||
<record model="ir.ui.view" id="golem_pack_rejection_wizard_view_form">
|
||||
<field name="name">GOLEM Pack Rejection Wizard Form</field>
|
||||
<field name="model">golem.pack.rejection.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Rejection reason">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="pack_id" readonly="1" />
|
||||
<field name="reason" />
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="reject" string="Reject" type="object"
|
||||
class="oe_highlight" />
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
19
golem_resource_pack_account/__init__.py
Normal file
19
golem_resource_pack_account/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import models
|
32
golem_resource_pack_account/__manifest__.py
Normal file
32
golem_resource_pack_account/__manifest__.py
Normal file
@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
{
|
||||
'name': 'GOLEM resources pack invoicing',
|
||||
'summary': 'GOLEM resources pack invoicing',
|
||||
'description': ''' GOLEM resources pack invoicing ''',
|
||||
'version': '10.0.0.1.0',
|
||||
'category': 'GOLEM',
|
||||
'author': 'Youssef El Ouahby, Fabien Bourgeois',
|
||||
'license': 'AGPL-3',
|
||||
'application': False,
|
||||
'installable': True,
|
||||
'auto_install': True,
|
||||
'depends': ['golem_resource_pack', 'golem_resource_account'],
|
||||
'data': ['views/golem_resource_pack_views.xml']
|
||||
}
|
19
golem_resource_pack_account/models/__init__.py
Normal file
19
golem_resource_pack_account/models/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from . import golem_resource_pack
|
84
golem_resource_pack_account/models/golem_resource_pack.py
Normal file
84
golem_resource_pack_account/models/golem_resource_pack.py
Normal file
@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" GOLEM Resource Pack Invoicing """
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class GolemResourcePack(models.Model):
|
||||
""" GOLEM Resource Pack invoice extention """
|
||||
_inherit = 'golem.resource.pack'
|
||||
|
||||
invoice_id = fields.Many2one('account.invoice', string="Invoice")
|
||||
|
||||
invoice_state = fields.Selection(related='invoice_id.state', store=True,
|
||||
copy=False)
|
||||
invoice_amount_total = fields.Monetary(related='invoice_id.amount_total')
|
||||
currency_id = fields.Many2one(related='invoice_id.currency_id')
|
||||
are_products_set = fields.Boolean(compute="_compute_are_products_set")
|
||||
|
||||
@api.depends('reservation_ids.resource_product_id')
|
||||
def _compute_are_products_set(self):
|
||||
""" Computes are_products_set """
|
||||
for pack in self:
|
||||
pack.are_products_set = all([r.resource_product_id.id for r in pack.reservation_ids])
|
||||
|
||||
@api.multi
|
||||
def chek_pack_to_invoice(self):
|
||||
""" Cheks pack before invoicing """
|
||||
for pack in self:
|
||||
if pack.state != 'validated':
|
||||
raise ValidationError(_('The current pack is not validated, please validate '
|
||||
'it before creating invoice'))
|
||||
elif not pack.are_products_set:
|
||||
raise ValidationError(_('You can not create an invoice for a pack without '
|
||||
'linked product on every resource reserved.'))
|
||||
elif pack.invoice_id.id:
|
||||
raise ValidationError(_('You can not create an invoice as there '
|
||||
'is already one.'))
|
||||
|
||||
@api.multi
|
||||
def create_invoice(self):
|
||||
""" Invoice creation """
|
||||
self.chek_pack_to_invoice()
|
||||
for pack in self:
|
||||
pack.reservation_ids.check_before_invoicing()
|
||||
partner_id = pack.partner_id
|
||||
invoice_id = self.env['account.invoice'].create({
|
||||
'origin': pack.name,
|
||||
'type': 'out_invoice',
|
||||
'reference': False,
|
||||
'account_id': partner_id.property_account_receivable_id.id,
|
||||
'partner_id': partner_id.id
|
||||
})
|
||||
pack.invoice_id = invoice_id.id
|
||||
pack.reservation_ids.create_invoice_line(invoice_id)
|
||||
|
||||
@api.multi
|
||||
def show_invoice(self):
|
||||
""" Redirects to linked invoice """
|
||||
self.ensure_one()
|
||||
pack = self[0]
|
||||
if pack.invoice_id:
|
||||
return {'type': 'ir.actions.act_window',
|
||||
'res_model': 'account.invoice',
|
||||
'res_id': pack.invoice_id.id,
|
||||
'view_mode': 'form',
|
||||
'view_id': self.env.ref('account.invoice_form').id}
|
18
golem_resource_pack_account/tests/__init__.py
Normal file
18
golem_resource_pack_account/tests/__init__.py
Normal file
@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
from . import test_golem_pack_invoice
|
115
golem_resource_pack_account/tests/test_golem_pack_invoice.py
Normal file
115
golem_resource_pack_account/tests/test_golem_pack_invoice.py
Normal file
@ -0,0 +1,115 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
# Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
""" GOLEM Resource Reservation testing """
|
||||
|
||||
import logging
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.exceptions import ValidationError
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestGolemResourcePack(TransactionCase):
|
||||
""" GOLEM Resource Pack testing """
|
||||
|
||||
def setUp(self, *args, **kwargs):
|
||||
""" Bootstrap Resource Reservation """
|
||||
super(TestGolemResourcePack, self).setUp(*args, **kwargs)
|
||||
# set product
|
||||
self.product = self.env['product.template'].create({
|
||||
'name': 'Product',
|
||||
'categ_id': self.env.ref('product.product_category_all').id,
|
||||
'list_price': 7.0,
|
||||
'type': 'service',
|
||||
'uom_id': self.env.ref('product.product_uom_hour').id,
|
||||
'uom_po_id': self.env.ref('product.product_uom_hour').id,
|
||||
'property_account_income_id': self.env.ref('l10n_fr.pcg_706').id
|
||||
})
|
||||
#set resources
|
||||
self.resource_1 = self.env['golem.resource'].create({
|
||||
'name': 'Resource1',
|
||||
'product_tmpl_id': self.product.id,
|
||||
'avaibility_start': '2018-01-01',
|
||||
'avaibility_stop': '2020-01-01',
|
||||
'availibility_24_7': True
|
||||
})
|
||||
self.resource_2 = self.env['golem.resource'].create({
|
||||
'name': 'Resource2',
|
||||
'avaibility_start': '2018-01-01',
|
||||
'avaibility_stop': '2020-01-01',
|
||||
'availibility_24_7': True
|
||||
})
|
||||
|
||||
#set partners
|
||||
self.partner_1 = self.env['res.partner'].create({'firstname': 'John',
|
||||
'lastname': 'DOE',
|
||||
'is_company': False})
|
||||
self.partner_2 = self.env['res.partner'].create({'firstname': 'John2',
|
||||
'lastname': 'DOE2',
|
||||
'is_company': False})
|
||||
|
||||
# set reservations
|
||||
self.reservation_1 = self.env['golem.resource.reservation'].create({
|
||||
'resource_id': self.resource_1.id,
|
||||
'date_start': '2018-02-05 11:00:00',
|
||||
'date_stop': '2018-02-05 12:00:00',
|
||||
'partner_id': self.partner_1.id
|
||||
})
|
||||
self.reservation_2 = self.env['golem.resource.reservation'].create({
|
||||
'resource_id': self.resource_1.id,
|
||||
'date_start': '2018-02-06 11:00:00',
|
||||
'date_stop': '2018-02-06 12:00:00',
|
||||
'partner_id': self.partner_1.id
|
||||
})
|
||||
|
||||
#set pack env
|
||||
self.pack_obj = self.env['golem.resource.pack']
|
||||
self.pack_data = {
|
||||
'name': 'Pack test',
|
||||
'partner_id': self.partner_1.id,
|
||||
'reservation_ids': [(4, self.reservation_1.id, 0),
|
||||
(4, self.reservation_2.id, 0)]}
|
||||
|
||||
|
||||
def test_pack_invoice_basic(self):
|
||||
""" Test pack invoice basic """
|
||||
pack = self.pack_obj.create(self.pack_data)
|
||||
pack.state_confirm()
|
||||
pack.create_invoice()
|
||||
self.assertTrue(pack.invoice_id.id)
|
||||
self.assertEqual(pack.invoice_state, 'draft')
|
||||
|
||||
def test_unallowed_pack_invoice(self):
|
||||
""" Test unallowed pack invoice cases """
|
||||
pack = self.pack_obj.create(self.pack_data)
|
||||
with self.assertRaises(ValidationError) as err:
|
||||
pack.create_invoice()
|
||||
self.assertIn(u'current pack is not validated', err.exception.args[0])
|
||||
self.reservation_2.write({'resource_id': self.resource_2.id})#no product linked
|
||||
pack.state_confirm()
|
||||
with self.assertRaises(ValidationError) as err:
|
||||
pack.create_invoice()
|
||||
self.assertIn(u'linked product on every resource', err.exception.args[0])
|
||||
pack.state_draft()
|
||||
self.reservation_2.write({'resource_id': self.resource_1.id})# with product linked
|
||||
pack.state_confirm()
|
||||
pack.create_invoice()
|
||||
self.assertTrue(pack.invoice_id.id)
|
||||
with self.assertRaises(ValidationError) as err:
|
||||
pack.create_invoice()
|
||||
self.assertIn(u'can not create an invoice as there', err.exception.args[0])
|
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Youssef El Ouahby <youssef@yaltik.com>
|
||||
Copyright 2018 Fabien Bourgeois <fabien@yaltik.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<!-- Tree -->
|
||||
<record model="ir.ui.view" id="golem_resource_pack_inherit_account_tree">
|
||||
<field name="name">GOLEM Resource Pack Account extention Tree</field>
|
||||
<field name="model">golem.resource.pack</field>
|
||||
<field name="inherit_id" ref="golem_resource_pack.golem_resource_pack_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="reservation_count" position="after">
|
||||
<field name="invoice_state" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Forms -->
|
||||
<record model="ir.ui.view" id="golem_resource_pack_inherit_account_form">
|
||||
<field name="name">GOLEM Resource Pack Account extention Form</field>
|
||||
<field name="model">golem.resource.pack</field>
|
||||
<field name="inherit_id" ref="golem_resource_pack.golem_resource_pack_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="state_rejected" position="after">
|
||||
<button name="create_invoice" type="object" string="Create Invoice" class="oe_highlight"
|
||||
attrs="{'invisible': ['|', ('state', '!=', 'validated'), '|', ('invoice_id', '!=', False), ('are_products_set', '=', False)]}" />
|
||||
<button name="show_invoice" type="object" string="Show invoice" class="oe_highlight"
|
||||
attrs="{'invisible': [('invoice_id', '=', False)]}" />
|
||||
</button>
|
||||
<group name="general" position="after">
|
||||
<group name="invoicing" string="Invoicing"
|
||||
attrs="{'invisible': [('invoice_id', '=', False)]}">
|
||||
<field name="are_products_set" invisible="1"/>
|
||||
<field name="invoice_id" />
|
||||
<field name="invoice_state" />
|
||||
<field name="invoice_amount_total" />
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
Loading…
Reference in New Issue
Block a user