Browse Source

[MIGR] migration of analytic_hours_block to OpenERP version 7.0

pull/2/head
Joel Grand-Guillaume 12 years ago
parent
commit
0eba6839fc
  1. 30
      analytic_hours_block/__init__.py
  2. 80
      analytic_hours_block/__openerp__.py
  3. 364
      analytic_hours_block/hours_block.py
  4. 10
      analytic_hours_block/hours_block_menu.xml
  5. 97
      analytic_hours_block/hours_block_view.xml
  6. 32
      analytic_hours_block/report/__init__.py
  7. 60
      analytic_hours_block/report/hours_block.py
  8. 34
      analytic_hours_block/report/hours_block.rml

30
analytic_hours_block/__init__.py

@ -1,27 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# @author Renaville Vincent, ported by Joel Grand-Guillaume
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
# Author: Vincent Renaville, ported by Joel Grand-Guillaume
# Copyright 2010-2012 Camptocamp SA
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 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 General Public License for more details.
# 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 General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# 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/>.
#
##############################################################################
import hours_block

80
analytic_hours_block/__openerp__.py

@ -1,60 +1,54 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com)
# All Right Reserved
# Author: Vincent Renaville, ported by Joel Grand-Guillaume
# Copyright 2010-2012 Camptocamp SA
#
# Author : Joël Grand-Guillaume (Camptocamp)
# 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.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
# 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.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# 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" : "Project Hours Blocks Management",
"description" : """
"name": "Project Hours Blocks Management",
"description": """
Project Hours Blocks Management
===============================
This module allows you to handle hours blocks, to follow for example the user support contracts.
This means, you sell a product of type "hours block" then you input the spent hours on the hours block and
This module allows you to handle hours blocks,
to follow for example the user support contracts.
This means, you sell a product of type "hours block"
then you input the spent hours on the hours block and
you can track and follow how much has been used.
""",
"version" : "1.2",
"author" : "Camptocamp",
"category" : "Generic Modules/Projects & Services",
"version": "1.3",
"author": "Camptocamp",
"license": 'AGPL-3',
"category": "Generic Modules/Projects & Services",
"website": "http://www.camptocamp.com",
"depends" : [
"account",
"hr_timesheet_invoice",
"analytic"
],
"init_xml" : [],
"update_xml" : [
"hours_block_view.xml",
"hours_block_menu.xml",
"report.xml",
"security/hours_block_security.xml",
"security/ir.model.access.csv",
],
"depends": [
"account",
"hr_timesheet_invoice",
"analytic"
],
"data": [
"hours_block_view.xml",
"hours_block_menu.xml",
"report.xml",
"security/hours_block_security.xml",
"security/ir.model.access.csv",
],
"active": False,
"installable": False
"installable": True
}

364
analytic_hours_block/hours_block.py

@ -1,120 +1,93 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2010 Camptocamp SA
# All Rights Reserved
# Author: Vincent Renaville, ported by Joel Grand-Guillaume
# Copyright 2010-2012 Camptocamp SA
#
# Author : Vincent Renaville, ported by Joel Grand-Guillaume
# 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.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
# 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.
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# 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/>.
#
##############################################################################
import time
import string
from osv import osv, fields
import netsvc
from openerp.osv import orm, fields
############################################################################
## Add hours blocks on invoice
############################################################################
class AccountHoursBlock(osv.osv):
class AccountHoursBlock(orm.Model):
_name = "account.hours.block"
def _get_last_action(self, cr, uid, ids, name, arg, context=None):
"""TODO"""
context = context or {}
""" Return the last analytic line date for an invoice"""
res = {}
for block in self.browse(cr, uid, ids):
for block in self.browse(cr, uid, ids, context=context):
cr.execute("SELECT max(al.date) FROM account_analytic_line AS al"
" WHERE al.invoice_id = %s", (block.invoice_id.id,))
fetch_res = cr.fetchone()
if fetch_res:
date = fetch_res[0]
else:
date = False
res[block.id] = date
res[block.id] = fetch_res[0] if fetch_res else False
return res
def _compute_hours(self, cr, uid, ids, fields, args, context=None):
"""Return a dict of [id][fields]"""
context = context or {}
if not isinstance(ids, list):
ids=[ids]
if isinstance(ids, (int, long)):
ids = [ids]
result = {}
aal_obj = self.pool.get('account.analytic.line')
for block in self.browse(cr,uid,ids):
result[block.id] = {'amount_hours_block' : 0.0,
'amount_hours_block_done' : 0.0,
'amount_hours_block_delta' : 0.0}
for block in self.browse(cr, uid, ids, context=context):
result[block.id] = {'amount_hours_block': 0.0,
'amount_hours_block_done': 0.0}
# Compute hours bought
for line in block.invoice_id.invoice_line:
hours_bought = 0.0
if line.product_id:
## We will now calculate the product_quantity
# We will now calculate the product_quantity
factor = line.uos_id.factor
if factor == 0.0:
factor = 1.0
amount = line.quantity
hours_bought += (amount / factor)
result[block.id]['amount_hours_block'] += hours_bought
# Compute hours spent
hours_used = 0.0
# Get ids of analytic line generated from timesheet associated to current block
# Get ids of analytic line generated from
# timesheet associated to the current block
cr.execute("SELECT al.id "
" FROM account_analytic_line AS al,account_analytic_journal AS aj"
" WHERE aj.id = al.journal_id AND"
" aj.type='general' AND"
" al.invoice_id = %s", (block.invoice_id.id,))
res2 = cr.fetchall()
if res2:
ids2 = [x[0] for x in res2]
else:
ids2 = []
for line in aal_obj.browse(cr, uid, ids2, context):
if line.product_uom_id:
"FROM account_analytic_line AS al, "
" account_analytic_journal AS aj "
"WHERE aj.id = al.journal_id "
"AND aj.type = 'general' "
"AND al.invoice_id = %s", (block.invoice_id.id,))
res_line_ids = cr.fetchall()
line_ids = [l[0] for l in res_line_ids] if res_line_ids else []
for line in aal_obj.browse(cr, uid, line_ids, context=context):
factor = 1.0
if line.product_uom_id and line.product_uom_id.factor != 0.0:
factor = line.product_uom_id.factor
if factor == 0.0:
factor = 1.0
else:
factor = 1.0
factor_invoicing = 1.0
if line.to_invoice and line.to_invoice.factor != 0.0:
factor_invoicing = 1.0 - line.to_invoice.factor / 100
factor_invoicing = 1.0 - line.to_invoice.factor / 100
hours_used += ((line.unit_amount / factor) * factor_invoicing)
result[block.id]['amount_hours_block_done'] = hours_used
return result
def _compute_amount(self, cr, uid, ids, fields, args, context):
def _compute_amount(self, cr, uid, ids, fields, args, context=None):
if context is None:
context = {}
result = {}
aal_obj = self.pool.get('account.analytic.line')
pricelist_obj = self.pool.get('product.pricelist')
for block in self.browse(cr,uid,ids):
result[block.id] = {'amount_hours_block' : 0.0,
'amount_hours_block_done' : 0.0,
'amount_hours_block_delta' : 0.0}
for block in self.browse(cr, uid, ids, context=context):
result[block.id] = {'amount_hours_block': 0.0,
'amount_hours_block_done': 0.0}
# Compute amount bought
for line in block.invoice_id.invoice_line:
@ -135,95 +108,218 @@ class AccountHoursBlock(osv.osv):
" WHERE aj.id = al.journal_id"
" AND aj.type='general'"
" AND al.invoice_id = %s", (block.invoice_id.id,))
res2 = cr.fetchall()
if res2:
ids2 = [x[0] for x in res2]
else:
ids2 = []
res_line_ids = cr.fetchall()
line_ids = [l[0] for l in res_line_ids] if res_line_ids else []
total_amount = 0.0
for line in aal_obj.browse(cr, uid, ids2, context):
for line in aal_obj.browse(cr, uid, line_ids, context=context):
factor_invoicing = 1.0
if line.to_invoice and line.to_invoice.factor != 0.0:
factor_invoicing = 1.0 - line.to_invoice.factor / 100
ctx = {'uom': line.product_uom_id.id}
amount = pricelist_obj.price_get(cr, uid,
[line.account_id.pricelist_id.id],
line.product_id.id,
line.unit_amount or 1.0,
line.account_id.partner_id.id or False,
ctx)[line.account_id.pricelist_id.id]
factor_invoicing = 1.0 - line.to_invoice.factor / 100
ctx = dict(context, uom=line.product_uom_id.id)
amount = pricelist_obj.price_get(
cr, uid,
[line.account_id.pricelist_id.id],
line.product_id.id,
line.unit_amount or 1.0,
line.account_id.partner_id.id or False,
ctx)[line.account_id.pricelist_id.id]
total_amount += amount * line.unit_amount * factor_invoicing
result[block.id]['amount_hours_block_done'] += total_amount
return result
def _compute(self, cr, uid, ids, fields, args, context):
def _compute(self, cr, uid, ids, fields, args, context=None):
result = {}
block_per_types = {}
for block in self.browse(cr, uid, ids, context=context):
if not block.type in block_per_types.keys():
block_per_types[block.type] = []
block_per_types[block.type].append(block.id)
block_per_types.setdefault(block.type, []).append(block.id)
for block_type in block_per_types:
if block_type:
func = getattr(self, "_compute_%s" % (block_type,))
result.update(func(cr, uid, ids, fields, args, context))
func = getattr(self, "_compute_%s" % block_type)
result.update(func(cr, uid, ids, fields, args, context=context))
for block in result:
result[block]['amount_hours_block_delta'] = \
result[block]['amount_hours_block'] - result[block]['amount_hours_block_done']
result[block]['amount_hours_block'] - \
result[block]['amount_hours_block_done']
return result
def _get_analytic_line(self, cr, uid, ids, context=None):
invoice_ids = []
an_lines_obj = self.pool.get('account.analytic.line')
block_obj = self.pool.get('account.hours.block')
for line in an_lines_obj.browse(cr, uid, ids, context=context):
if line.invoice_id:
invoice_ids.append(line.invoice_id.id)
return block_obj.search(
cr, uid, [('invoice_id', 'in', invoice_ids)], context=context)
def _get_invoice(self, cr, uid, ids, context=None):
block_ids = set()
inv_obj = self.pool.get('account.invoice')
for invoice in inv_obj.browse(cr, uid, ids, context=context):
block_ids.update([inv.id for inv in invoice.account_hours_block_ids])
return list(block_ids)
_recompute_triggers = {
'account.hours.block': (lambda self, cr, uid, ids, c=None:
ids, ['invoice_id', 'type'], 10),
'account.invoice': (_get_invoice, ['analytic_line_ids'], 10),
'account.analytic.line': (
_get_analytic_line,
['product_uom_id', 'unit_amount', 'to_invoice', 'invoice_id'],
10),
}
_columns = {
'amount_hours_block': fields.function(_compute, method=True, type='float', string='Quantity /Amount bought', store=True,
multi='amount_hours_block_delta',
help="Amount bought by the customer. This amount is expressed in the base UoM (factor=1.0)"),
'amount_hours_block_done': fields.function(_compute, method=True, type='float', string='Quantity / Amount used', store=True,
multi='amount_hours_block_delta',
help="Amount done by the staff. This amount is expressed in the base UoM (factor=1.0)"),
'amount_hours_block_delta': fields.function(_compute, method=True, type='float', string='Difference', store=True,
multi='amount_hours_block_delta',
help="Difference between bought and used. This amount is expressed in the base UoM (factor=1.0)"),
'last_action_date': fields.function(_get_last_action, method=True, type='date', string='Last action date',
help="Date of the last analytic line linked to the invoice related to this block hours."),
'amount_hours_block': fields.function(
_compute,
type='float',
string='Quantity / Amount bought',
store=_recompute_triggers,
multi='amount_hours_block_delta',
help="Amount bought by the customer. "
"This amount is expressed in the base Unit of Measure "
"(factor=1.0)"),
'amount_hours_block_done': fields.function(
_compute,
type='float',
string='Quantity / Amount used',
store=_recompute_triggers,
multi='amount_hours_block_delta',
help="Amount done by the staff. "
"This amount is expressed in the base Unit of Measure "
"(factor=1.0)"),
'amount_hours_block_delta': fields.function(
_compute,
type='float',
string='Difference',
store=_recompute_triggers,
multi='amount_hours_block_delta',
help="Difference between bought and used. "
"This amount is expressed in the base Unit of Measure "
"(factor=1.0)"),
'last_action_date': fields.function(
_get_last_action,
type='date',
string='Last action date',
help="Date of the last analytic line linked to the invoice "
"related to this block hours."),
'close_date': fields.date('Closed Date'),
'invoice_id': fields.many2one('account.invoice', 'Invoice', ondelete='cascade', required=True),
'type': fields.selection([('hours','Hours'), ('amount','Amount')], 'Type of Block',
required=True, help="Choose if you want a time or amount base block."),
'invoice_id': fields.many2one(
'account.invoice',
'Invoice',
ondelete='cascade',
required=True),
'type': fields.selection(
[('hours', 'Hours'),
('amount', 'Amount')],
string='Type of Block',
required=True,
help="The block is based on the quantity of hours "
"or on the amount."),
# Invoices related infos
'date_invoice': fields.related('invoice_id', 'date_invoice', type="date", string="Invoice Date", store=True, readonly=True),
'user_id': fields.related('invoice_id', 'user_id', type="many2one", relation="res.users", string="Salesman", store=True, readonly=True),
'partner_id': fields.related('invoice_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store=True, readonly=True),
'name': fields.related('invoice_id', 'name', type="char",size=64, string="Description", store=True,readonly=True),
'number': fields.related('invoice_id', 'number', type="char",size=64, string="Number", store=True,readonly=True),
'journal_id': fields.related('invoice_id', 'journal_id', type="many2one", relation="account.journal", string="Journal", store=True,readonly=True),
'period_id': fields.related('invoice_id', 'period_id', type="many2one", relation="account.period", string="Period", store=True,readonly=True),
'company_id': fields.related('invoice_id', 'company_id', type="many2one", relation="res.company", string="Company", store=True,readonly=True),
'currency_id': fields.related('invoice_id', 'currency_id', type="many2one", relation="res.currency", string="Currency", store=True,readonly=True),
'residual': fields.related('invoice_id', 'residual', type="float", string="Residual", store=True,readonly=True),
'amount_total': fields.related('invoice_id', 'amount_total', type="float", string="Total", store=True,readonly=True),
'state':fields.related('invoice_id','state',
type='selection',
selection=[
('draft','Draft'),
('proforma','Pro-forma'),
('proforma2','Pro-forma'),
('open','Open'),
('paid','Paid'),
('cancel','Cancelled')
],
string='State', readonly=True, store=True),
'date_invoice': fields.related(
'invoice_id', 'date_invoice',
type="date",
string="Invoice Date",
store=True,
readonly=True),
'user_id': fields.related(
'invoice_id', 'user_id',
type="many2one",
relation="res.users",
string="Salesman",
store=True,
readonly=True),
'partner_id': fields.related(
'invoice_id', 'partner_id',
type="many2one",
relation="res.partner",
string="Partner",
store=True,
readonly=True),
'name': fields.related(
'invoice_id', 'name',
type="char",
string="Description",
store=True,
readonly=True),
'number': fields.related(
'invoice_id', 'number',
type="char",
string="Number",
store=True,
readonly=True),
'journal_id': fields.related(
'invoice_id', 'journal_id',
type="many2one",
relation="account.journal",
string="Journal",
store=True,
readonly=True),
'period_id': fields.related(
'invoice_id', 'period_id',
type="many2one",
relation="account.period",
string="Period",
store=True,
readonly=True),
'company_id': fields.related(
'invoice_id', 'company_id',
type="many2one",
relation="res.company",
string="Company",
store=True,
readonly=True),
'currency_id': fields.related(
'invoice_id', 'currency_id',
type="many2one",
relation="res.currency",
string="Currency",
store=True,
readonly=True),
'residual': fields.related(
'invoice_id', 'residual',
type="float",
string="Residual",
store=True,
readonly=True),
'amount_total': fields.related(
'invoice_id', 'amount_total',
type="float",
string="Total",
store=True,
readonly=True),
'state': fields.related(
'invoice_id', 'state',
type='selection',
selection=[
('draft', 'Draft'),
('proforma', 'Pro-forma'),
('proforma2', 'Pro-forma'),
('open', 'Open'),
('paid', 'Paid'),
('cancel', 'Cancelled'),
],
string='State',
readonly=True,
store=True),
}
AccountHoursBlock()
class AccountInvoice(osv.osv):
############################################################################
## Add hours blocks on invoice
############################################################################
class AccountInvoice(orm.Model):
_inherit = 'account.invoice'
_columns = {
'account_hours_block_ids': fields.one2many('account.hours.block', 'invoice_id', 'Hours Block')
'account_hours_block_ids': fields.one2many(
'account.hours.block',
'invoice_id',
string='Hours Block')
}
AccountInvoice()

10
analytic_hours_block/hours_block_menu.xml

@ -2,13 +2,11 @@
<openerp>
<data>
#---------------------------------------------------------------------------------------------------------
# Hours block menu
#---------------------------------------------------------------------------------------------------------
<!--
Hours block menu
-->
<record model="ir.actions.act_window" id="action_all_block_hour">
<field name="name">Hours Block</field>
<field name="name">Hours Blocks</field>
<field name="res_model">account.hours.block</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>

97
analytic_hours_block/hours_block_view.xml

@ -2,13 +2,12 @@
<openerp>
<data>
#---------------------------------------------------------------------
# Hours block search form
#---------------------------------------------------------------------
<!--
Hours block search form
-->
<record id="view_account_invoice_filter" model="ir.ui.view">
<field name="name">account.hours.block.select</field>
<field name="model">account.hours.block</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Search Invoice">
<group col="7" colspan="4">
@ -28,47 +27,58 @@
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
<filter string="Invoice State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
#------------------------------------------------------------------------
# Hours Block View
#------------------------------------------------------------------------
<!--
Hours Block View
-->
<record id="hours_block_invoice_form" model="ir.ui.view">
<field name="name">account.hours.block.form</field>
<field name="model">account.hours.block</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Invoice">
<field name="type" />
<field name="invoice_id" />
<field name="last_action_date" />
<field name="close_date" />
<group col="6" colspan="4">
<separator colspan="6" string="Hours Quantity / Amount"/>
<form string="Hours Blocks" version="7.0">
<sheet>
<h1>
<field name="invoice_id" placeholder="Choose an invoice..."/>
<label for="type" string="Based on:" class="oe_inline"/>
<field name="type" class="oe_inline"/>
</h1>
<group>
<field name="last_action_date" />
<field name="close_date" />
</group>
<group>
<separator colspan="4" string="Hours Quantity / Amount"/>
<field name="amount_hours_block" string="Bought"/>
<field name="amount_hours_block_done" string="Used"/>
<field name="amount_hours_block_delta" string="Difference"/>
</group>
<separator colspan="4" string="Invoice's related information"/>
<field name="date_invoice"/>
<field name="name"/>
<field name="number"/>
<field name="partner_id" groups="base.group_user"/>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
<field name="journal_id" invisible="1"/>
<field name="period_id" invisible="1" groups="account.group_account_user"/>
<group>
<separator colspan="4" string="Invoice's related information"/>
<field name="date_invoice"/>
<field name="name"/>
<field name="number"/>
<field name="partner_id" groups="base.group_user"/>
<field name="user_id"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/>
<field name="currency_id"/>
<newline/>
<field name="residual" sum="Residual Amount"/>
<field name="amount_total" sum="Total Amount"/>
<field name="state"/>
<field name="journal_id" invisible="1"/>
<field name="period_id" invisible="1" groups="account.group_account_user"/>
<field name="currency_id"/>
<newline/>
<field name="residual" sum="Residual Amount"/>
<field name="amount_total" sum="Total Amount"/>
<field name="state"/>
</group>
</sheet>
</form>
</field>
</record>
@ -76,7 +86,6 @@
<record model="ir.ui.view" id="invoice_tree_hour_block">
<field name="name">account.hours.block.tree</field>
<field name="model">account.hours.block</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree colors="blue:state in ('draft');black:state in ('proforma','proforma2','open');gray:state in ('cancel')" string="Invoice">
<field name="date_invoice"/>
@ -102,19 +111,18 @@
</record>
#---------------------------------------------------------------------------------------------------------
# Add related act_window from partner and Hours Block
#---------------------------------------------------------------------------------------------------------
<!--
Add related act_window from partner and Hours Block
-->
<act_window name="All blocks hours"
domain="[('partner_id', '=', active_id)]"
res_model="account.hours.block"
src_model="res.partner"
id="act_block_hour_from_partner"/>
#---------------------------------------------------------------------------------------------------------
# Link to invoice on hours block view
#---------------------------------------------------------------------------------------------------------
<!--
Link to invoice on hours block view
-->
<act_window
domain="[('account_hours_block_ids', '=', active_id)]"
id="act_invoice_from_hours_block"
@ -124,9 +132,9 @@
view_mode="tree,form"
view_type="form"/>
#---------------------------------------------------------------------------------------------------------
# Link to analytic lines on hours block view
#---------------------------------------------------------------------------------------------------------
<!--
Link to analytic lines on hours block view
-->
<act_window
domain="[('invoice_id.account_hours_block_ids', '=', active_id)]"
id="act_analytic_lines_from_hours_block"
@ -136,9 +144,9 @@
view_mode="tree,form"
view_type="form"/>
#---------------------------------------------------------------------------------------------------------
# Link to hours block on invoice view
#---------------------------------------------------------------------------------------------------------
<!--
Link to hours block on invoice view
-->
<act_window
domain="[('invoice_id', '=', active_id)]"
id="act_hours_block_from_invoice"
@ -148,6 +156,5 @@
view_mode="tree,form,calendar,graph"
view_type="form"/>
</data>
</openerp>

32
analytic_hours_block/report/__init__.py

@ -1,27 +1,21 @@
# -*- encoding: utf-8 -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Vincent Renaville, ported by Joel Grand-Guillaume
# Copyright 2010-2012 Camptocamp SA
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
# 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 Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# 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/>.
#
##############################################################################
import hours_block

60
analytic_hours_block/report/hours_block.py

@ -1,59 +1,47 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
# Author: Vincent Renaville, ported by Joel Grand-Guillaume
# Copyright 2010-2012 Camptocamp SA
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
# 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 Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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.
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# 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/>.
#
##############################################################################
import time
from report import report_sxw
#import xml.dom.minidom
#import re
from openerp.report import report_sxw
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
class account_hours_block(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context=None):
super(account_hours_block, self).__init__(cr, uid, name, context)
super(account_hours_block, self).__init__(cr, uid, name, context=context)
self.localcontext.update({
'time': time,
'format_date': self._get_and_change_date_format_for_swiss,
'date_format': DEFAULT_SERVER_DATE_FORMAT,
'analytic_lines': self._get_analytic_lines,
})
self.context = context
def _get_analytic_lines(self, hours_block):
al_pool = self.pool.get('account.analytic.line')
al_ids = al_pool.search(self.cr, self.uid,
[['invoice_id', '=', hours_block.invoice_id.id]],
order='date desc')
res = al_pool.browse(self.cr, self.uid, al_ids)
return res
def _get_and_change_date_format_for_swiss(self, date_to_format):
date_formatted = ''
if date_to_format:
date_formatted = strptime(date_to_format, '%Y-%m-%d').strftime('%d.%m.%Y')
return date_formatted
al_ids = al_pool.search(
self.cr,
self.uid,
[('invoice_id', '=', hours_block.invoice_id.id)],
order='date desc',
context=self.context)
return al_pool.browse(self.cr, self.uid, al_ids, context=self.context)
report_sxw.report_sxw('report.account.hours.block', 'account.hours.block', 'addons/analytic_hours_block/report/hours_block.rml', parser=account_hours_block)

34
analytic_hours_block/report/hours_block.rml

@ -10,7 +10,7 @@
<drawString x="17.7cm" y="28.1cm">Maintenance And Support Summary</drawString>
<setFont name="Helvetica" size="9"/>
<drawString x="1.0cm" y="2cm"> [[ time.strftime("%m-%d-%y %H:%M", time.localtime()) ]]</drawString>
<drawString x="1.0cm" y="2cm"> [[ formatLang(time.strftime(date_format), date=True) ]]</drawString>
<drawString x="17.7cm" y="2cm">Page <pageNumber/></drawString>
<lineMode width="0.7"/>
@ -165,7 +165,7 @@
<blockTable colWidths="258.0,259.0" style="Table1" repeatRows="1">
<tr>
<td>
<para style="P12a">Description :</para>
<para style="P12a">Description: </para>
</td>
<td>
<para style="P2">[[ o.name ]]</para>
@ -173,24 +173,24 @@
</tr>
<tr>
<td>
<para style="P12a">Report Date : </para>
<para style="P12a">Report Date: </para>
</td>
<td>
<para style="P2">[[ time.strftime("%d.%m.%Y", time.localtime()) ]]</para>
<para style="P2">[[ formatLang(time.strftime(date_format), date=True) ]]</para>
</td>
</tr>
<tr>
<td>
<para style="P12a">Invoice Date : </para>
<para style="P12a">Invoice Date: </para>
</td>
<td>
<para style="P2">[[ o.date_invoice and format_date(o.date_invoice) or '' ]]</para>
<para style="P2">[[ o.date_invoice and formatLang(o.date_invoice, date=True) or '' ]]</para>
</td>
</tr>
<tr>
<td>
<para style="P12a">Amount bought : [[ (o.type == 'amount' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Quantity of hours bought : [[ (o.type == 'hours' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Amount bought: [[ (o.type == 'amount' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Quantity of hours bought: [[ (o.type == 'hours' or removeParentNode('para')) and '' ]]</para>
</td>
<td>
<para style="P2">[[ o.amount_hours_block ]]</para>
@ -198,9 +198,8 @@
</tr>
<tr>
<td>
<!-- <para style="P12a">[[ o.type == 'hours' and "Quantity of hours" or "Amount"]] used : </para> -->
<para style="P12a">Amount used : [[ (o.type == 'amount' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Quantity of hours used : [[ (o.type == 'hours' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Amount used: [[ (o.type == 'amount' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Quantity of hours used: [[ (o.type == 'hours' or removeParentNode('para')) and '' ]]</para>
</td>
<td>
<para style="P2">[[ round(o.amount_hours_block_done, 2) ]]</para>
@ -208,9 +207,8 @@
</tr>
<tr>
<td>
<!-- <para style="P12a">Remaining [[ o.type == 'hours' and "hours" or "amount"]] : </para> -->
<para style="P12a">Remaining amount : [[ (o.type == 'amount' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Remaining hours : [[ (o.type == 'hours' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Remaining amount: [[ (o.type == 'amount' or removeParentNode('para')) and '' ]]</para>
<para style="P12a">Remaining hours: [[ (o.type == 'hours' or removeParentNode('para')) and '' ]]</para>
</td>
<td>
@ -241,21 +239,21 @@
</tr>
<tr>
[[ repeatIn(analytic_lines(o),'l') ]]
[[ repeatIn(analytic_lines(o), 'l') ]]
<td>
<para style="P2">[[ l.date and format_date(l.date) or '' ]]</para>
<para style="P2">[[ l.date if formatLang(l.date, date=True) else '' ]]</para>
</td>
<td>
<para style="P2">[[ l.name or '' ]]</para>
</td>
<td>
<para style="P2c">[[ round(l.unit_amount or '0.0', 2) ]]</para>
<para style="P2c">[[ round(l.unit_amount, 2) or '0.0' ]]</para>
</td>
<td>
<para style="P2c">[[ l.to_invoice.customer_name ]]</para>
</td>
<td>
<para style="P2c">[[ round((l.unit_amount and l.to_invoice) and (l.unit_amount - (l.unit_amount * l.to_invoice.factor) / 100 ) or '0.0', 2) ]]</para>
<para style="P2c">[[ round((l.unit_amount and l.to_invoice) and (l.unit_amount - (l.unit_amount * l.to_invoice.factor) / 100 ), 2) or '0.0' ]]</para>
</td>
</tr>
</blockTable>

Loading…
Cancel
Save