Merge lp:~vauxoo/addons-vauxoo/6.1-account_rent_dev_luist into lp:addons-vauxoo/6.1
- 6.1-account_rent_dev_luist
- Merge into 6.1
Proposed by
Luis Torres - http://www.vauxoo.com
Status: | Merged |
---|---|
Merged at revision: | 626 |
Proposed branch: | lp:~vauxoo/addons-vauxoo/6.1-account_rent_dev_luist |
Merge into: | lp:addons-vauxoo/6.1 |
Diff against target: |
973 lines (+815/-20) 9 files modified
account_analytic_analysis_rent/__init__.py (+1/-0) account_analytic_analysis_rent/__openerp__.py (+6/-2) account_analytic_analysis_rent/account_analytic_account_rent.py (+198/-9) account_analytic_analysis_rent/account_analytic_account_rent.xml (+166/-5) account_analytic_analysis_rent/product.py (+41/-2) account_analytic_analysis_rent/product_view.xml (+68/-2) account_analytic_analysis_rent/wizard/__init__.py (+1/-0) account_analytic_analysis_rent/wizard/lines_invoice_create.py (+268/-0) account_analytic_analysis_rent/wizard/lines_invoice_create_view.xml (+66/-0) |
To merge this branch: | bzr merge lp:~vauxoo/addons-vauxoo/6.1-account_rent_dev_luist |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julio Serna-http://www.vauxoo.com | Pending | ||
Review via email:
|
Commit message
Description of the change
Se mergeo la opción de contratos
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'account_analytic_analysis_rent/__init__.py' |
2 | --- account_analytic_analysis_rent/__init__.py 2013-06-03 17:04:02 +0000 |
3 | +++ account_analytic_analysis_rent/__init__.py 2014-02-11 23:05:08 +0000 |
4 | @@ -1,3 +1,4 @@ |
5 | import account_analytic_account_rent |
6 | import product |
7 | import report |
8 | +import wizard |
9 | |
10 | === modified file 'account_analytic_analysis_rent/__openerp__.py' |
11 | --- account_analytic_analysis_rent/__openerp__.py 2013-06-03 17:04:02 +0000 |
12 | +++ account_analytic_analysis_rent/__openerp__.py 2014-02-11 23:05:08 +0000 |
13 | @@ -24,12 +24,16 @@ |
14 | 'name' : "Account Analytic Account Rent", |
15 | 'category' : "account_analytic", |
16 | 'version' : "1.0", |
17 | - 'depends' : ['account_analytic_analysis','product'], |
18 | + 'depends' : ['account_analytic_analysis','product','account_voucher'], |
19 | 'author' : "Vauxoo", |
20 | 'description' : """ |
21 | This module added product in account_analytic_analysis to product control |
22 | """, |
23 | - 'data' : ['account_analytic_account_rent.xml','product_view.xml','account_analytic_analysis_report.xml'], |
24 | + 'data' : ['account_analytic_account_rent.xml', |
25 | + 'product_view.xml', |
26 | + 'account_analytic_analysis_report.xml', |
27 | + 'wizard/lines_invoice_create_view.xml', |
28 | + ], |
29 | 'installable': True, |
30 | 'auto_install': False, |
31 | } |
32 | |
33 | === modified file 'account_analytic_analysis_rent/account_analytic_account_rent.py' |
34 | --- account_analytic_analysis_rent/account_analytic_account_rent.py 2013-06-03 17:04:02 +0000 |
35 | +++ account_analytic_analysis_rent/account_analytic_account_rent.py 2014-02-11 23:05:08 +0000 |
36 | @@ -22,12 +22,158 @@ |
37 | from openerp.osv import osv, fields |
38 | from datetime import datetime, timedelta |
39 | from tools.translate import _ |
40 | +from datetime import datetime, timedelta |
41 | +from dateutil.relativedelta import relativedelta |
42 | + |
43 | +class analytic_term(osv.osv): |
44 | + _name='analytic.term' |
45 | + |
46 | + _columns={ |
47 | + 'name': fields.char('Term',size=64,required=True), |
48 | + 'no_term': fields.integer('No Term') |
49 | + } |
50 | + |
51 | +class account_analytic_product(osv.osv): |
52 | + _name='account.analytic.product' |
53 | + |
54 | + |
55 | + def onchange_prodlot(self, cr , uid, ids, prodlot_id, context=None): |
56 | + if context==None: |
57 | + context={} |
58 | + res={} |
59 | + if prodlot_id: |
60 | + prodlot_obj=self.pool.get('stock.production.lot') |
61 | + if prodlot_obj.browse(cr, uid, prodlot_id, context=context).stock_available < 0: |
62 | + res={'value':{'prodlot_id': False },'warning':{ |
63 | + 'title': _('This product is already rented !'), |
64 | + 'message': _('This product is already rented,check serial number.') |
65 | + }} |
66 | + return res |
67 | + |
68 | + def onchange_product_id(self, cr, uid, ids, product_id, context=None): |
69 | + res={} |
70 | + list=[] |
71 | + if context==None: |
72 | + context={} |
73 | + if product_id: |
74 | + product_obj=self.pool.get('product.product') |
75 | + for prod in product_obj.browse(cr, uid, [product_id], context): |
76 | + type='rent' |
77 | + if prod.accesory_ok: |
78 | + type='accesory' |
79 | + list_data = [{'name':feature.name.id} for feature in prod.feature_ids] |
80 | + res={'value':{'type': type, }} |
81 | + return res |
82 | + |
83 | + _columns={ |
84 | + 'product_id':fields.many2one('product.product','Product', required=True, domain=['|', ('rent_ok','=',True), ('accesory_ok','=',True) ]), |
85 | + 'type': fields.selection([('rent','Rent'),('accesory','Accesory')],'Type'), |
86 | + 'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', help="Production lot is used to put a serial number on the production", select=True), |
87 | + 'analytic_id':fields.many2one('account.analytic.account','Account Analytic') |
88 | + } |
89 | + |
90 | +class account_analytic_line(osv.osv): |
91 | + _inherit='account.analytic.line' |
92 | + _order='product_id' |
93 | + |
94 | + def _check_inv(self, cr, uid, ids, vals): |
95 | + select = ids |
96 | + if isinstance(select, (int, long)): |
97 | + select = [ids] |
98 | + if ( not vals.has_key('invoice_id')) or vals['invoice_id' ] == False: |
99 | + for line in self.browse(cr, uid, select): |
100 | + if line.invoice_id and 'account_id' not in vals: |
101 | + raise osv.except_osv(_('Error !'), |
102 | + _('You cannot modify an invoiced analytic lines!')) |
103 | + return True |
104 | + |
105 | + def onchange_copys(self, cr, uid, id, w_start, w_end, context=None): |
106 | + res={} |
107 | + if context==None: |
108 | + context={} |
109 | + return {'value':{'unit_amount': w_end - w_start} } |
110 | + |
111 | + _columns={ |
112 | + 'w_start': fields.integer('Inicial'), |
113 | + 'w_end': fields.integer('Final'), |
114 | + 'feature_id': fields.many2one('product.feature.line','Feature'), |
115 | + 'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', help="Production lot is used to put a serial number on the production", select=True), |
116 | + } |
117 | + |
118 | + |
119 | +class account_invoice_line(osv.osv): |
120 | + _inherit='account.invoice.line' |
121 | + |
122 | + _columns={ |
123 | + 'w_start': fields.integer('Inicial'), |
124 | + 'w_end': fields.integer('Final'), |
125 | + 'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', help="Production lot is used to put a serial number on the production", select=True), |
126 | + } |
127 | +account_invoice_line() |
128 | + |
129 | |
130 | class account_analytic_account(osv.osv): |
131 | _inherit='account.analytic.account' |
132 | |
133 | + def onchange_product_lines(self, cr, uid, ids, product_ids, feature_ids, context=None): |
134 | + res={} |
135 | + list_feature=[] |
136 | + if context==None: |
137 | + context={} |
138 | + if product_ids: |
139 | + product_obj=self.pool.get('product.product') |
140 | + for prod in product_ids: |
141 | + if prod[2]['product_id']: |
142 | + for feature in product_obj.browse(cr, uid, prod[2]['product_id'], context=context).feature_ids: |
143 | + list_feature.append({'name': feature.name and feature.name.id or False, 'product_line_id':prod[2]['product_id'],'counter':feature.counter or False, 'prodlot_feature_id' : prod[2]['prodlot_id']}) |
144 | + return {'value':{'feature_ids': [(0, 6, data) for data in list_feature]}} |
145 | + |
146 | + def _get_journal(self, cr, uid, context=None): |
147 | + if context is None: |
148 | + context = {} |
149 | + type_inv = context.get('type', 'out_invoice') |
150 | + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) |
151 | + company_id = context.get('company_id', user.company_id.id) |
152 | + type2journal = {'out_invoice': 'sale', 'in_invoice': 'purchase', 'out_refund': 'sale_refund', 'in_refund': 'purchase_refund'} |
153 | + journal_obj = self.pool.get('account.journal') |
154 | + res = journal_obj.search(cr, uid, [('type', '=', type2journal.get(type_inv, 'sale')), |
155 | + ('company_id', '=', company_id)], |
156 | + limit=1) |
157 | + return res and res[0] or False |
158 | + |
159 | + def _compute_lines(self, cr, uid, ids, name, args, context=None): |
160 | + result = {} |
161 | + for contract in self.browse(cr, uid, ids, context=context): |
162 | + src = [] |
163 | + lines = [] |
164 | + for line in contract.line_ids: |
165 | + if line.invoice_id: |
166 | + if line.invoice_id.state=='paid': |
167 | + for l in line.invoice_id.payment_ids: |
168 | + if l.id not in lines: |
169 | + lines.append(l.id) |
170 | + result[contract.id] = lines |
171 | + return result |
172 | + |
173 | + def _compute_lines_inv(self, cr, uid, ids, name, args, context=None): |
174 | + result = {} |
175 | + for contract in self.browse(cr, uid, ids, context=context): |
176 | + src = [] |
177 | + lines = [] |
178 | + for line in contract.line_ids: |
179 | + if line.invoice_id and line.invoice_id.id not in lines: |
180 | + lines.append(line.invoice_id.id) |
181 | + result[contract.id]=lines |
182 | + return result |
183 | + |
184 | _columns={ |
185 | - 'product_id':fields.many2one('product.product','Product', domain=[('rent','=',False), ('rent_ok','=',True)]), |
186 | + 'product_ids':fields.one2many('account.analytic.product','analytic_id', 'Products'), |
187 | + 'term_id': fields.many2one('analytic.term','Term', required=True), |
188 | + 'voucher_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'), |
189 | + 'invoice_ids': fields.function(_compute_lines_inv, relation='account.invoice', type="many2many", string='Invoice'), |
190 | + 'group_product': fields.boolean('Group Product'), |
191 | + 'journal_id':fields.many2one('account.journal','Journal', required=True), |
192 | + 'feature_ids': fields.one2many('product.feature.line', 'analytic_id', 'Features') |
193 | } |
194 | |
195 | def set_close(self, cr, uid, ids, context=None): |
196 | @@ -37,10 +183,16 @@ |
197 | product_obj=self.pool.get('product.product') |
198 | ware_id=warehouse_obj.search(cr, uid, [], context=context)[0] |
199 | warehouse=warehouse_obj.browse(cr ,uid, ware_id, context=context) |
200 | + location = self.pool.get('stock.location').search(cr, uid, [('usage', '=', 'customer')], context=context) |
201 | + if location: |
202 | + location=location[0] |
203 | + else: |
204 | + raise osv.except_osv(_('Error!'), _('You not have a configured client location')) |
205 | for contract in self.browse(cr, uid , ids , context=context): |
206 | - picking_id=picking_obj.create(cr, uid, {'origin':contract.name, 'address_id':contract.contact_id.id,'date':contract.date_start,'type':'in'}, context=context) |
207 | - move_obj.create(cr, uid, {'name':contract.product_id.name,'product_id':contract.product_id.id,'product_qty':1,'picking_id':picking_id,'product_uom':contract.product_id.uom_id.id,'location_id':warehouse.lot_output_id.id,'location_dest_id':warehouse.lot_input_id.id}, context=context) |
208 | - product_obj.write(cr, uid, contract.product_id.id, {'rent':False, 'contract_id': False}, context=context) |
209 | + picking_id=picking_obj.create(cr, uid, {'origin':contract.name or False, 'address_id': contract.contact_id and contract.contact_id.id or False,'date':contract.date_start or False,'type':'in'}, context=context) |
210 | + for prod in contract.product_ids: |
211 | + move_obj.create(cr, uid, {'name':prod.product_id.name,'product_id':prod.product_id.id,'product_qty':1,'picking_id':picking_id,'product_uom':prod.product_id.uom_id.id,'location_id':location,'location_dest_id': warehouse.lot_input_id and warehouse.lot_input_id.id or False, 'prodlot_id': prod.prodlot_id and prod.prodlot_id.id or 1}, context=context) |
212 | + product_obj.write(cr, uid, prod.product_id.id, {'rent':False, 'contract_id': False}, context=context) |
213 | return super(account_analytic_account, self).set_close(cr, uid, ids, context=context) |
214 | |
215 | def set_open(self, cr, uid, ids, context=None): |
216 | @@ -48,17 +200,45 @@ |
217 | move_obj=self.pool.get('stock.move') |
218 | warehouse_obj=self.pool.get('stock.warehouse') |
219 | product_obj=self.pool.get('product.product') |
220 | + line_obj=self.pool.get('account.analytic.line') |
221 | ware_id=warehouse_obj.search(cr, uid, [], context=context)[0] |
222 | warehouse=warehouse_obj.browse(cr ,uid, ware_id, context=context) |
223 | |
224 | for contract in self.browse(cr, uid , ids , context=context): |
225 | - picking_id=picking_obj.create(cr, uid, {'origin':contract.name, 'address_id':contract.contact_id.id,'date':contract.date_start,'type':'out'}, context=context) |
226 | - move_obj.create(cr, uid, {'name':contract.product_id.name,'product_id':contract.product_id.id,'product_qty':1,'picking_id':picking_id,'product_uom':contract.product_id.uom_id.id,'location_id':warehouse.lot_stock_id.id,'location_dest_id':warehouse.lot_output_id.id}, context=context) |
227 | - product_obj.write(cr, uid, contract.product_id.id, {'rent':True,'contract_id':contract.id}, context=context) |
228 | + date_invoice=contract.date_start |
229 | + #~ date_invoice=datetime.strptime(contract.date_start, "%Y-%m-%d") |
230 | + picking_id=picking_obj.create(cr, uid, {'origin':contract.name, 'address_id': contract.contact_id and contract.contact_id.id or False,'date':contract.date_start,'type':'out'}, context=context) |
231 | + for prod in contract.product_ids: |
232 | + move_obj.create(cr, uid, {'name':prod.product_id.name,'product_id':prod.product_id.id,'product_qty':1,'picking_id':picking_id,'product_uom':prod.product_id.uom_id.id,'location_id': warehouse.lot_stock_id and warehouse.lot_stock_id.id or False,'location_dest_id': warehouse.lot_output_id and warehouse.lot_output_id.id or False, 'prodlot_id': prod.prodlot_id and prod.prodlot_id.id or 1}, context=context) |
233 | + for line in range(0,contract.term_id.no_term): |
234 | + for prod in contract.product_ids: |
235 | + a = prod.product_id.product_tmpl_id.property_account_income.id |
236 | + if not a: |
237 | + a = prod.product_id.categ_id.property_account_income_categ.id |
238 | + for feature in contract.feature_ids: |
239 | + if feature.product_line_id.id==prod.product_id.id: |
240 | + line_obj.create(cr, uid, {'date':date_invoice,'name':feature.name and feature.name.name or False,'product_id':prod.product_id.id,'product_uom_id':prod.product_id.uom_id.id,'general_account_id':a,'to_invoice':1,'account_id': contract and contract.id or False,'journal_id': contract.journal_id and contract.journal_id.analytic_journal_id and contract.journal_id.analytic_journal_id.id or False,'amount': feature and feature.cost or False, 'feature_id':feature and feature.id or False, 'prodlot_id': prod.prodlot_id and prod.prodlot_id.id or 1},context=context) |
241 | + product_obj.write(cr, uid, prod.product_id.id, {'rent':True,'contract_id': contract and contract.id or False}, context=context) |
242 | + date_invoice=(datetime.strptime(date_invoice, "%Y-%m-%d") + relativedelta(months=1)).strftime("%Y-%m-%d") |
243 | return super(account_analytic_account, self).set_open(cr, uid, ids, context=context) |
244 | |
245 | + def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False): |
246 | + journal_obj = self.pool.get('account.journal') |
247 | + if context is None: |
248 | + context = {} |
249 | + res = super(account_analytic_account,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) |
250 | + type = 'sale' |
251 | + for field in res['fields']: |
252 | + if field == 'journal_id' and type: |
253 | + journal_select = journal_obj._name_search(cr, uid, '', [('type', '=', type)], context=context, limit=None, name_get_uid=1) |
254 | + res['fields'][field]['selection'] = journal_select |
255 | + |
256 | + return res |
257 | + |
258 | _defaults = { |
259 | 'state': 'draft', |
260 | + 'group_product': True, |
261 | + 'journal_id': _get_journal, |
262 | } |
263 | account_analytic_account() |
264 | |
265 | @@ -77,5 +257,14 @@ |
266 | res['product']=line.product_id.id |
267 | return res |
268 | hr_timesheet_invoice_create() |
269 | - |
270 | - |
271 | + |
272 | + |
273 | +class stock_production_lot(osv.osv): |
274 | + _inherit='stock.production.lot' |
275 | + |
276 | + def name_get(self, cr, uid, ids, context=None): |
277 | + if ids and ids[0] == False: |
278 | + ids=[] |
279 | + return super(stock_production_lot, self).name_get( |
280 | + cr, uid, ids, context=context) |
281 | +stock_production_lot() |
282 | |
283 | === modified file 'account_analytic_analysis_rent/account_analytic_account_rent.xml' |
284 | --- account_analytic_analysis_rent/account_analytic_account_rent.xml 2013-06-03 17:04:02 +0000 |
285 | +++ account_analytic_analysis_rent/account_analytic_account_rent.xml 2014-02-11 23:05:08 +0000 |
286 | @@ -10,11 +10,172 @@ |
287 | <field name="arch" type="xml"> |
288 | <notebook position="inside"> |
289 | <page string="Product"> |
290 | - <field name="product_id"/> |
291 | - </page> |
292 | - </notebook> |
293 | - </field> |
294 | - </record> |
295 | + <field name="product_ids" on_change="onchange_product_lines(product_ids, feature_ids)" nolabel="1"> |
296 | + <tree string="products" editable="top"> |
297 | + <field name="product_id" on_change="onchange_product_id(product_id)"/> |
298 | + <field name="prodlot_id" |
299 | + context="{'product_id':product_id}" |
300 | + domain="[('product_id','=?',product_id)]" |
301 | + on_change="onchange_prodlot(prodlot_id)"/> |
302 | + <field name="type"/> |
303 | + </tree> |
304 | + <form string="products"> |
305 | + <field name="product_id" on_change="onchange_product_id(product_id)"/> |
306 | + <field name="prodlot_id" |
307 | + context="{'product_id':product_id}" |
308 | + domain="[('product_id','=?',product_id)]" |
309 | + on_change="onchange_prodlot(prodlot_id)"/> |
310 | + <field name="type"/> |
311 | + </form> |
312 | + </field> |
313 | + <newline/> |
314 | + <field name="feature_ids" nolabel="1"> |
315 | + <tree string='Features' editable="top"> |
316 | + <field name="product_line_id"/> |
317 | + <field name="name"/> |
318 | + <field name="counter"/> |
319 | + <field name="cost"/> |
320 | + <field name="prodlot_feature_id" invisible = '1'/> |
321 | + </tree> |
322 | + <form string='Features'> |
323 | + <field name="product_line_id"/> |
324 | + <field name="name"/> |
325 | + <field name="counter"/> |
326 | + <field name="cost"/> |
327 | + </form> |
328 | + </field> |
329 | + </page> |
330 | + </notebook> |
331 | + </field> |
332 | + </record> |
333 | + |
334 | + <record model="ir.ui.view" id="account_analytic_analysis_invoice_page"> |
335 | + <field name="name">account.analytic.analysis.invoice.page</field> |
336 | + <field name="model">account.analytic.account</field> |
337 | + <field name="type">form</field> |
338 | + <field name="inherit_id" ref="account.view_account_analytic_account_form"/> |
339 | + <field name="arch" type="xml"> |
340 | + <notebook position="inside"> |
341 | + <page string="Invoice"> |
342 | + <field name="invoice_ids" nolabel="1"/> |
343 | + </page> |
344 | + </notebook> |
345 | + </field> |
346 | + </record> |
347 | + |
348 | + <record model="ir.ui.view" id="account_analytic_analysis_payments"> |
349 | + <field name="name">account.analytic.analysis.payments</field> |
350 | + <field name="model">account.analytic.account</field> |
351 | + <field name="type">form</field> |
352 | + <field name="inherit_id" ref="account.view_account_analytic_account_form"/> |
353 | + <field name="arch" type="xml"> |
354 | + <notebook position="inside"> |
355 | + <page string="Payments"> |
356 | + <field name="voucher_ids" nolabel="1"/> |
357 | + </page> |
358 | + </notebook> |
359 | + </field> |
360 | + </record> |
361 | + |
362 | + |
363 | + <record id="view_analytic_term_tree" model="ir.ui.view"> |
364 | + <field name="name">view.analytic.term.tree</field> |
365 | + <field name="model">analytic.term</field> |
366 | + <field name="type">tree</field> |
367 | + <field name="arch" type="xml"> |
368 | + <tree string="Analytic Term"> |
369 | + <field name="name"/> |
370 | + <field name="no_term"/> |
371 | + </tree> |
372 | + </field> |
373 | + </record> |
374 | + |
375 | + <record id="view_analytic_term_form" model="ir.ui.view"> |
376 | + <field name="name">view.analytic.term.form</field> |
377 | + <field name="model">analytic.term</field> |
378 | + <field name="type">form</field> |
379 | + <field name="arch" type="xml"> |
380 | + <form string="Analytic Term"> |
381 | + <field name="name"/> |
382 | + <field name="no_term"/> |
383 | + </form> |
384 | + </field> |
385 | + </record> |
386 | + |
387 | + <record model="ir.actions.act_window" id="analytic_term_action"> |
388 | + <field name="name">Analytic Term</field> |
389 | + <field name="res_model">analytic.term</field> |
390 | + <field name="view_type">form</field> |
391 | + <field name="view_mode">tree,form</field> |
392 | + </record> |
393 | + <menuitem id="analytic_contract" name="Contract" parent="base.menu_sale_config_sales"/> |
394 | + <menuitem action="analytic_term_action" id="analytic_term_action_menu" parent="analytic_contract"/> |
395 | + |
396 | + |
397 | + <record model="ir.ui.view" id="account_analytic_analysis_term_contract"> |
398 | + <field name="name">account.analytic.analysis.term.contract</field> |
399 | + <field name="model">account.analytic.account</field> |
400 | + <field name="type">form</field> |
401 | + <field name="inherit_id" ref="account.view_account_analytic_account_form"/> |
402 | + <field name="arch" type="xml"> |
403 | + <field name="quantity_max" position="after"> |
404 | + <field name="term_id"/> |
405 | + </field> |
406 | + </field> |
407 | + </record> |
408 | + |
409 | + <record model="ir.ui.view" id="account_analytic_analysis_journal_contract"> |
410 | + <field name="name">account.analytic.analysis.journal.contract</field> |
411 | + <field name="model">account.analytic.account</field> |
412 | + <field name="type">form</field> |
413 | + <field name="inherit_id" ref="account.view_account_analytic_account_form"/> |
414 | + <field name="arch" type="xml"> |
415 | + <field name="user_id" position="after"> |
416 | + <field name="journal_id" widget="selection"/> |
417 | + </field> |
418 | + </field> |
419 | + </record> |
420 | + |
421 | + <record model="ir.ui.view" id="account_analytic_analysis_group_prod"> |
422 | + <field name="name">account.analytic.analysis.group.prod</field> |
423 | + <field name="model">account.analytic.account</field> |
424 | + <field name="type">form</field> |
425 | + <field name="inherit_id" ref="hr_timesheet_invoice.account_analytic_account_form_form"/> |
426 | + <field name="arch" type="xml"> |
427 | + <field name="amount_invoiced" position="after"> |
428 | + <field name="group_product"/> |
429 | + </field> |
430 | + </field> |
431 | + </record> |
432 | + |
433 | + |
434 | + <record model="ir.ui.view" id="account_analytic_line_product_visible"> |
435 | + <field name="name">account.analytic.line.product.visible</field> |
436 | + <field name="model">account.analytic.line</field> |
437 | + <field name="type">form</field> |
438 | + <field name="inherit_id" ref="account.view_account_analytic_line_tree"/> |
439 | + <field name="arch" type="xml"> |
440 | + <field name="product_id" position="replace"> |
441 | + <field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id, journal_id)" /> |
442 | + </field> |
443 | + </field> |
444 | + </record> |
445 | + |
446 | + <record model="ir.ui.view" id="account_invoice_line_write"> |
447 | + <field name="name">account.invoice.line_write</field> |
448 | + <field name="model">account.invoice.line</field> |
449 | + <field name="type">form</field> |
450 | + <field name="inherit_id" ref="account.view_invoice_line_tree"/> |
451 | + <field name="arch" type="xml"> |
452 | + <field name="name" position="after"> |
453 | + <field name="product_id" /> |
454 | + <field name="prodlot_id" /> |
455 | + <field name="w_start" /> |
456 | + <field name="w_end" /> |
457 | + </field> |
458 | + </field> |
459 | + </record> |
460 | + |
461 | |
462 | </data> |
463 | </openerp> |
464 | |
465 | === modified file 'account_analytic_analysis_rent/product.py' |
466 | --- account_analytic_analysis_rent/product.py 2013-06-03 17:04:02 +0000 |
467 | +++ account_analytic_analysis_rent/product.py 2014-02-11 23:05:08 +0000 |
468 | @@ -22,15 +22,54 @@ |
469 | from openerp.osv import osv, fields |
470 | from datetime import datetime, timedelta |
471 | from tools.translate import _ |
472 | +import decimal_precision as dp |
473 | |
474 | class product_template(osv.osv): |
475 | _inherit='product.template' |
476 | |
477 | + |
478 | + |
479 | _columns={ |
480 | 'rent_ok':fields.boolean('Rentable'), |
481 | + 'accesory_ok':fields.boolean('Accesory'), |
482 | 'rent': fields.boolean('Rent', readonly=True), |
483 | - 'contract_id': fields.many2one('account.analytic.account', 'Contract', readonly=True) |
484 | + 'contract_id': fields.many2one('account.analytic.account', 'Contract', readonly=True), |
485 | } |
486 | |
487 | product_template() |
488 | - |
489 | + |
490 | +class product_product(osv.osv): |
491 | + _inherit='product.product' |
492 | + |
493 | + _columns={ |
494 | + 'feature_ids': fields.one2many('product.feature.line', 'product_id', 'Features') |
495 | + } |
496 | + |
497 | +product_product() |
498 | + |
499 | +class product_feature(osv.osv): |
500 | + _name='product.feature' |
501 | + |
502 | + _columns={ |
503 | + 'name':fields.char('Name', size=64, required=True), |
504 | + 'description':fields.char('Description', size=256), |
505 | + } |
506 | + |
507 | +product_feature() |
508 | + |
509 | +class product_feature_line(osv.osv): |
510 | + _name='product.feature.line' |
511 | + _order='product_id' |
512 | + _columns={ |
513 | + 'name':fields.many2one('product.feature', 'Feature', required=True), |
514 | + 'product_id':fields.many2one('product.product','Product'), |
515 | + 'product_line_id':fields.many2one('product.product','Product'), |
516 | + 'counter':fields.integer('Counter'), |
517 | + 'analytic_id':fields.many2one('account.analytic.account','Product'), |
518 | + 'cost':fields.float('cost', digits_compute=dp.get_precision('Account')), |
519 | + 'prodlot_feature_id': fields.many2one('stock.production.lot', 'Production Lot', help="Production lot is used to put a serial number on the production", select=True), |
520 | + } |
521 | + |
522 | +product_feature_line() |
523 | + |
524 | + |
525 | |
526 | === modified file 'account_analytic_analysis_rent/product_view.xml' |
527 | --- account_analytic_analysis_rent/product_view.xml 2013-06-03 17:04:02 +0000 |
528 | +++ account_analytic_analysis_rent/product_view.xml 2014-02-11 23:05:08 +0000 |
529 | @@ -3,19 +3,42 @@ |
530 | <data> |
531 | |
532 | <record model="ir.ui.view" id="product_rentable"> |
533 | - <field name="name">product_rentable</field> |
534 | + <field name="name">product.rentable</field> |
535 | <field name="model">product.product</field> |
536 | <field name="type">form</field> |
537 | <field name="inherit_id" ref="product.product_normal_form_view"/> |
538 | <field name="arch" type="xml"> |
539 | <field name="purchase_ok" position="after"> |
540 | <field name="rent_ok"/> |
541 | + <field name="accesory_ok"/> |
542 | </field> |
543 | </field> |
544 | </record> |
545 | |
546 | + <record model="ir.ui.view" id="product_feature_product"> |
547 | + <field name="name">product.feature.product</field> |
548 | + <field name="model">product.product</field> |
549 | + <field name="type">form</field> |
550 | + <field name="inherit_id" ref="product.product_normal_form_view"/> |
551 | + <field name="arch" type="xml"> |
552 | + <group name="misc" position="after"> |
553 | + <group name="Features" colspan="2"> |
554 | + <separator colspan="4" string='Features'/> |
555 | + <field name="feature_ids" nolabel="1"> |
556 | + <tree string='Features'> |
557 | + <field name="name"/> |
558 | + </tree> |
559 | + <form string='Features'> |
560 | + <field name="name"/> |
561 | + </form> |
562 | + </field> |
563 | + </group> |
564 | + </group> |
565 | + </field> |
566 | + </record> |
567 | + |
568 | <record model="ir.ui.view" id="product_rent"> |
569 | - <field name="name">product_rent</field> |
570 | + <field name="name">product.rent</field> |
571 | <field name="model">product.product</field> |
572 | <field name="type">form</field> |
573 | <field name="inherit_id" ref="product.product_normal_form_view"/> |
574 | @@ -49,5 +72,48 @@ |
575 | |
576 | <menuitem action="product_rent_action" id="product_rent_action_menu" parent="base.menu_sales"/> |
577 | |
578 | + <record model="ir.actions.act_window" id="product_accesory_action"> |
579 | + <field name="name">Accesory Product</field> |
580 | + <field name="res_model">product.product</field> |
581 | + <field name="view_type">form</field> |
582 | + <field name="view_mode">tree,form</field> |
583 | + <field name="domain">[('accesory_ok','=',True)]</field> |
584 | + </record> |
585 | + |
586 | + <menuitem action="product_accesory_action" id="product_accesory_action_menu" parent="base.menu_sales"/> |
587 | + |
588 | + <record id="view_feature_product_tree" model="ir.ui.view"> |
589 | + <field name="name">view.feature.product.tree</field> |
590 | + <field name="model">product.feature</field> |
591 | + <field name="type">tree</field> |
592 | + <field name="arch" type="xml"> |
593 | + <tree string="Features"> |
594 | + <field name="name"/> |
595 | + <field name="description"/> |
596 | + </tree> |
597 | + </field> |
598 | + </record> |
599 | + |
600 | + <record id="view_feature_product_form" model="ir.ui.view"> |
601 | + <field name="name">view.feature.product.form</field> |
602 | + <field name="model">product.feature</field> |
603 | + <field name="type">form</field> |
604 | + <field name="arch" type="xml"> |
605 | + <form string="Features"> |
606 | + <field name="name"/> |
607 | + <field name="description"/> |
608 | + </form> |
609 | + </field> |
610 | + </record> |
611 | + |
612 | + <record model="ir.actions.act_window" id="product_feature_action"> |
613 | + <field name="name">Features</field> |
614 | + <field name="res_model">product.feature</field> |
615 | + <field name="view_type">form</field> |
616 | + <field name="view_mode">tree,form</field> |
617 | + </record> |
618 | + <menuitem id="product_feature" name="Features" parent="base.menu_sale_config_sales"/> |
619 | + <menuitem action="product_feature_action" id="product_feature_action_menu" parent="product_feature"/> |
620 | + |
621 | </data> |
622 | </openerp> |
623 | |
624 | === added directory 'account_analytic_analysis_rent/wizard' |
625 | === added file 'account_analytic_analysis_rent/wizard/__init__.py' |
626 | --- account_analytic_analysis_rent/wizard/__init__.py 1970-01-01 00:00:00 +0000 |
627 | +++ account_analytic_analysis_rent/wizard/__init__.py 2014-02-11 23:05:08 +0000 |
628 | @@ -0,0 +1,1 @@ |
629 | +import lines_invoice_create |
630 | |
631 | === added file 'account_analytic_analysis_rent/wizard/lines_invoice_create.py' |
632 | --- account_analytic_analysis_rent/wizard/lines_invoice_create.py 1970-01-01 00:00:00 +0000 |
633 | +++ account_analytic_analysis_rent/wizard/lines_invoice_create.py 2014-02-11 23:05:08 +0000 |
634 | @@ -0,0 +1,268 @@ |
635 | +# -*- coding: utf-8 -*- |
636 | +############################################################################## |
637 | +# |
638 | +# OpenERP, Open Source Management Solution |
639 | +# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
640 | +# |
641 | +# This program is free software: you can redistribute it and/or modify |
642 | +# it under the terms of the GNU Affero General Public License as |
643 | +# published by the Free Software Foundation, either version 3 of the |
644 | +# License, or (at your option) any later version. |
645 | +# |
646 | +# This program is distributed in the hope that it will be useful, |
647 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
648 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
649 | +# GNU Affero General Public License for more details. |
650 | +# |
651 | +# You should have received a copy of the GNU Affero General Public License |
652 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
653 | +# |
654 | +############################################################################## |
655 | + |
656 | +import time |
657 | +from datetime import datetime |
658 | +from osv import osv, fields |
659 | +from tools.translate import _ |
660 | + |
661 | +## Create an invoice based on selected timesheet lines |
662 | +# |
663 | + |
664 | +class account_analytic_line(osv.osv): |
665 | + _inherit = "account.analytic.line" |
666 | + |
667 | + # |
668 | + # data = { |
669 | + # 'date': boolean |
670 | + # 'time': boolean |
671 | + # 'name': boolean |
672 | + # 'price': boolean |
673 | + # 'product': many2one id |
674 | + # } |
675 | + def invoice_cost_create(self, cr, uid, ids, data={}, context=None): |
676 | + analytic_account_obj = self.pool.get('account.analytic.account') |
677 | + res_partner_obj = self.pool.get('res.partner') |
678 | + account_payment_term_obj = self.pool.get('account.payment.term') |
679 | + invoice_obj = self.pool.get('account.invoice') |
680 | + product_obj = self.pool.get('product.product') |
681 | + invoice_factor_obj = self.pool.get('hr_timesheet_invoice.factor') |
682 | + pro_price_obj = self.pool.get('product.pricelist') |
683 | + fiscal_pos_obj = self.pool.get('account.fiscal.position') |
684 | + product_uom_obj = self.pool.get('product.uom') |
685 | + invoice_line_obj = self.pool.get('account.invoice.line') |
686 | + feature_line_obj = self.pool.get('product.feature.line') |
687 | + invoices = [] |
688 | + if context is None: |
689 | + context = {} |
690 | + |
691 | + account_ids = {} |
692 | + for line in self.pool.get('account.analytic.line').browse(cr, uid, ids, context=context): |
693 | + account_ids[line.account_id.id] = True |
694 | + |
695 | + account_ids = account_ids.keys() #data['accounts'] |
696 | + for account in analytic_account_obj.browse(cr, uid, account_ids, context=context): |
697 | + partner = account.partner_id |
698 | + if (not partner) or not (account.pricelist_id): |
699 | + raise osv.except_osv(_('Analytic Account incomplete'), |
700 | + _('Please fill in the Partner or Customer and Sale Pricelist fields in the Analytic Account:\n%s') % (account.name,)) |
701 | + |
702 | + if not partner.address: |
703 | + raise osv.except_osv(_('Partner incomplete'), |
704 | + _('Please fill in the Address field in the Partner: %s.') % (partner.name,)) |
705 | + |
706 | + date_due = False |
707 | + if partner.property_payment_term: |
708 | + pterm_list= account_payment_term_obj.compute(cr, uid, |
709 | + partner.property_payment_term.id, value=1, |
710 | + date_ref=time.strftime('%Y-%m-%d')) |
711 | + if pterm_list: |
712 | + pterm_list = [line[0] for line in pterm_list] |
713 | + pterm_list.sort() |
714 | + date_due = pterm_list[-1] |
715 | + curr_invoice = { |
716 | + 'name': time.strftime('%d/%m/%Y')+' - '+account.name, |
717 | + 'partner_id': account.partner_id.id, |
718 | + 'address_contact_id': res_partner_obj.address_get(cr, uid, |
719 | + [account.partner_id.id], adr_pref=['contact'])['contact'], |
720 | + 'address_invoice_id': res_partner_obj.address_get(cr, uid, |
721 | + [account.partner_id.id], adr_pref=['invoice'])['invoice'], |
722 | + 'payment_term': partner.property_payment_term.id or False, |
723 | + 'account_id': partner.property_account_receivable.id, |
724 | + 'currency_id': account.pricelist_id.currency_id.id, |
725 | + 'date_due': date_due, |
726 | + 'fiscal_position': account.partner_id.property_account_position.id, |
727 | + 'type':'out_invoice', |
728 | + 'journal_id':account.journal_id.id |
729 | + } |
730 | + last_invoice = invoice_obj.create(cr, uid, curr_invoice, context=context) |
731 | + invoices.append(last_invoice) |
732 | + context2 = context.copy() |
733 | + context2['lang'] = partner.lang |
734 | + cr.execute("SELECT product_id, to_invoice, unit_amount, product_uom_id, w_start, w_end, name, amount, feature_id, prodlot_id " \ |
735 | + "FROM account_analytic_line as line " \ |
736 | + "WHERE account_id = %s " \ |
737 | + "AND id IN %s AND to_invoice IS NOT NULL " , (account.id, tuple(ids),)) |
738 | + |
739 | + for product_id, factor_id, qty, uom, w_start, w_end, name, amount, feature_id, prodlot_id in cr.fetchall(): |
740 | + product = product_obj.browse(cr, uid, product_id, context2) |
741 | + if not product: |
742 | + raise osv.except_osv(_('Error'), _('At least one line has no product !')) |
743 | + factor_name = '' |
744 | + factor = invoice_factor_obj.browse(cr, uid, factor_id, context2) |
745 | + |
746 | + ctx = context.copy() |
747 | + ctx.update({'uom':uom}) |
748 | + if account.pricelist_id: |
749 | + pl = account.pricelist_id.id |
750 | + price = pro_price_obj.price_get(cr,uid,[pl], product_id or data.get('product', False), qty or 1.0, account.partner_id.id, context=ctx)[pl] |
751 | + else: |
752 | + price = 0.0 |
753 | + |
754 | + taxes = product.taxes_id |
755 | + tax = fiscal_pos_obj.map_tax(cr, uid, account.partner_id.property_account_position, taxes) |
756 | + account_id = product.product_tmpl_id.property_account_income.id or product.categ_id.property_account_income_categ.id |
757 | + if not account_id: |
758 | + raise osv.except_osv(_("Configuration Error"), _("No income account defined for product '%s'") % product.name) |
759 | + curr_line = { |
760 | + 'price_unit': amount or price, |
761 | + 'quantity': qty, |
762 | + 'discount':factor.factor, |
763 | + 'invoice_line_tax_id': [(6,0,tax )], |
764 | + 'invoice_id': last_invoice, |
765 | + 'name': name, |
766 | + 'product_id': product_id or data.get('product',product_id), |
767 | + 'invoice_line_tax_id': [(6,0,tax)], |
768 | + 'uos_id': uom, |
769 | + 'account_id': account_id, |
770 | + 'account_analytic_id': account.id, |
771 | + 'w_start': int(w_start or 0), |
772 | + 'w_end': int(w_end or 0), |
773 | + 'prodlot_id': prodlot_id, |
774 | + } |
775 | + feature_line_obj.write(cr, uid, feature_id, {'counter': int(w_end or 0)}, context=context) |
776 | + # |
777 | + # Compute for lines |
778 | + # |
779 | + cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s ORDER BY account_analytic_line.date", (account.id, tuple(ids), product_id, factor_id)) |
780 | + |
781 | + line_ids = cr.dictfetchall() |
782 | + note = [] |
783 | + for line in line_ids: |
784 | + # set invoice_line_note |
785 | + details = [] |
786 | + if data.get('date', False): |
787 | + details.append(line['date']) |
788 | + if data.get('time', False): |
789 | + if line['product_uom_id']: |
790 | + details.append("%s %s" % (line['unit_amount'], product_uom_obj.browse(cr, uid, [line['product_uom_id']],context2)[0].name)) |
791 | + else: |
792 | + details.append("%s" % (line['unit_amount'], )) |
793 | + if data.get('name', False): |
794 | + details.append(line['name']) |
795 | + note.append(u' - '.join(map(lambda x: unicode(x) or '',details))) |
796 | + |
797 | + curr_line['note'] = "\n".join(map(lambda x: unicode(x) or '',note)) |
798 | + invoice_line_obj.create(cr, uid, curr_line, context=context) |
799 | + cr.execute("update account_analytic_line set invoice_id=%s WHERE account_id = %s and id IN %s", (last_invoice, account.id, tuple(ids))) |
800 | + |
801 | + invoice_obj.button_reset_taxes(cr, uid, [last_invoice], context) |
802 | + return invoices |
803 | + |
804 | +class lines_create(osv.osv_memory): |
805 | + |
806 | + _name = 'lines.create' |
807 | + _columns = { |
808 | + 'month': fields.selection([('1','January'), ('2','February'), |
809 | + ('3','March'), ('4','April'), ('5','May'), ('6','June'), |
810 | + ('7','July'), ('8','August'), ('9','September'), ('10','October'), |
811 | + ('11','November'), ('12','December')], 'Month'), |
812 | + 'line_ids': fields.many2many('account.analytic.line','analytic_wiz_lines_rel','wiz_id','line_id','lines'), |
813 | + 'contract_id': fields.many2one('account.analytic.account','Contract') |
814 | + #~ 'time': fields.boolean('Time spent', help='The time of each work done will be displayed on the invoice'), |
815 | + #~ 'name': fields.boolean('Description', help='The detail of each work done will be displayed on the invoice'), |
816 | + #~ 'price': fields.boolean('Cost', help='The cost of each work done will be displayed on the invoice. You probably don\'t want to check this'), |
817 | + #~ 'product': fields.many2one('product.product', 'Product', help='Complete this field only if you want to force to use a specific product. Keep empty to use the real product that comes from the cost.'), |
818 | + } |
819 | + |
820 | + def default_get(self, cr, uid, fields, context=None): |
821 | + if context is None: |
822 | + context = {} |
823 | + res = super(lines_create, self).default_get( |
824 | + cr, uid, fields, context=context) |
825 | + analytic_obj = self.pool.get('account.analytic.account') |
826 | + product_obj = self.pool.get('product.product') |
827 | + line_obj = self.pool.get('account.analytic.line') |
828 | + lines_ids=[] |
829 | + if context.get('active_model') == 'account.analytic.account': |
830 | + res['contract_id']=context.get('active_id') |
831 | + res['month']=str(datetime.strptime(datetime.now().strftime('%Y-%m-%d'), "%Y-%m-%d").month) |
832 | + for contract in analytic_obj.browse(cr,uid,context['active_ids'],context): |
833 | + lines_ids=[] |
834 | + for line in contract.line_ids: |
835 | + if not line.invoice_id and line.to_invoice: |
836 | + date_line=datetime.strptime(line.date, "%Y-%m-%d") |
837 | + #~ date=datetime.strptime(datetime.now().strftime('%Y-%m-%d'), "%Y-%m-%d") |
838 | + if date_line.month==res['month']: |
839 | + lines_ids.append(line.id) |
840 | + res['line_ids']=lines_ids |
841 | + return res |
842 | + |
843 | + def onchange_date(self, cr, uid, ids, month, contract_id, context=None): |
844 | + if context is None: |
845 | + context = {} |
846 | + res={} |
847 | + analytic_obj = self.pool.get('account.analytic.account') |
848 | + line_obj = self.pool.get('account.analytic.line') |
849 | + lines_ids=[] |
850 | + for contract in analytic_obj.browse(cr,uid,[contract_id],context): |
851 | + lines_ids=[] |
852 | + for line in contract.line_ids: |
853 | + if not line.invoice_id and line.to_invoice: |
854 | + date_line=datetime.strptime(line.date, "%Y-%m-%d") |
855 | + #~ date_new=datetime.strptime(month, "%Y-%m-%d") |
856 | + if str(month)==str(date_line.month): |
857 | + for feature in contract.feature_ids: |
858 | + if feature.id==line.feature_id.id: |
859 | + line_obj.write(cr, uid, line.id, {'w_start':feature.counter}, context=context) |
860 | + lines_ids.append(line.id) |
861 | + res['value']={'line_ids':lines_ids} |
862 | + return res |
863 | + |
864 | + |
865 | + |
866 | + def do_create(self, cr, uid, ids, context=None): |
867 | + analytic_obj = self.pool.get('account.analytic.account') |
868 | + data = self.read(cr, uid, ids, [], context=context)[0] |
869 | + if context.get('active_model') == 'account.analytic.account': |
870 | + invs=[] |
871 | + for contract in analytic_obj.browse(cr,uid,context['active_ids'],context): |
872 | + new_lines=[] |
873 | + for prod in contract.product_ids: |
874 | + lines_ids=[] |
875 | + for line in contract.line_ids: |
876 | + if not line.invoice_id and line.to_invoice and line.product_id.id==prod.product_id.id and prod.type=='rent': |
877 | + date_line=datetime.strptime(line.date, "%Y-%m-%d") |
878 | + #~ date=datetime.strptime(data['date'], "%Y-%m-%d") |
879 | + if str(date_line.month)==data['month']: |
880 | + lines_ids.append(line.id) |
881 | + if not lines_ids and prod.type=='rent': |
882 | + raise osv.except_osv(_('Warning !'), _("Invoice is already linked to some of the analytic line(s)!")) |
883 | + if contract.group_product and prod.type=='rent': |
884 | + new_lines=new_lines + lines_ids |
885 | + elif not contract.group_product and prod.type=='rent': |
886 | + invs.append(self.pool.get('account.analytic.line').invoice_cost_create(cr, uid, lines_ids, {}, context=context)) |
887 | + if contract.group_product: |
888 | + invs.append(self.pool.get('account.analytic.line').invoice_cost_create(cr, uid, new_lines, {}, context=context)) |
889 | + mod_obj = self.pool.get('ir.model.data') |
890 | + act_obj = self.pool.get('ir.actions.act_window') |
891 | + mod_ids = mod_obj.search(cr, uid, [('name', '=', 'action_invoice_tree1')], context=context)[0] |
892 | + res_id = mod_obj.read(cr, uid, mod_ids, ['res_id'], context=context)['res_id'] |
893 | + act_win = act_obj.read(cr, uid, res_id, [], context=context) |
894 | + act_win['domain'] = [('id','in',invs),('type','=','out_invoice')] |
895 | + act_win['name'] = _('Invoices') |
896 | + return act_win |
897 | + |
898 | + |
899 | +lines_create() |
900 | + |
901 | + |
902 | + |
903 | |
904 | === added file 'account_analytic_analysis_rent/wizard/lines_invoice_create_view.xml' |
905 | --- account_analytic_analysis_rent/wizard/lines_invoice_create_view.xml 1970-01-01 00:00:00 +0000 |
906 | +++ account_analytic_analysis_rent/wizard/lines_invoice_create_view.xml 2014-02-11 23:05:08 +0000 |
907 | @@ -0,0 +1,66 @@ |
908 | +<?xml version="1.0" encoding="utf-8"?> |
909 | +<openerp> |
910 | + <data> |
911 | + |
912 | + <record id="view_lines_create" model="ir.ui.view"> |
913 | + <field name="name">lines.create.form</field> |
914 | + <field name="model">lines.create</field> |
915 | + <field name="type">form</field> |
916 | + <field name="arch" type="xml"> |
917 | + <form string="Create Invoice"> |
918 | + <notebook colspan="4"> |
919 | + <page string="Billing Data"> |
920 | + <group col="4" colspan="4"> |
921 | + <separator string="Do you want to show details of work in invoice ?" colspan="4"/> |
922 | + <field name="month" on_change="onchange_date(month,contract_id)"/> |
923 | + <newline/> |
924 | + <field name="line_ids" nolabel="1" colspan="4"> |
925 | + <tree editable="top" string="Analytic Entries"> |
926 | + <field name="date" /> |
927 | + <field name="ref" /> |
928 | + <field name="name" /> |
929 | + <field name="journal_id" /> |
930 | + <field name="amount" sum="Total" /> |
931 | + <field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id, journal_id)" /> |
932 | + <field name="prodlot_id"/> |
933 | + <field name="w_start" on_change="onchange_copys(w_start,w_end)"/> |
934 | + <field name="w_end" on_change="onchange_copys(w_start,w_end)" /> |
935 | + <field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)" sum="Total Quantity" /> |
936 | + <field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)" /> |
937 | + <field name="general_account_id" /> |
938 | + <field name="user_id" invisible="1"/> |
939 | + |
940 | + </tree> |
941 | + </field> |
942 | + <field name="contract_id" invisible="1"/> |
943 | + </group> |
944 | + </page> |
945 | + </notebook> |
946 | + <separator colspan="4"/> |
947 | + <group col="2" colspan="4"> |
948 | + <button special="cancel" string="Cancel" icon='gtk-cancel'/> |
949 | + <button name="do_create" string="Create Invoices" colspan="1" type="object" icon="terp-gtk-go-back-rtl"/> |
950 | + </group> |
951 | + </form> |
952 | + </field> |
953 | + </record> |
954 | + |
955 | + <record id="lines_invoice_create" model="ir.actions.act_window"> |
956 | + <field name="name">Create Invoice</field> |
957 | + <field name="type">ir.actions.act_window</field> |
958 | + <field name="res_model">lines.create</field> |
959 | + <field name="view_type">form</field> |
960 | + <field name="view_mode">form</field> |
961 | + <field name="target">new</field> |
962 | + </record> |
963 | + |
964 | + <act_window id="lines_invoice_create_wizard" |
965 | + name="Create Invoice" |
966 | + src_model="account.analytic.account" |
967 | + res_model="lines.create" |
968 | + view_mode="form" |
969 | + target="new" |
970 | + key2="client_action_multi"/> |
971 | + |
972 | + </data> |
973 | +</openerp> |