Merge lp:~altegra/altegra/altegra_dev_carlos_2 into lp:~altegra/+junk/altegra
- altegra_dev_carlos_2
- Merge into altegra
Proposed by
Carlos Blanco - http://www.grupoaltegra.com
Status: | Merged |
---|---|
Merged at revision: | 102 |
Proposed branch: | lp:~altegra/altegra/altegra_dev_carlos_2 |
Merge into: | lp:~altegra/+junk/altegra |
Diff against target: |
1882 lines (+1587/-50) 25 files modified
account_altegra/__openerp__.py (+1/-0) account_altegra/account_invoice_view.xml (+16/-0) crm_altegra/__init__.py (+32/-0) crm_altegra/__openerp__.py (+57/-0) crm_altegra/crm_project.py (+586/-0) crm_altegra/crm_project_view.xml (+442/-0) crm_altegra/security/groups.xml (+15/-0) crm_altegra/security/ir.model.access.csv (+4/-0) crm_altegra/security/sequence.xml (+21/-0) dollars_altegra/__init__.py (+4/-0) dollars_altegra/__openerp__.py (+2/-0) dollars_altegra/account_invoice_view.xml (+45/-3) dollars_altegra/account_voucher_view.xml (+16/-0) dollars_altegra/internal_order.py (+44/-0) dollars_altegra/internal_order_view.xml (+19/-0) dollars_altegra/purchase.py (+52/-0) dollars_altegra/purchase_view.xml (+22/-0) dollars_altegra/sale.py (+10/-0) dollars_altegra/stock.py (+47/-0) dollars_altegra/wizard/__init__.py (+32/-0) dollars_altegra/wizard/create_purchase.py (+62/-0) internal_order_altegra/purchase.py (+4/-1) internal_order_altegra/sale.py (+24/-29) internal_order_altegra/wizard/create_purchase.py (+29/-16) product_altegra/product.py (+1/-1) |
To merge this branch: | bzr merge lp:~altegra/altegra/altegra_dev_carlos_2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Eric Hernández - http://www.grupoaltegra.com | Pending | ||
Review via email:
|
Commit message
Description of the change
[REF] Purchase_order has product's price in Dollars
To post a comment you must log in.
- 102. By Eric Hernández - http://www.grupoaltegra.com
-
[MERGE] Carlos
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'account_altegra/__openerp__.py' |
2 | --- account_altegra/__openerp__.py 2013-02-19 00:22:16 +0000 |
3 | +++ account_altegra/__openerp__.py 2013-07-03 23:03:28 +0000 |
4 | @@ -38,6 +38,7 @@ |
5 | "description": "Account customization altegra", |
6 | "data" :[ |
7 | #~ "account_invoice_view.xml", |
8 | + "account_invoice_view.xml", |
9 | ], |
10 | 'demo': [], |
11 | 'test': [], |
12 | |
13 | === added file 'account_altegra/account_invoice_view.xml' |
14 | --- account_altegra/account_invoice_view.xml 1970-01-01 00:00:00 +0000 |
15 | +++ account_altegra/account_invoice_view.xml 2013-07-03 23:03:28 +0000 |
16 | @@ -0,0 +1,16 @@ |
17 | +<?xml version="1.0" encoding="utf-8"?> |
18 | +<openerp> |
19 | + <data> |
20 | + <record model="ir.ui.view" id="view_invoice_line_form_inherit"> |
21 | + <field name="name">view.invoice.line.form.inherit</field> |
22 | + <field name="type">form</field> |
23 | + <field name="model">account.invoice.line</field> |
24 | + <field name="inherit_id" ref="account.view_invoice_line_form" /> |
25 | + <field name="arch" type="xml"> |
26 | + <field name="uos_id" position="replace"> |
27 | + <field name="uos_id" nolabel="1"/> |
28 | + </field> |
29 | + </field> |
30 | + </record> |
31 | + </data> |
32 | +</openerp> |
33 | |
34 | === added directory 'crm_altegra' |
35 | === added file 'crm_altegra/__init__.py' |
36 | --- crm_altegra/__init__.py 1970-01-01 00:00:00 +0000 |
37 | +++ crm_altegra/__init__.py 2013-07-03 23:03:28 +0000 |
38 | @@ -0,0 +1,32 @@ |
39 | +#!/usr/bin/env python |
40 | +#-*- coding:utf-8 -*- |
41 | + |
42 | +############################################################################# |
43 | +# Module Writen to OpenERP, Open Source Management Solution |
44 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
45 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
46 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
47 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
48 | +# |
49 | +############################################################################# |
50 | +# |
51 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
52 | +# |
53 | +############################################################################# |
54 | +# |
55 | +# This program is free software: you can redistribute it and/or modify |
56 | +# it under the terms of the GNU Affero General Public License as |
57 | +# published by the Free Software Foundation, either version 3 of the |
58 | +# License, or (at your option) any later version. |
59 | +# |
60 | +# This program is distributed in the hope that it will be useful, |
61 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
62 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
63 | +# GNU Affero General Public License for more details. |
64 | +# |
65 | +# You should have received a copy of the GNU Affero General Public License |
66 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
67 | +# |
68 | +############################################################################# |
69 | + |
70 | +import crm_project |
71 | |
72 | === added file 'crm_altegra/__openerp__.py' |
73 | --- crm_altegra/__openerp__.py 1970-01-01 00:00:00 +0000 |
74 | +++ crm_altegra/__openerp__.py 2013-07-03 23:03:28 +0000 |
75 | @@ -0,0 +1,57 @@ |
76 | +#!/usr/bin/env python |
77 | +#-*- coding:utf-8 -*- |
78 | + |
79 | +############################################################################# |
80 | +# Module Writen to OpenERP, Open Source Management Solution |
81 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
82 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
83 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
84 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
85 | +# |
86 | +############################################################################# |
87 | +# |
88 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
89 | +# |
90 | +############################################################################# |
91 | +# |
92 | +# This program is free software: you can redistribute it and/or modify |
93 | +# it under the terms of the GNU Affero General Public License as |
94 | +# published by the Free Software Foundation, either version 3 of the |
95 | +# License, or (at your option) any later version. |
96 | +# |
97 | +# This program is distributed in the hope that it will be useful, |
98 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
99 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
100 | +# GNU Affero General Public License for more details. |
101 | +# |
102 | +# You should have received a copy of the GNU Affero General Public License |
103 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
104 | +# |
105 | +############################################################################# |
106 | + |
107 | +{ |
108 | + |
109 | + "name": "CRM Altegra", |
110 | + "version": "0.1", |
111 | + "depends": ["base","sale_altegra"], |
112 | + "author": "Grupo Altegra", |
113 | + "description": """ |
114 | + This module allows you to manage projects that are entered |
115 | + """, |
116 | + "website" : "http://www.grupoaltegra.com", |
117 | + "category": "Custom Modules", |
118 | + |
119 | + "data" :[ |
120 | + 'security/ir.model.access.csv', |
121 | + 'security/groups.xml', |
122 | + 'security/sequence.xml', |
123 | + 'crm_project_view.xml', |
124 | + ], |
125 | + |
126 | + 'demo': [ |
127 | + ], |
128 | + |
129 | + "active": False, |
130 | + "images": [], |
131 | + "installable": True, |
132 | +} |
133 | |
134 | === added file 'crm_altegra/crm_project.py' |
135 | --- crm_altegra/crm_project.py 1970-01-01 00:00:00 +0000 |
136 | +++ crm_altegra/crm_project.py 2013-07-03 23:03:28 +0000 |
137 | @@ -0,0 +1,586 @@ |
138 | +#!/usr/bin/env python |
139 | +#-*- coding:utf-8 -*- |
140 | + |
141 | +############################################################################# |
142 | +# Module Writen to OpenERP, Open Source Management Solution |
143 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
144 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
145 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
146 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
147 | +# |
148 | +############################################################################# |
149 | +# |
150 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
151 | +# |
152 | +############################################################################# |
153 | +# |
154 | +# This program is free software: you can redistribute it and/or modify |
155 | +# it under the terms of the GNU Affero General Public License as |
156 | +# published by the Free Software Foundation, either version 3 of the |
157 | +# License, or (at your option) any later version. |
158 | +# |
159 | +# This program is distributed in the hope that it will be useful, |
160 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
161 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
162 | +# GNU Affero General Public License for more details. |
163 | +# |
164 | +# You should have received a copy of the GNU Affero General Public License |
165 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
166 | +# |
167 | +############################################################################# |
168 | + |
169 | +from osv import osv, fields |
170 | +import datetime |
171 | +import time |
172 | +from tools.translate import _ |
173 | + |
174 | +class crm_project(osv.Model): |
175 | + _name = "crm.project" |
176 | + |
177 | + def _get_task_date(self, cr, uid, ids, field_names=None, arg=False, context=None): |
178 | + """ |
179 | + Metodo para obtener la fecha menor de todas las tareas agregadas al proyecto |
180 | + """ |
181 | + res = {} |
182 | + # Para cada projecto buscamos la fecha menor de todas sus tareas |
183 | + for project_row in self.browse(cr, uid, ids, context): |
184 | + # Si es el campo "task_warning_date" buscamos el campo "warning_date" |
185 | + if field_names == 'task_warning_date': |
186 | + field = "warning_date" |
187 | + else: |
188 | + field = "date_limit" |
189 | + # Query donde obtenemos la fehca menor |
190 | + query = "SELECT "+str(field)+" FROM crm_task WHERE state = 'open' AND type = '"+str(project_row.type)+"' AND project_id = '"+str(project_row.id)+"' order by date_limit ASC limit 1 " |
191 | + cr.execute(query) |
192 | + date_min = cr.fetchall() |
193 | + # Si se tiene una fecha |
194 | + if date_min: |
195 | + # Obtenemos la fecha |
196 | + date_min = date_min[0][0] |
197 | + # Separams la fecha y la hora |
198 | + date_min = date_min.split(' ') |
199 | + # Obtenemos solo la fecha |
200 | + date2 = date_min[0] |
201 | + # Se la asiganamos al campo |
202 | + res[project_row.id] = str(date2) |
203 | + else: |
204 | + res[project_row.id] = False |
205 | + return res |
206 | + |
207 | + _columns = { |
208 | + 'name': fields.char('Nombre',size= 64, help="Nombre del proyecto", required=True, readonly=True, states={'draft': [('readonly', False)]}), |
209 | + 'reference': fields.char('Referencia',size=64, readonly=True,states={'draft': [('readonly', False)]}), |
210 | + 'user_id': fields.many2one('res.users','Responsable', required=True, readonly=True, states={'draft': [('readonly', False)]}, help = "Usuario que debe estar encargado del proyecto"), |
211 | + 'estimated_amount': fields.float('Ingreso estimado', states={'done': [('readonly', True)],'cancel': [('readonly', True)]}, help = "Ingreso que podria dar este proyecto si se gana"), |
212 | + 'date':fields.datetime('Fecha de creación', readonly=True, states={'draft': [('readonly', False)]}, help = "Fecha en que se creo el proyecto "), |
213 | + 'customer_id': fields.many2one('res.partner','Cliente', readonly=True, states={'draft': [('readonly', False)]}, help = "Cliente que se esta trabajando si es que existe en la base"), |
214 | + 'company': fields.char('Empresa', size= 64, readonly=True, required=True, states={'draft': [('readonly', False)]}, help = " Nombre de la empresa que tiene el proyecto"), |
215 | + 'contact_name': fields.char('Nombre de contacto', states={'done': [('readonly', True)],'cancel': [('readonly', True)]}, size=64, help="Nombre con quien se debe contactar para información del proyecto"), |
216 | + 'phone': fields.char('Teléfono', size= 64, states={'done': [('readonly', True)],'cancel': [('readonly', True)]}), |
217 | + 'mail': fields.char('e-mail',size= 64, states={'done': [('readonly', True)],'cancel': [('readonly', True)]}), |
218 | + 'type': fields.selection([ |
219 | + ('opportunity', 'Oportunidad'), |
220 | + ('implementation', 'Implementación') |
221 | + ], 'Tipo', help="Tipo del proyecto.", readonly=True, states={'draft': [('readonly', False)]}), |
222 | + 'state': fields.selection([ |
223 | + ('draft', 'Borrador'), |
224 | + ('opportunity', 'Oportunidad'), |
225 | + ('implementation', 'Implementación'), |
226 | + ('done', 'Finalizado'), |
227 | + ('cancel', 'Cancelada') |
228 | + ], 'Estado', readonly=True, help="Estado en el que se encuentra el proyecto.", select=True), |
229 | + #~ 'task_ids': fields.one2many('crm.task','project_id', 'Tareas', states={'done': [('readonly', True)],'draft': [('readonly', True)],'cancel': [('readonly', True)]}, help="Tareas que deben realizarse para el proyecto"), |
230 | + 'task_opportunity_ids': fields.one2many('crm.task','project_id', 'Tareas Oportunidades', domain=[('type','=','opportunity')], readonly=True,states={'opportunity': [('readonly', False)]}, help="Tareas que deben realizarse para el proyecto"), |
231 | + 'task_implementation_ids': fields.one2many('crm.task','project_id', 'Tareas Implementaciones', domain=[('type','=','implementation')], readonly=True,states={'implementation': [('readonly', False)]}, help="Tareas que deben realizarse para el proyecto"), |
232 | + 'activity_ids': fields.one2many('crm.activities','project_id', 'Actividades', states={'done': [('readonly', True)],'draft': [('readonly', True)],'cancel': [('readonly', True)]}, help="Actividades que deben realizarse para el proyecto"), |
233 | + 'task_min_date':fields.function(_get_task_date,type='date',string="Fecha menor", help="Fecha menor de todos las tareas agregadas al proyecto"), |
234 | + 'task_warning_date':fields.function(_get_task_date,type='date',string="Fecha menor", help="Fecha menor de todos las tareas agregadas al proyecto"), |
235 | + 'change_date':fields.boolean('Cambio Fecha', help ="Indica que se cambio la fecha de alguna tarea"), |
236 | + 'pending_project': fields.boolean('Proyecto Pendiente', states={'done': [('readonly', True)],'draft': [('readonly', True)],'cancel': [('readonly', True)]}, help="Se marca esta opcion para indicar que éste proyecto tendra un seguimiento a largo plazo."), |
237 | + 'UEE': fields.many2one('account.analytic.account', 'UEE', required=True, help="Unidad de negocios a las que pertenece el usuario."), |
238 | + } |
239 | + |
240 | + _defaults = { |
241 | + 'state': 'draft', |
242 | + 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), |
243 | + 'user_id': lambda obj, cr, uid, context: uid, |
244 | + 'type': 'opportunity', |
245 | + 'pending_project': False, |
246 | + 'reference': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'crm.project'), |
247 | + } |
248 | + |
249 | + def acction_done(self, cr, uid, ids, context=None): |
250 | + """ |
251 | + Función para finalizar el proyecto y cambiarlos a estado Done |
252 | + """ |
253 | + for project_row in self.browse(cr, uid ,ids, context): |
254 | + # Validamos que se hayan realizado todas las tareas |
255 | + #~ self.validate_task_done(cr, uid, project_row.task_ids, context) |
256 | + self.validate_task_done(cr, uid, project_row.task_implementation_ids, context) |
257 | + self.write(cr, uid, ids, {'state':'done'}) |
258 | + return True |
259 | + |
260 | + def review_task_change_date(self, cr, uid, ids, context=None): |
261 | + """ |
262 | + función para revisar si a otra tarea se le han cambiado la fecha |
263 | + """ |
264 | + for projetc_row in self.browse(cr, uid, ids, context): |
265 | + change_date = False |
266 | + if projetc_row.type == 'opportunity': |
267 | + for task_row in projetc_row.task_opportunity_ids: |
268 | + if task_row.change_date and task_row.state == 'open': |
269 | + change_date = True |
270 | + break |
271 | + self.write(cr, uid, ids, {'change_date':change_date}) |
272 | + elif projetc_row.type == 'implementation': |
273 | + for task_row in projetc_row.task_implementation_ids: |
274 | + if task_row.change_date and task_row.state == 'open': |
275 | + change_date = True |
276 | + break |
277 | + self.write(cr, uid, [projetc_row.id], {'change_date':change_date}) |
278 | + return True |
279 | + |
280 | + def acction_cancel(self, cr, uid, ids, context=None): |
281 | + """ |
282 | + Función para cancelar los projectos y cambiarlas a estado Cancelodo |
283 | + """ |
284 | + for project_row in self.browse(cr, uid, ids, context): |
285 | + task_opportunity_ids = [task_row.id for task_row in project_row.task_opportunity_ids] |
286 | + task_implementation_ids = [task_row.id for task_row in project_row.task_implementation_ids] |
287 | + activities_ids = [activity_row.id for activity_row in project_row.activity_ids] |
288 | + if task_opportunity_ids: |
289 | + self.pool.get('crm.task').acction_cancel(cr, uid, task_opportunity_ids, context) |
290 | + if task_implementation_ids: |
291 | + self.pool.get('crm.task').acction_cancel(cr, uid, task_implementation_ids, context) |
292 | + #~ task_ids = [task_row.id for task_row in project_row.task_ids] |
293 | + #~ if task_ids: |
294 | + #~ self.pool.get('crm.task').acction_cancel(cr, uid, task_ids, context) |
295 | + self.write(cr, uid, ids, {'state':'cancel'}) |
296 | + return True |
297 | + |
298 | + def on_change_customer_id(self, cr, uid, ids, partner_id, context = None): |
299 | + """ |
300 | + Método para obtener todos los datos del cliente que se esta seleccionando |
301 | + """ |
302 | + val = {} |
303 | + if partner_id: |
304 | + partner_row = self.pool.get('res.partner').browse(cr, uid, partner_id) |
305 | + val.update({'company':partner_row.name}) |
306 | + if partner_row.address: |
307 | + address_row = partner_row.address[0] |
308 | + val.update({'contact_name':address_row.name, 'phone':address_row.phone, 'mail':address_row.email}) |
309 | + return { 'value' : val} |
310 | + |
311 | + def validate_task_done(self, cr, uid, task_rows, context=None): |
312 | + """ |
313 | + Función que evalua si todas las tareas ya fueron terminadas |
314 | + """ |
315 | + done = False |
316 | + if not task_rows: |
317 | + raise osv.except_osv(_('Error !'),_('No tienes asignada ninguna tarea al proyecto.')) |
318 | + for task_row in task_rows: |
319 | + if task_row.state in ('draft','open'): |
320 | + raise osv.except_osv(_('Error !'),_('Aun falta terminar la tarea '+str(task_row.name)+'.')) |
321 | + if task_row.state == 'done': |
322 | + done = True |
323 | + if not done: |
324 | + raise osv.except_osv(_('Error !'),_('No se realizo ninguna tarea.')) |
325 | + return True |
326 | + |
327 | + def acction_confirm(self, cr, uid, ids, context=None): |
328 | + """ |
329 | + Función para confirmar el proyecto y pasarlo a estado oportunidad |
330 | + """ |
331 | + self.write(cr, uid, ids, {'state': 'opportunity','type':'opportunity'}) |
332 | + return True |
333 | + |
334 | + def acction_implementation(self, cr, uid, ids, context=None): |
335 | + """ |
336 | + Función para confirmar el proyecto y pasarlo a estado implementación |
337 | + """ |
338 | + for project_row in self.browse(cr, uid, ids, context): |
339 | + if not project_row.type == 'implementation': |
340 | + self.validate_task_done(cr, uid, project_row.task_opportunity_ids, context) |
341 | + #~ self.validate_task_done(cr, uid, project_row.task_ids, context) |
342 | + self.write(cr, uid, ids, {'state': 'implementation', 'type':'implementation'}) |
343 | + return True |
344 | + |
345 | + def unlink(self, cr, uid, ids, context=None): |
346 | + """ |
347 | + Función que redefine la función unlink para evitar que eliminen proyectos que no esten en estado draft |
348 | + """ |
349 | + for project_row in self.browse(cr, uid, ids, context): |
350 | + task_ids = [] |
351 | + if project_row.state != 'draft': |
352 | + raise osv.except_osv(_('Error !'),_('Solo puedes eliminar proyectos en estao Borrador.')) |
353 | + task_opportunity_ids = [task_row.id for task_row in project_row.task_opportunity_ids] |
354 | + task_implementation_ids = [task_row.id for task_row in project_row.task_implementation_ids] |
355 | + if task_opportunity_ids: |
356 | + self.pool.get('crm.task').unlink(cr, uid, task_opportunity_ids) |
357 | + if task_implementation_ids: |
358 | + self.pool.get('crm.task').unlink(cr, uid, task_implementation_ids) |
359 | + #~ task_ids = [task_row.id for task_row in project_row.task_ids] |
360 | + #~ if task_ids: |
361 | + #~ self.pool.get('crm.task').unlink(cr, uid, task_ids) |
362 | + return super(crm_project, self).unlink(cr, uid, ids, context) |
363 | + |
364 | + def search_task_expired(self, cr, uid, ids=None, context=None): |
365 | + if not context: |
366 | + context = {} |
367 | + self.pool.get('crm.task').search_task_expired(cr, uid, ids=None, context=None) |
368 | + return True |
369 | + |
370 | +class crm_task(osv.Model): |
371 | + _name = "crm.task" |
372 | + |
373 | + _columns = { |
374 | + 'name': fields.char('Nombre Tarea', size=64, required=True,readonly=True, states={'draft': [('readonly', False)]}), |
375 | + 'date_limit': fields.datetime('Fecha Limite', required=True, states={'cancel': [('readonly', True)]}, help="Fecha limite en la cual debe realizarse la tarea"), |
376 | + 'user_id': fields.many2one('res.users','Responsable', required=True, select=True,readonly=True, states={'draft': [('readonly', False)]}), |
377 | + 'note': fields.text('Notas',states={'cancel': [('readonly', True)]}), |
378 | + 'project_id': fields.many2one('crm.project', 'Proyecto', domain="[('state','in',('opportunity','implementation'))]", required = True, select=True,readonly=True, states={'draft': [('readonly', False)]}), |
379 | + 'type': fields.selection([ |
380 | + ('opportunity', 'Oportunidad'), |
381 | + ('implementation', 'Implementación') |
382 | + ], 'Tipo', help="Tipo de la tarea.", readonly=True, states={'draft': [('readonly', False)]},select=True), |
383 | + 'state': fields.selection([ |
384 | + ('draft', 'Borrador'), |
385 | + ('open', 'Abierta'), |
386 | + ('done', 'Finalizado'), |
387 | + ('cancel', 'Cancelada') |
388 | + ], 'Estado', readonly=True, help="Estado en el que se encuentra la tarea.", select=True), |
389 | + 'warning_date': fields.date('Fecha para aviso', help="Fecha en que se avisara que la tarea esta por vencerse"), |
390 | + 'change_date':fields.boolean('Cambio Fecha', readonly=True, help ="Indica que se cambio la fecha de la tarea"), |
391 | + 'activity_id': fields.many2one('crm.activities','Actividad', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Actividad a la que pertenece esta tarea"), |
392 | + } |
393 | + |
394 | + _defaults = { |
395 | + 'state': 'draft', |
396 | + 'change_date': False, |
397 | + 'user_id': lambda obj, cr, uid, context: uid, |
398 | + 'type': 'opportunity', |
399 | + } |
400 | + |
401 | + def onchange_activity(self, cr, uid, ids, activity_id,context=None): |
402 | + """Función para ontener el proyecto al que pertenece el sprint seleccionado""" |
403 | + val = {} |
404 | + if not activity_id: |
405 | + val['project_id'] = False |
406 | + return {'value': val} |
407 | + # Obtenemos el registro de la actividad |
408 | + activity_row = self.pool.get('crm.activities').browse(cr, uid, activity_id) |
409 | + # Asignamos al proyecto que tiene asigando |
410 | + val['project_id'] = activity_row.project_id.id |
411 | + return {'value': val} |
412 | + |
413 | + def get_email_vals(self, cr, uid, task_ids, subject, message, context=None): |
414 | + """ |
415 | + Funcion para obtener los datos para crear el correo |
416 | + """ |
417 | + list_vals = [] |
418 | + notifications_obj = self.pool.get('email.notifications') |
419 | + user_obj = self.pool.get('res.users') |
420 | + # Buscamos las notificaciones |
421 | + notifications_ids = notifications_obj.search(cr, uid, [], limit = 1) |
422 | + if not notifications_ids: |
423 | + raise osv.except_osv(_('Error'), _("No existen correos de destinatario en las notificaciones!")) |
424 | + notifications_row = notifications_obj.browse(cr,uid, notifications_ids, context)[0] |
425 | + # Validamos si existen correos para productos recibidos |
426 | + if not notifications_row.authorization_discount: |
427 | + raise osv.except_osv(_('Error'), _("No existen correos de destinatario !")) |
428 | + for task_row in self.browse(cr, uid, task_ids, context): |
429 | + # Validamos que el usuario tenga correo |
430 | + if not task_row.user_id.user_email: |
431 | + raise osv.except_osv(_('Error'), _("No tiene correo el usuario "+str(task_row.user_id.name)+" !")) |
432 | + date = str(task_row.date_limit) |
433 | + task_name = task_row.name.encode('utf-8') |
434 | + project_name = task_row.project_id.name.encode('utf-8') |
435 | + # concatenamos el asunto y el mensaje con los datos de la tarea |
436 | + subject_new = subject % (str(task_name), date) |
437 | + message_new = message % (str(task_name),str(project_name),date,task_row.user_id.name.encode('utf-8')) |
438 | + # Obtenemos los destinatarios que es el del responsable de la tarea y al director |
439 | + email_to = notifications_row.authorization_discount.encode('utf-8') +","+task_row.user_id.user_email.encode('utf-8') |
440 | + # Obtenemos todos los valores para crear el correo |
441 | + vals = { |
442 | + 'email_from': "moyblanco22@gmail.com", |
443 | + 'email_to': email_to, |
444 | + 'subject': subject_new, |
445 | + 'body_text' :message_new, |
446 | + } |
447 | + list_vals.append(vals) |
448 | + return list_vals |
449 | + |
450 | + def search_task_expired(self, cr, uid, ids=None, context=None): |
451 | + if not context: |
452 | + context = {} |
453 | + # Obtenemos la fecha de hoy |
454 | + today = datetime.date.today() |
455 | + # Obtenemos las tareas que esten abiertas y que su fecha de expiracion es |
456 | + expiring_task_ids = self.search(cr, uid, [('state','=','open'),('warning_date','=',today)]) |
457 | + # Obtenemos las tareas que estan abiertas pero la fecha limite de realizacion esta pasada |
458 | + expired_task_ids = self.search(cr, uid, [('state','=','open'),('date_limit','<',str(today))]) |
459 | + # Creamos los correos para las tareas que apenas expiraran |
460 | + if expiring_task_ids: |
461 | + # Creamos el asunto y el mensaje |
462 | + subject = "La tarea '%s' esta por expirar el dia %s " |
463 | + msj = "La tarea '%s' del proyecto '%s' tiene fecha limite de realizacion el dia %s \n Responsable: %s" |
464 | + # Obtenemos los diccionarios para las tareas que van a expirar |
465 | + vals_expiring_task_ids = self.get_email_vals(cr, uid, expiring_task_ids, subject, msj.encode('utf-8'), context) |
466 | + # Enviamos los correos de las tareas que apenas van a expirar |
467 | + self.send_email(cr, uid, ids, vals_expiring_task_ids, context) |
468 | + # Creamos los correos para las tareas que ya estan expiradass |
469 | + if expired_task_ids: |
470 | + # Creamos el asunto y mensaje |
471 | + subject = "La tarea '%s' ya expiro el dia %s" |
472 | + msj = "La tarea '%s' del proyecto '%s' tiene fecha limite de realizacion el dia %s \n Responsable: %s" |
473 | + # Obtenemos los diccionarios para las tareas que van a expirar |
474 | + vals_expired_task_ids = self.get_email_vals(cr, uid, expired_task_ids, subject, msj.encode('utf-8'), context) |
475 | + # Enviamos correos con las tareas ya expiradas |
476 | + self.send_email(cr, uid, ids, vals_expired_task_ids, context) |
477 | + return True |
478 | + |
479 | + def send_email(self, cr, uid, ids, list_vals, context=None): |
480 | + """ |
481 | + Método que envia correo por el picking que se recibio |
482 | + ids: ids de task_row |
483 | + vals: diccionario con todos los elementos que se necesitan para crear el correo "email_from, email_to, subject, body_text" |
484 | + """ |
485 | + if not context: |
486 | + context = {} |
487 | + # Objetos |
488 | + mail_message_obj = self.pool.get('mail.message') |
489 | + for vals in list_vals: |
490 | + # Creamos el correo |
491 | + msg_id = mail_message_obj.schedule_with_attach(cr, uid, vals['email_from'], [vals['email_to']], vals['subject'], vals['body_text'], |
492 | + model='mail.campaign', email_cc=False, email_bcc=False, reply_to=False, |
493 | + attachments={}, references=False, res_id=1, |
494 | + subtype='html', headers=False, context=context) |
495 | + # Enviamos el Correo |
496 | + mail_message_obj.send(cr,uid,[msg_id],context) |
497 | + return True |
498 | + |
499 | + def acction_confirm(self, cr, uid, ids, context=None): |
500 | + """ |
501 | + Funcion para aprobar las tareas y cambiarlas a estado aprobada |
502 | + """ |
503 | + self.write(cr, uid, ids, {'state':'open'}) |
504 | + activities_ids = [task_row.activity_id.id for task_row in self.browse(cr, uid, ids, context)] |
505 | + if activities_ids: |
506 | + self.pool.get('crm.activities').update_state_activities(cr, uid, activities_ids, context) |
507 | + return True |
508 | + |
509 | + def acction_done(self, cr, uid, ids, context=None): |
510 | + """ |
511 | + Funcion para Terminar las tareas y cambiarlas a estado Finalizado |
512 | + """ |
513 | + activities_ids = [] |
514 | + # Para cada tarea que se quiere finalizar se obtiene su actividad y se revisa si no tiene revisiones pendientes |
515 | + for task_row in self.browse(cr, uid, ids, context): |
516 | + activities_ids.append(task_row.activity_id.id) |
517 | + # Si aun no se revisa esa tarea se marca un error |
518 | + if task_row.change_date: |
519 | + raise osv.except_osv(_('Error !'),_('No se puede finalizar una tarea que no se ha revisado.')) |
520 | + # Se actualiza el estado de las tareas a realizado si todas estan bien |
521 | + self.write(cr, uid, ids, {'state':'done'}) |
522 | + # Se actualizan las actividades de las tareas que se acaban de finalizar |
523 | + if activities_ids: |
524 | + self.pool.get('crm.activities').update_state_activities(cr, uid, activities_ids, context) |
525 | + return True |
526 | + |
527 | + def acction_cancel(self, cr, uid, ids, context=None): |
528 | + """ |
529 | + Funcion para cancelar las tareas y cambiarlas a estado Finalizado |
530 | + """ |
531 | + project_ids = [] |
532 | + activities_ids = [] |
533 | + # Se obtienen los proyectos relacionados a las tareas a cancelar |
534 | + for task_row in self.browse(cr, uid, ids, context): |
535 | + if task_row.change_date: |
536 | + project_ids.append(task_row.project_id.id) |
537 | + activities_ids.append(task_row.activity_id.id) |
538 | + # Se actualiza el proyecto a revisado puesto que se cancelo la tarea que se cambio la fecha |
539 | + if project_ids: |
540 | + # Se actualiza el proyecto indicando que ya se reviso la tarea con fecha cambiada |
541 | + self.pool.get('crm.project').review_task_change_date(cr, uid, project_ids, context) |
542 | + self.write(cr, uid, ids, {'state':'cancel'}) |
543 | + if activities_ids: |
544 | + self.pool.get('crm.activities').update_state_activities(cr, uid, activities_ids, context) |
545 | + return True |
546 | + |
547 | + def action_review(self, cr, uid, ids, context=None): |
548 | + """ |
549 | + Funcion para indicar que esta tarea ya fue revisada |
550 | + """ |
551 | + project_ids = [] |
552 | + # Se buscan los proyectos relacionados con la tarea |
553 | + for task_row in self.browse(cr, uid, ids, context): |
554 | + project_ids.append(task_row.project_id.id) |
555 | + # Se actualiza la tarea indicando que ya se reviso |
556 | + self.write(cr, uid, ids, {'change_date':False}) |
557 | + if project_ids: |
558 | + # Se actualiza el proyecto indicando que ya se reviso |
559 | + self.pool.get('crm.project').review_task_change_date(cr, uid, project_ids, context) |
560 | + return True |
561 | + |
562 | + def get_warning_date(self, cr, uid, vals, context=None): |
563 | + """ |
564 | + Función que obtiene la fecha para aviso si es que se agrega la fecha limite |
565 | + """ |
566 | + if vals.get('date_limit'): |
567 | + # Obtenemos solo la fecha sin tiempo |
568 | + date = vals.get('date_limit').split(' ') |
569 | + # La convertimos a datetime |
570 | + date = datetime.datetime.strptime(date[0] ,'%Y-%m-%d') |
571 | + warning_date = date - datetime.timedelta(days = 1) |
572 | + # Actualizamos la fecha para aviso |
573 | + vals.update({'warning_date':warning_date}) |
574 | + if context.get('write'): |
575 | + vals.update({'change_date': True}) |
576 | + return vals |
577 | + |
578 | + def create(self, cr, uid, vals, context=None): |
579 | + """ |
580 | + Función que redefine el metodo create para obtener la fecha limite y las fechas para dar avisos |
581 | + """ |
582 | + vals = self.get_warning_date(cr, uid, vals, context) |
583 | + if vals.get('activity_id'): |
584 | + # Obtenemos el registro del spint |
585 | + activity_row = self.pool.get('crm.activities').browse(cr, uid, vals.get('activity_id')) |
586 | + # Asignamos al proyecto que tiene asigando |
587 | + vals.update({'project_id':activity_row.project_id.id,'type':activity_row.project_id.type}) |
588 | + vals.update({'change_date': False}) |
589 | + # Creamos la nueva tarea |
590 | + task_id = super(crm_task, self).create(cr, uid, vals, context) |
591 | + return task_id |
592 | + |
593 | + def write(self, cr, uid, ids, vals, context=None): |
594 | + """ |
595 | + Función que redefine el metodo write para saber si se esta modificando la fecha limite |
596 | + """ |
597 | + if context is None: |
598 | + context = {} |
599 | + # Actualizamos el context por si se actualiza la fech alimite se actualize tambien el campo change_date |
600 | + context.update({'write':True}) |
601 | + # Obtenemos la fecha de aviso |
602 | + vals = self.get_warning_date(cr, uid, vals, context) |
603 | + # Realizamos el write de la funcion original |
604 | + res = super(crm_task, self).write(cr, uid, ids, vals, context) |
605 | + project_ids = [] |
606 | + task_ids = [] |
607 | + # Obtenemos los ids de los projectos |
608 | + for task_row in self.browse(cr, uid, ids): |
609 | + if task_row.state == 'draft' and task_row.change_date: |
610 | + task_ids.append(task_row.id) |
611 | + elif task_row.change_date: |
612 | + project_ids.append(task_row.project_id.id) |
613 | + # se actualiza el proyecto indicando que se cambio la fecha |
614 | + if project_ids: |
615 | + self.pool.get('crm.project').write(cr, uid, project_ids, {'change_date':True}) |
616 | + if task_ids: |
617 | + self.write(cr, uid, task_ids, {'change_date':False}) |
618 | + return res |
619 | + |
620 | + def unlink(self, cr, uid, ids, context=None): |
621 | + """ |
622 | + Función que redefine la función unlink para evitar que eliminen tarea que no esten en estado draft |
623 | + """ |
624 | + activities_ids = [] |
625 | + for task_row in self.browse(cr, uid, ids, context): |
626 | + if task_row.state != 'draft': |
627 | + raise osv.except_osv(_('Error !'),_('Solo puedes eliminar tareas en estao Borrador.')) |
628 | + activities_ids.append(task_row.activity_id.id) |
629 | + res = super(crm_task, self).unlink(cr, uid, ids, context) |
630 | + if activities_ids: |
631 | + self.pool.get('crm.activities').update_state_activities(cr, uid, activities_ids, context) |
632 | + return res |
633 | + |
634 | + |
635 | +class crm_activities(osv.Model): |
636 | + |
637 | + _name = "crm.activities" |
638 | + |
639 | + _columns = { |
640 | + 'name': fields.char('Nombre', size=64, required=True,readonly=True, states={'draft': [('readonly', False)]}), |
641 | + 'task_ids': fields.one2many('crm.task', 'activity_id', 'Tareas', readonly=True, states={'open': [('readonly', False)]}, help="Tareas de la actividad"), |
642 | + 'project_id': fields.many2one('crm.project', 'Proyecto', required=True, readonly=True, states={'draft': [('readonly', False)]}, domain="[('state','in',('opportunity','implementation'))]", help="Proyecto al que pertenece la actividad"), |
643 | + 'user_id': fields.many2one('res.users','Responsable', required=True, readonly=True, states={'draft': [('readonly', False)]}, help = "Usuario que debe estar encargado de la actividad"), |
644 | + 'type': fields.selection([ |
645 | + ('opportunity', 'Oportunidad'), |
646 | + ('implementation', 'Implementación') |
647 | + ], 'Tipo', help="Tipo de la actividad.", readonly=True), |
648 | + 'state': fields.selection([ |
649 | + ('draft', 'Borrador'), |
650 | + ('open', 'Abierta'), |
651 | + ('done', 'Finalizado'), |
652 | + ('cancel', 'Cancelada') |
653 | + ], 'Estado', readonly=True, help="Estado en el que se encuentra la actividad.", select=True), |
654 | + 'date_limit': fields.date('Fecha limite', readonly=True, states={'draft': [('readonly', False)]}, help=" Fecha limite en que se debe cumplir la actividad"), |
655 | + } |
656 | + |
657 | + _defaults = { |
658 | + 'state': 'draft', |
659 | + 'user_id': lambda obj, cr, uid, context: uid, |
660 | + } |
661 | + |
662 | + def create(self, cr, uid, vals, context=None): |
663 | + """ |
664 | + Función para actualizar el tipo de la actividad segun el tipo del proyecto seleccionado |
665 | + """ |
666 | + if vals.get('project_id'): |
667 | + project_row = self.pool.get('crm.project').browse(cr, uid, vals.get('project_id')) |
668 | + vals.update({'type':project_row.type}) |
669 | + return super(crm_activities, self).create(cr, uid, vals, context) |
670 | + |
671 | + def action_confirm_activity(self, cr, uid, ids, context=None): |
672 | + """ |
673 | + Función para cambiar el estado de la actividd a confirmada |
674 | + """ |
675 | + self.write(cr, uid, ids, {'state':'open'}) |
676 | + return True |
677 | + |
678 | + def unlink(self, cr, uid, ids, context=None): |
679 | + """ |
680 | + Se redefine el método unlink para no permitir eliminar actividades que no esten en estado draft |
681 | + """ |
682 | + for activity_row in self.browse(cr, uid, ids): |
683 | + if activity_row.state != 'draft': |
684 | + raise osv.except_osv(_('Error !'),_('No se puede eliminar una actividad que no esta en estado draft.')) |
685 | + super(crm_activities, self).unlink(cr, uid, ids, context) |
686 | + return True |
687 | + |
688 | + def update_state_activities(self, cr, uid, ids, context=None): |
689 | + """ |
690 | + Funcion para cambiar el estado de la actividad en base a sus tareas |
691 | + """ |
692 | + # Se recorren todas las actividades |
693 | + for activity_row in self.browse(cr, uid, ids, context): |
694 | + done = 0 |
695 | + cancel = 0 |
696 | + state =False |
697 | + # Se recorren todas las tareas de la actividad para revisar sus estados si tienen tareas |
698 | + if activity_row.task_ids: |
699 | + for task_row in activity_row.task_ids: |
700 | + # Si tiene alguntatarea en estado draft u open se marca la actividad como abierta |
701 | + if task_row.state == 'draft' or task_row.state == 'open': |
702 | + state = 'open' |
703 | + break |
704 | + # Si tiene tareas en estado done se aumenta el contador |
705 | + elif task_row.state == 'done': |
706 | + done += 1 |
707 | + # Si tiene tareas en estado cancel se aumenta el contador |
708 | + elif task_row.state == 'cancel': |
709 | + cancel += 1 |
710 | + # Si no se tiene estado aun comparamos los contadores de done y cancel |
711 | + if not state: |
712 | + # si existen cantidades en done y cancel o si el contador done es igual al total de actividades se pone en estado done |
713 | + if (done and cancel) or done == len(activity_row.task_ids): |
714 | + state = 'done' |
715 | + # Si el contador de cancel es igual al total de tareas el estado es cancel |
716 | + elif cancel == len(activity_row.task_ids): |
717 | + state = 'cancel' |
718 | + else: |
719 | + state='draft' |
720 | + self.write(cr, uid, [activity_row.id], {'state':state}) |
721 | + return True |
722 | + |
723 | + |
724 | |
725 | === added file 'crm_altegra/crm_project_view.xml' |
726 | --- crm_altegra/crm_project_view.xml 1970-01-01 00:00:00 +0000 |
727 | +++ crm_altegra/crm_project_view.xml 2013-07-03 23:03:28 +0000 |
728 | @@ -0,0 +1,442 @@ |
729 | +<?xml version="1.0" encoding="utf-8"?> |
730 | +<openerp> |
731 | + <data> |
732 | + <!-- crm_project_main_menu --> |
733 | + <menuitem icon="terp-stock" id="crm_project_main_menu" name="CRM" sequence="0" groups="crm_altegra.group_crm_user" |
734 | + web_icon="images/icon.png" |
735 | + web_icon_hover="images/icon.png"/> |
736 | + |
737 | + <!-- crm_project_menu --> |
738 | + <menuitem id="crm_project_menu" name="CRM" parent="crm_project_main_menu" sequence="1"/> |
739 | + |
740 | + <!-- crm_task_menu --> |
741 | + <menuitem id="crm_activities_menu" name="Actividades" parent="crm_project_main_menu" sequence="1"/> |
742 | + |
743 | + <!-- crm_task_menu --> |
744 | + <menuitem id="crm_task_menu" name="Tareas" parent="crm_project_main_menu" sequence="2"/> |
745 | + |
746 | + <record id="view_crm_project_filter" model="ir.ui.view"> |
747 | + <field name="name">view.crm.project.filter</field> |
748 | + <field name="model">crm.project</field> |
749 | + <field name="type">search</field> |
750 | + <field name="arch" type="xml"> |
751 | + <search string="Buscar"> |
752 | + <group> |
753 | + <filter icon="terp-check" name="pending_project_false" string="Proyectos Actuales" domain="[('pending_project','=',False),('state','in',('opportunity','implementation','draft'))]" help="Proyectos que estan marcados como pendientes"/> |
754 | + <filter icon="terp-gtk-media-pause" name="pending_project_true" string="Proyectos Pendientes" domain="[('pending_project','=',True),('state','in',('opportunity','implementation','draft'))]" help="Proyectos que estan marcados como pendientes"/> |
755 | + </group> |
756 | + <field name="name" filter_domain="[('name','ilike',self)]" string="Proyecto"/> |
757 | + <field name="company" filter_domain="[('company','ilike',self)]"/> |
758 | + <field name="user_id"> |
759 | + <filter domain="[('user_id','=',uid)]" help="Encargado" icon="terp-personal"/> |
760 | + </field> |
761 | + <field name="state"/> |
762 | + <field name="UEE"/> |
763 | + <newline/> |
764 | + <group expand="0" string="Group By..." groups="base.group_extended"> |
765 | + <filter string="Responsable" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> |
766 | + <filter string="Cliente" icon="terp-personal" domain="[]" context="{'group_by':'company'}"/> |
767 | + <separator orientation="vertical"/> |
768 | + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> |
769 | + </group> |
770 | + </search> |
771 | + </field> |
772 | + </record> |
773 | + |
774 | + <!-- view_crm_project_tree --> |
775 | + <record id="view_crm_project_tree" model="ir.ui.view"> |
776 | + <field name="name">view.crm.project.tree</field> |
777 | + <field name="model">crm.project</field> |
778 | + <field name="type">tree</field> |
779 | + <field name="priority" eval="17"/> |
780 | + <field name="arch" type="xml"> |
781 | + <tree string="Proyectos" colors="black: state == 'done';grey: state == 'cancel';blue: change_date == True;red: task_min_date < current_date and state in ('implementation','opportunity');orange: task_warning_date <= current_date and state in ('implementation','opportunity')"> |
782 | + <field name="reference"/> |
783 | + <field name="name"/> |
784 | + <field name="company"/> |
785 | + <field name="user_id"/> |
786 | + <field name="estimated_amount" sum="Sum amount"/> |
787 | + <field name="state"/> |
788 | + <field name="task_min_date" invisible="1"/> |
789 | + <field name="task_warning_date" invisible="1"/> |
790 | + <field name="change_date" invisible="1"/> |
791 | + <field name="pending_project" invisible="1"/> |
792 | + <field name="UEE" invisible="1"/> |
793 | + </tree> |
794 | + </field> |
795 | + </record> |
796 | + |
797 | + <!-- view_crm_project_form --> |
798 | + <record id="view_crm_project_form" model="ir.ui.view"> |
799 | + <field name="name">view.crm.project.form</field> |
800 | + <field name="model">crm.project</field> |
801 | + <field name="type">form</field> |
802 | + <field name="priority" eval="17"/> |
803 | + <field name="arch" type="xml"> |
804 | + <form string="Proyecto" > |
805 | + <group colspan="4" col = "8"> |
806 | + <field name="name" colspan="6"/> |
807 | + <field name="reference" invisible="1"/> |
808 | + <field name="pending_project" colspan="2"/> |
809 | + <field name="user_id" colspan="2"/> |
810 | + <field name="UEE" colspan="4"/> |
811 | + <field name="date" colspan="2"/> |
812 | + <field name="estimated_amount" colspan="2"/> |
813 | + <field name="type" invisible="1"/> |
814 | + </group> |
815 | + <group string ="Cliente" colspan="4"> |
816 | + <field name="customer_id" on_change="on_change_customer_id(customer_id)"/> |
817 | + <field name="company"/> |
818 | + <field name="contact_name"/> |
819 | + <field name="phone"/> |
820 | + <field name="mail"/> |
821 | + </group> |
822 | + <notebook colspan="4"> |
823 | + <page string="Actividades"> |
824 | + <field name="activity_ids" nolabel="1"> |
825 | + <form string="Actividad" > |
826 | + <group colspan="4" col = "6"> |
827 | + <field name="name" /> |
828 | + <field name="date_limit"/> |
829 | + </group> |
830 | + <group string="Tareas" colspan="4"> |
831 | + <field name="task_ids" nolabel="1"/> |
832 | + </group> |
833 | + <group> |
834 | + <field name="state" widget="statusbar"/> |
835 | + </group> |
836 | + <group> |
837 | + <button name="action_confirm_activity" type="object" states="draft" string="Aprobar" icon="gtk-go-forward" /> |
838 | + </group> |
839 | + </form> |
840 | + </field> |
841 | + </page> |
842 | + <page string="Tareas Oportunidad"> |
843 | + <group colspan="4"> |
844 | + <field name="task_opportunity_ids" nolabel="1"> |
845 | + <form string="Tarea" > |
846 | + <group colspan="4" col = "6"> |
847 | + <field name="name" colspan="6"/> |
848 | + <field name="user_id"/> |
849 | + <field name="date_limit"/> |
850 | + <field name="change_date" invisible="1"/> |
851 | + <field name="activity_id" domain="[('project_id','=',parent.id),('state','=','open')]"/> |
852 | + </group> |
853 | + <group string ="Notas" colspan="4"> |
854 | + <field name="note" nolabel="1"/> |
855 | + </group> |
856 | + <group> |
857 | + <field name="state" widget="statusbar"/> |
858 | + </group> |
859 | + <group> |
860 | + <button name="action_review" type="object" string="Revisado" icon="terp-stock_zoom" attrs="{'invisible':['|',('change_date','=',False),('state','in',('draft','cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
861 | + <button name="acction_confirm" type="object" states="draft" string="Aprobar" icon="STOCK_NEW" /> |
862 | + <button name="acction_done" type="object" states="open" string="Finalizada" icon="terp-camera_test" /> |
863 | + <button name="acction_cancel" type="object" string="Cancelar" icon="gtk-cancel" attrs="{'invisible':['|',('state','in',('cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
864 | + </group> |
865 | + </form> |
866 | + </field> |
867 | + </group> |
868 | + </page> |
869 | + <page string="Tareas implementacion"> |
870 | + <group colspan="4"> |
871 | + <field name="task_implementation_ids" nolabel="1"> |
872 | + <form string="Tarea" > |
873 | + <group colspan="4" col = "6"> |
874 | + <field name="name" colspan="6"/> |
875 | + <field name="user_id"/> |
876 | + <field name="date_limit"/> |
877 | + <field name="change_date" invisible="1"/> |
878 | + <field name="activity_id" domain="[('project_id','=',parent.id),('state','=','open')]"/> |
879 | + </group> |
880 | + <group string ="Notas" colspan="4"> |
881 | + <field name="note" nolabel="1"/> |
882 | + </group> |
883 | + <group> |
884 | + <field name="state" widget="statusbar"/> |
885 | + </group> |
886 | + <group> |
887 | + <button name="action_review" type="object" string="Revisado" icon="terp-stock_zoom" attrs="{'invisible':['|',('change_date','=',False),('state','in',('draft','cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
888 | + <button name="acction_confirm" type="object" states="draft" string="Aprobar" icon="STOCK_NEW" /> |
889 | + <button name="acction_done" type="object" states="open" string="Finalizada" icon="terp-camera_test" /> |
890 | + <button name="acction_cancel" type="object" string="Cancelar" icon="gtk-cancel" attrs="{'invisible':['|',('state','in',('cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
891 | + </group> |
892 | + </form> |
893 | + </field> |
894 | + </group> |
895 | + </page> |
896 | + </notebook> |
897 | + <group col="16"> |
898 | + <group> |
899 | + <field name="state" widget="statusbar"/> |
900 | + </group> |
901 | + <group col="10"> |
902 | +<!-- |
903 | + <button name="search_task_expired" type="object" string="Correos" icon="gtk-go-forward" groups="crm_altegra.group_crm_admin"/> |
904 | +--> |
905 | + <button name="acction_confirm" type="object" string="Oportunidad" icon="gtk-go-forward" attrs="{'invisible':['|',('state','!=','draft'),('type','=','implementation')]}"/> |
906 | + <button name="acction_implementation" type="object" string="Implementación" icon="gtk-go-forward" attrs="{'invisible':['|',('state','!=','draft'),('type','=','opportunity')]}"/> |
907 | + <button name="acction_implementation" states ="opportunity" type="object" string="Implementación" icon="gtk-go-forward" /> |
908 | + <button name="acction_done" states ="implementation" type="object" string="Finalizar" icon="gtk-go-forward" /> |
909 | + <button name="acction_cancel" type="object" string="Cancelar" icon="gtk-cancel" groups="crm_altegra.group_crm_admin" attrs="{'invisible':[('state','in',('cancel','done'))]}"/> |
910 | + </group> |
911 | + </group> |
912 | + </form> |
913 | + </field> |
914 | + </record> |
915 | + |
916 | + <!-- crm_project_opportunity_action --> |
917 | + <record id="crm_project_opportunity_action" model="ir.actions.act_window"> |
918 | + <field name="name">Proyectos Oportunidades</field> |
919 | + <field name="res_model">crm.project</field> |
920 | + <field name="view_type">form</field> |
921 | + <field name="view_mode">tree,form</field> |
922 | + <field name="context">{'default_type': 'opportunity',"search_default_pending_project_false":1}</field> |
923 | + <field name="domain">[('type','=','opportunity')]</field> |
924 | + <field name="view_id" ref="view_crm_project_tree"/> |
925 | + </record> |
926 | + |
927 | + <record id="crm_project_implementation_action" model="ir.actions.act_window"> |
928 | + <field name="name">Proyectos Implementación</field> |
929 | + <field name="res_model">crm.project</field> |
930 | + <field name="view_type">form</field> |
931 | + <field name="view_mode">tree,form</field> |
932 | + <field name="context">{'default_type': 'implementation',"search_default_pending_project_false":1}</field> |
933 | + <field name="domain">[('type','=','implementation')]</field> |
934 | + <field name="search_view_id" ref="view_crm_project_filter"/> |
935 | + <field name="view_id" ref="view_crm_project_tree"/> |
936 | + </record> |
937 | + |
938 | + <!-- crm_project_menu_action --> |
939 | + <menuitem id="crm_project_opportunity_menu_action" |
940 | + parent="crm_project_menu" |
941 | + name="Oportunidades" |
942 | + action="crm_project_opportunity_action" |
943 | + sequence="1"/> |
944 | + |
945 | + <menuitem id="crm_project_implementation_menu_action" |
946 | + parent="crm_project_menu" |
947 | + name="Implementación" |
948 | + action="crm_project_implementation_action" |
949 | + sequence="1"/> |
950 | + |
951 | + <record id="view_crm_task_filter" model="ir.ui.view"> |
952 | + <field name="name">view.crm.task.filter</field> |
953 | + <field name="model">crm.task</field> |
954 | + <field name="type">search</field> |
955 | + <field name="arch" type="xml"> |
956 | + <search string="Buscar"> |
957 | + <field name="name" filter_domain="[('name','ilike',self)]" string="Tarea"/> |
958 | + <field name="project_id"/> |
959 | + <field name="user_id"> |
960 | + <filter domain="[('user_id','=',uid)]" help="Encargado" icon="terp-personal"/> |
961 | + </field> |
962 | + <field name="type"/> |
963 | + <field name="state"/> |
964 | + <newline/> |
965 | + <group expand="0" string="Group By..." groups="base.group_extended"> |
966 | + <filter string="Proyecto" icon="gtk-open" domain="[]" context="{'group_by':'project_id'}"/> |
967 | + <filter string="Actividad" icon="gtk-find-and-replace" domain="[]" context="{'group_by':'activity_id'}"/> |
968 | + <filter string="Responsable" icon="terp-personal+" domain="[]" context="{'group_by':'user_id'}"/> |
969 | + <separator orientation="vertical"/> |
970 | + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> |
971 | + </group> |
972 | + </search> |
973 | + </field> |
974 | + </record> |
975 | + |
976 | + <!-- view_crm_task_tree --> |
977 | + <record id="view_crm_task_tree" model="ir.ui.view"> |
978 | + <field name="name">view.crm.task.tree</field> |
979 | + <field name="model">crm.task</field> |
980 | + <field name="type">tree</field> |
981 | + <field name="priority" eval="17"/> |
982 | + <field name="arch" type="xml"> |
983 | + <tree string="Tareas" colors="black: state == 'done';grey: state == 'cancel';blue: change_date == True;red: date_limit <= current_date and state == 'open';orange: warning_date <= current_date and state == 'open';green: date_limit > current_date and state == 'open'" > |
984 | + <field name="name"/> |
985 | + <field name="project_id"/> |
986 | + <field name="activity_id"/> |
987 | + <field name="user_id"/> |
988 | + <field name="date_limit"/> |
989 | + <field name="type" invisible="1"/> |
990 | + <field name="warning_date" invisible="1"/> |
991 | + <field name="change_date" invisible="1"/> |
992 | + <field name="state"/> |
993 | + <field name="type" invisible="1"/> |
994 | + <button name="acction_confirm" type="object" states="draft" string="Aprobar" icon="STOCK_NEW" /> |
995 | + <button name="acction_done" type="object" states="open" string="Finalizada" icon="terp-camera_test" /> |
996 | + </tree> |
997 | + </field> |
998 | + </record> |
999 | + |
1000 | + |
1001 | + <!-- view_crm_task_form --> |
1002 | + <record id="view_crm_task_form" model="ir.ui.view"> |
1003 | + <field name="name">view.crm.task.form</field> |
1004 | + <field name="model">crm.task</field> |
1005 | + <field name="type">form</field> |
1006 | + <field name="priority" eval="17"/> |
1007 | + <field name="arch" type="xml"> |
1008 | + <form string="Tarea" > |
1009 | + <group colspan="4" col = "6"> |
1010 | + <field name="name" colspan="6"/> |
1011 | + <field name="user_id"/> |
1012 | + <field name="date_limit"/> |
1013 | + </group> |
1014 | + <notebook colspan="4"> |
1015 | + <page string ="Notas"> |
1016 | + <group colspan="4"> |
1017 | + <field name="note" nolabel="1"/> |
1018 | + </group> |
1019 | + </page> |
1020 | + <page string="Otra información"> |
1021 | + <field name="project_id" /> |
1022 | + <field name="activity_id" domain="[('project_id','=',project_id),('state','=','open')]"/> |
1023 | + <field name="type" readonly="1"/> |
1024 | + <field name="change_date" readonly="1"/> |
1025 | + </page> |
1026 | + </notebook> |
1027 | + <group> |
1028 | + <field name="state" widget="statusbar"/> |
1029 | + </group> |
1030 | + <group> |
1031 | + <button name="action_review" type="object" string="Revisado" icon="terp-stock_zoom" attrs="{'invisible':['|',('change_date','=',False),('state','in',('draft','cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
1032 | + <button name="acction_confirm" type="object" states="draft" string="Aprobar" icon="STOCK_NEW" /> |
1033 | + <button name="acction_done" type="object" states="open" string="Finalizada" icon="terp-camera_test" /> |
1034 | + <button name="acction_cancel" type="object" string="Cancelar" icon="gtk-cancel" attrs="{'invisible':['|',('state','in',('cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
1035 | + </group> |
1036 | + </form> |
1037 | + </field> |
1038 | + </record> |
1039 | + |
1040 | + <record id="crm_task_action" model="ir.actions.act_window"> |
1041 | + <field name="name">Tareas</field> |
1042 | + <field name="res_model">crm.task</field> |
1043 | + <field name="view_type">form</field> |
1044 | + <field name="view_mode">tree,form</field> |
1045 | + <field name="search_view_id" ref="view_crm_task_filter"/> |
1046 | + <field name="view_id" ref="view_crm_task_tree"/> |
1047 | + </record> |
1048 | + |
1049 | + <!-- crm_project_menu_action --> |
1050 | + <menuitem id="crm_task_menu_action" |
1051 | + parent="crm_task_menu" |
1052 | + name="Tareas" |
1053 | + action="crm_task_action" |
1054 | + groups="crm_altegra.group_crm_admin" |
1055 | + sequence="1"/> |
1056 | + |
1057 | + |
1058 | + <record id="view_crm_activities_filter" model="ir.ui.view"> |
1059 | + <field name="name">view.crm.activities.filter</field> |
1060 | + <field name="model">crm.activities</field> |
1061 | + <field name="type">search</field> |
1062 | + <field name="arch" type="xml"> |
1063 | + <search string="Buscar"> |
1064 | + <field name="name" filter_domain="[('name','ilike',self)]" string="Actividad"/> |
1065 | + <field name="project_id"/> |
1066 | + <field name="user_id"> |
1067 | + <filter domain="[('user_id','=',uid)]" help="Encargado" icon="terp-personal"/> |
1068 | + </field> |
1069 | + <field name="state"/> |
1070 | + <newline/> |
1071 | + <group expand="0" string="Group By..." groups="base.group_extended"> |
1072 | + <filter string="Proyecto" icon="gtk-open" domain="[]" context="{'group_by':'project_id'}"/> |
1073 | + <filter string="Responsable" icon="terp-personal+" domain="[]" context="{'group_by':'user_id'}"/> |
1074 | + <separator orientation="vertical"/> |
1075 | + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> |
1076 | + </group> |
1077 | + </search> |
1078 | + </field> |
1079 | + </record> |
1080 | + |
1081 | + |
1082 | + <!-- view_crm_activities_tree --> |
1083 | + <record id="view_crm_activities_tree" model="ir.ui.view"> |
1084 | + <field name="name">view.crm.activities.tree</field> |
1085 | + <field name="model">crm.activities</field> |
1086 | + <field name="type">tree</field> |
1087 | + <field name="priority" eval="17"/> |
1088 | + <field name="arch" type="xml"> |
1089 | + <tree string="Actividades"> |
1090 | + <field name="name"/> |
1091 | + <field name="project_id"/> |
1092 | + <field name="user_id"/> |
1093 | + <field name="type"/> |
1094 | + <field name="state"/> |
1095 | + <button name="action_confirm_activity" type="object" states="draft" string="Aprobar" icon="gtk-go-forward" /> |
1096 | + </tree> |
1097 | + </field> |
1098 | + </record> |
1099 | + |
1100 | + <!-- view_crm_activities_form --> |
1101 | + <record id="view_crm_activities_form" model="ir.ui.view"> |
1102 | + <field name="name">view.crm.activities.form</field> |
1103 | + <field name="model">crm.activities</field> |
1104 | + <field name="type">form</field> |
1105 | + <field name="priority" eval="17"/> |
1106 | + <field name="arch" type="xml"> |
1107 | + <form string="Actividad" > |
1108 | + <group colspan="4" > |
1109 | + <field name="name" /> |
1110 | + <field name="project_id"/> |
1111 | + <field name="user_id"/> |
1112 | + <field name="date_limit"/> |
1113 | + </group> |
1114 | + <group string="Tareas" colspan="4"> |
1115 | + <field name="task_ids" nolabel="1"> |
1116 | + <form string="Tarea" > |
1117 | + <group colspan="4" col = "6"> |
1118 | + <field name="name" colspan="6"/> |
1119 | + <field name="user_id"/> |
1120 | + <field name="date_limit"/> |
1121 | + <field name="change_date" invisible="1"/> |
1122 | + </group> |
1123 | + <group string ="Notas" colspan="4"> |
1124 | + <field name="note" nolabel="1"/> |
1125 | + </group> |
1126 | + <group> |
1127 | + <field name="state" widget="statusbar"/> |
1128 | + </group> |
1129 | + <group> |
1130 | + <button name="action_review" type="object" string="Revisado" icon="terp-stock_zoom" attrs="{'invisible':['|',('change_date','=',False),('state','in',('draft','cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
1131 | + <button name="acction_confirm" type="object" states="draft" string="Aprobar" icon="STOCK_NEW" /> |
1132 | + <button name="acction_done" type="object" states="open" string="Finalizada" icon="terp-camera_test" /> |
1133 | + <button name="acction_cancel" type="object" string="Cancelar" icon="gtk-cancel" attrs="{'invisible':['|',('state','in',('cancel','done'))]}" groups="crm_altegra.group_crm_admin"/> |
1134 | + </group> |
1135 | + </form> |
1136 | + </field> |
1137 | + </group> |
1138 | + <group> |
1139 | + <field name="state" widget="statusbar"/> |
1140 | + </group> |
1141 | + <group> |
1142 | + <button name="action_confirm_activity" type="object" states="draft" string="Aprobar" icon="gtk-go-forward" /> |
1143 | +<!-- |
1144 | + <button name="update_state_activities" type="object" string="UPDATE" icon="gtk-go-forward" /> |
1145 | +--> |
1146 | + </group> |
1147 | + </form> |
1148 | + </field> |
1149 | + </record> |
1150 | + |
1151 | + <record id="crm_activities_action" model="ir.actions.act_window"> |
1152 | + <field name="name">Actividades</field> |
1153 | + <field name="res_model">crm.activities</field> |
1154 | + <field name="view_type">form</field> |
1155 | + <field name="view_mode">tree,form</field> |
1156 | + <field name="search_view_id" ref="view_crm_activities_filter"/> |
1157 | + <field name="view_id" ref="view_crm_activities_tree"/> |
1158 | + </record> |
1159 | + |
1160 | + <!-- crm_project_menu_action --> |
1161 | + <menuitem id="crm_activities_menu_action" |
1162 | + parent="crm_activities_menu" |
1163 | + name="Actividades" |
1164 | + action="crm_activities_action" |
1165 | + groups="crm_altegra.group_crm_admin" |
1166 | + sequence="1"/> |
1167 | + |
1168 | + |
1169 | + </data> |
1170 | +</openerp> |
1171 | |
1172 | === added directory 'crm_altegra/images' |
1173 | === added file 'crm_altegra/images/icon.png' |
1174 | Binary files crm_altegra/images/icon.png 1970-01-01 00:00:00 +0000 and crm_altegra/images/icon.png 2013-07-03 23:03:28 +0000 differ |
1175 | === added directory 'crm_altegra/security' |
1176 | === added file 'crm_altegra/security/groups.xml' |
1177 | --- crm_altegra/security/groups.xml 1970-01-01 00:00:00 +0000 |
1178 | +++ crm_altegra/security/groups.xml 2013-07-03 23:03:28 +0000 |
1179 | @@ -0,0 +1,15 @@ |
1180 | +<?xml version="1.0"?> |
1181 | +<openerp> |
1182 | + <data> |
1183 | + <record model="res.groups" id="group_crm_admin"> |
1184 | + <field name="name">Administrador de CRM</field> |
1185 | + <field name="category_id" ref="base.module_category_usability"/> |
1186 | + </record> |
1187 | + |
1188 | + <record model="res.groups" id="group_crm_user"> |
1189 | + <field name="name">Usuario de CRM</field> |
1190 | + <field name="category_id" ref="base.module_category_usability"/> |
1191 | + </record> |
1192 | + |
1193 | + </data> |
1194 | +</openerp> |
1195 | |
1196 | === added file 'crm_altegra/security/ir.model.access.csv' |
1197 | --- crm_altegra/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 |
1198 | +++ crm_altegra/security/ir.model.access.csv 2013-07-03 23:03:28 +0000 |
1199 | @@ -0,0 +1,4 @@ |
1200 | +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
1201 | +access_crm_project,crm.project,model_crm_project,,1,1,1,1 |
1202 | +access_crm_task,crm.task,model_crm_task,,1,1,1,1 |
1203 | +access_crm_activities,crm.activities,model_crm_activities,,1,1,1,1 |
1204 | |
1205 | === added file 'crm_altegra/security/sequence.xml' |
1206 | --- crm_altegra/security/sequence.xml 1970-01-01 00:00:00 +0000 |
1207 | +++ crm_altegra/security/sequence.xml 2013-07-03 23:03:28 +0000 |
1208 | @@ -0,0 +1,21 @@ |
1209 | +<?xml version="1.0"?> |
1210 | +<openerp> |
1211 | + <data> |
1212 | + <record model="ir.sequence.type" id="sequence_crm_project"> |
1213 | + <field name="code">crm.project</field> |
1214 | + <field name="name">Seguimiento</field> |
1215 | + </record> |
1216 | + |
1217 | + <record model="ir.sequence" id="sequence_tracing"> |
1218 | + <field name="code">crm.project</field> |
1219 | + <field name="name">Seguimiento</field> |
1220 | + <field name="number_next">1</field> |
1221 | + <field name="implementation">standard</field> |
1222 | + <field name="padding">4</field> |
1223 | + <field name="number_increment">1</field> |
1224 | + <field name="prefix">SEG</field> |
1225 | + <field name="active">True</field> |
1226 | + </record> |
1227 | + |
1228 | + </data> |
1229 | +</openerp> |
1230 | |
1231 | === added directory 'crm_altegra/static' |
1232 | === added directory 'crm_altegra/static/src' |
1233 | === added directory 'crm_altegra/static/src/img' |
1234 | === added file 'crm_altegra/static/src/img/icon.png' |
1235 | Binary files crm_altegra/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and crm_altegra/static/src/img/icon.png 2013-07-03 23:03:28 +0000 differ |
1236 | === modified file 'dollars_altegra/__init__.py' |
1237 | --- dollars_altegra/__init__.py 2013-03-28 22:40:30 +0000 |
1238 | +++ dollars_altegra/__init__.py 2013-07-03 23:03:28 +0000 |
1239 | @@ -34,3 +34,7 @@ |
1240 | import account_invoice |
1241 | import account_change_currency |
1242 | import account_voucher |
1243 | +import internal_order |
1244 | +import purchase |
1245 | +import wizard |
1246 | +import stock |
1247 | |
1248 | === modified file 'dollars_altegra/__openerp__.py' |
1249 | --- dollars_altegra/__openerp__.py 2013-04-15 22:22:45 +0000 |
1250 | +++ dollars_altegra/__openerp__.py 2013-07-03 23:03:28 +0000 |
1251 | @@ -40,6 +40,8 @@ |
1252 | "sale_view.xml", |
1253 | "account_invoice_view.xml", |
1254 | "account_voucher_view.xml", |
1255 | + "internal_order_view.xml", |
1256 | + "purchase_view.xml", |
1257 | ], |
1258 | 'demo': [], |
1259 | 'test': [], |
1260 | |
1261 | === modified file 'dollars_altegra/account_invoice_view.xml' |
1262 | --- dollars_altegra/account_invoice_view.xml 2013-05-07 06:18:54 +0000 |
1263 | +++ dollars_altegra/account_invoice_view.xml 2013-07-03 23:03:28 +0000 |
1264 | @@ -3,6 +3,43 @@ |
1265 | <data> |
1266 | |
1267 | <!-- account_invoice_form_inh --> |
1268 | + <record model="ir.ui.view" id="invoice_supplier_form_inh"> |
1269 | + <field name="name">invoice.supplier.form.inh</field> |
1270 | + <field name="model">account.invoice</field> |
1271 | + <field name="inherit_id" ref="account.invoice_supplier_form" /> |
1272 | + <field name="type">form</field> |
1273 | + <field name="arch" type="xml" > |
1274 | + |
1275 | + <field name="currency_id" position="replace"/> |
1276 | + <field name="period_id" position="replace"> |
1277 | + <field name="period_id" domain="[('state', '=', 'draft')]" groups="account.group_account_user" widget="selection" invisible="1"/> |
1278 | + </field> |
1279 | + <field name="reference_type" position="replace"> |
1280 | + <field name="reference_type" nolabel="1" size="0" invisible="1"/> |
1281 | + </field> |
1282 | + <field name="fiscal_position" position="replace"> |
1283 | + <field name="fiscal_position" groups="base.group_extended" widget="selection" invisible="1"/> |
1284 | + </field> |
1285 | + <button name="239" string="Change" position="replace"> |
1286 | + <button name="239" type="action" icon="terp-stock_effects-object-colorize" string="Change" attrs="{'invisible':[('state','!=','draft')]}" colspan="2" invisible="1"/> |
1287 | + </button> |
1288 | + <field name="date_due" position="after"> |
1289 | + <newline/> |
1290 | + <group string="Dolares" colspan="4" col="10"> |
1291 | + <field name="currency_id" width="50" colspan="2"/> |
1292 | + <button name="239" type="action" icon="terp-stock_effects-object-colorize" string="Change" attrs="{'invisible':[('state','!=','draft')]}" colspan="2"/> |
1293 | + <field name="exchange_rate" attrs="{'readonly':[('state','!=','draft')]}" colspan="2"/> |
1294 | + <field name="system_rate" colspan="2"/> |
1295 | + <field name="dollar_invoice" readonly="1" colspan="2"/> |
1296 | + </group> |
1297 | + </field> |
1298 | + <button name="invoice_open" position="replace"> |
1299 | + <button name="invoice_open" states="draft,proforma2" string="Approve" icon="terp-camera_test" attrs="{'readonly':[('exchange_rate','=', False),('dollar_invoice','=', True)]}"/> |
1300 | + </button> |
1301 | + </field> |
1302 | + </record> |
1303 | + |
1304 | + <!-- account_invoice_form_inh --> |
1305 | <record model="ir.ui.view" id="account_invoice_form_inh"> |
1306 | <field name="name">account.invoice.form.inh</field> |
1307 | <field name="model">account.invoice</field> |
1308 | @@ -17,15 +54,20 @@ |
1309 | <button name="%(account.action_account_change_currency)d" type="action" icon="terp-stock_effects-object-colorize" string="Change" attrs="{'invisible':[('state','!=','draft')]}" groups="account.group_account_user"/> |
1310 | </group> |
1311 | <group colspan="2" col="6"> |
1312 | - <field name="exchange_rate" attrs="{'readonly':[('state','!=','draft')]}"/> |
1313 | - <field name="system_rate"/> |
1314 | - <field name="dollar_invoice" readonly="1"/> |
1315 | + <field name="exchange_rate" attrs="{'readonly':[('state','!=','draft')]}" /> |
1316 | + <field name="system_rate" /> |
1317 | + <field name="dollar_invoice" readonly="1" /> |
1318 | </group> |
1319 | </field> |
1320 | + <button string="Validate" position="replace"> |
1321 | + <button name="invoice_open" string="Validate" icon="gtk-go-forward" attrs="{'invisible':['|',('state','not in',('draft')),'|',('origin','=','')], 'readonly':[('exchange_rate','=', '0'),('dollar_invoice','=', True)]}"/> |
1322 | + </button> |
1323 | +<!-- |
1324 | <button string="Validate" position="replace"/> |
1325 | <button string="IMPRIMIR REMISION" position="after"> |
1326 | <button name="invoice_open" string="Validate" icon="gtk-go-forward" attrs="{'invisible':['|',('state','not in',('draft')),'|',('origin','=','')], 'readonly':[('exchange_rate','=', '0'),('dollar_invoice','=', True)]}"/> |
1327 | </button> |
1328 | +--> |
1329 | <field name="origin" position="replace"> |
1330 | <field name="origin" attrs="{'readonly':[('manual_invoice','!=',True)]}"/> |
1331 | <field name="manual_invoice" groups="base.group_system"/> |
1332 | |
1333 | === modified file 'dollars_altegra/account_voucher_view.xml' |
1334 | --- dollars_altegra/account_voucher_view.xml 2013-04-15 20:39:28 +0000 |
1335 | +++ dollars_altegra/account_voucher_view.xml 2013-07-03 23:03:28 +0000 |
1336 | @@ -24,6 +24,22 @@ |
1337 | <button name="proforma_voucher" string="Validate" states="draft" icon="gtk-go-forward" invisible="context.get('line_type', False)" |
1338 | attrs="{'readonly':[('payment_rate_currency_id','=','2'),('validate_rate','=', False)]}"/> |
1339 | </button> |
1340 | + <xpath expr="//field[@name='line_cr_ids']/tree//field[@name='date_due']" position="after"> |
1341 | + <field name="currency_id" string="Divisa"/> |
1342 | + </xpath> |
1343 | + </field> |
1344 | + </record> |
1345 | + |
1346 | + <!-- view_vendor_payment_form_inherit --> |
1347 | + <record model="ir.ui.view" id="view_vendor_payment_form_inherit"> |
1348 | + <field name="name">view.vendor.payment.form.inherit</field> |
1349 | + <field name="model">account.voucher</field> |
1350 | + <field name="inherit_id" ref="account_voucher.view_vendor_payment_form"/> |
1351 | + <field name="type">form</field> |
1352 | + <field name="arch" type="xml"> |
1353 | + <xpath expr="//field[@name='line_dr_ids']/tree//field[@name='date_due']" position="after"> |
1354 | + <field name="currency_id" string="Divisa"/> |
1355 | + </xpath> |
1356 | </field> |
1357 | </record> |
1358 | |
1359 | |
1360 | === added file 'dollars_altegra/internal_order.py' |
1361 | --- dollars_altegra/internal_order.py 1970-01-01 00:00:00 +0000 |
1362 | +++ dollars_altegra/internal_order.py 2013-07-03 23:03:28 +0000 |
1363 | @@ -0,0 +1,44 @@ |
1364 | +#!/usr/bin/env python |
1365 | +#-*- coding:utf-8 -*- |
1366 | + |
1367 | +############################################################################# |
1368 | +# Module Writen to OpenERP, Open Source Management Solution |
1369 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
1370 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
1371 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
1372 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
1373 | +# |
1374 | +############################################################################# |
1375 | +# |
1376 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
1377 | +# Coded by: Edgar Romero (edgar.romero@grupoaltegra.com) |
1378 | +# |
1379 | +############################################################################# |
1380 | +# |
1381 | +# This program is free software: you can redistribute it and/or modify |
1382 | +# it under the terms of the GNU Affero General Public License as |
1383 | +# published by the Free Software Foundation, either version 3 of the |
1384 | +# License, or (at your option) any later version. |
1385 | +# |
1386 | +# This program is distributed in the hope that it will be useful, |
1387 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1388 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1389 | +# GNU Affero General Public License for more details. |
1390 | +# |
1391 | +# You should have received a copy of the GNU Affero General Public License |
1392 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1393 | +# |
1394 | +############################################################################# |
1395 | + |
1396 | +from osv import osv, fields |
1397 | + |
1398 | +class internal_order(osv.Model): |
1399 | + _inherit = "internal.order" |
1400 | + |
1401 | + _columns = { |
1402 | + 'currency_id': fields.many2one('res.currency', 'Moneda', help="Tipo de moneda en que se realizo la cotización"), |
1403 | + } |
1404 | + |
1405 | + _defaults = { |
1406 | + 'currency_id': 34, |
1407 | + } |
1408 | |
1409 | === added file 'dollars_altegra/internal_order_view.xml' |
1410 | --- dollars_altegra/internal_order_view.xml 1970-01-01 00:00:00 +0000 |
1411 | +++ dollars_altegra/internal_order_view.xml 2013-07-03 23:03:28 +0000 |
1412 | @@ -0,0 +1,19 @@ |
1413 | +<?xml version="1.0" encoding="utf-8"?> |
1414 | +<openerp> |
1415 | + <data> |
1416 | + |
1417 | + <!-- sale_view_order_form_dollars_inh --> |
1418 | + <record model="ir.ui.view" id="view_internal_order_tree_inherit"> |
1419 | + <field name="name">view.internal.order.tree.inherit</field> |
1420 | + <field name="model">internal.order</field> |
1421 | + <field name="inherit_id" ref="internal_order_altegra.view_internal_order_tree" /> |
1422 | + <field name="type">tree</field> |
1423 | + <field name="arch" type="xml" > |
1424 | + <field name="part_number" position="replace"> |
1425 | + <field name="currency_id" /> |
1426 | + </field> |
1427 | + </field> |
1428 | + </record> |
1429 | + |
1430 | + </data> |
1431 | +</openerp> |
1432 | |
1433 | === added file 'dollars_altegra/purchase.py' |
1434 | --- dollars_altegra/purchase.py 1970-01-01 00:00:00 +0000 |
1435 | +++ dollars_altegra/purchase.py 2013-07-03 23:03:28 +0000 |
1436 | @@ -0,0 +1,52 @@ |
1437 | +#!/usr/bin/env python |
1438 | +#-*- coding:utf-8 -*- |
1439 | + |
1440 | +############################################################################# |
1441 | +# Module Writen to OpenERP, Open Source Management Solution |
1442 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
1443 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
1444 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
1445 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
1446 | +# |
1447 | +############################################################################# |
1448 | +# |
1449 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
1450 | +# |
1451 | +############################################################################# |
1452 | +# |
1453 | +# This program is free software: you can redistribute it and/or modify |
1454 | +# it under the terms of the GNU Affero General Public License as |
1455 | +# published by the Free Software Foundation, either version 3 of the |
1456 | +# License, or (at your option) any later version. |
1457 | +# |
1458 | +# This program is distributed in the hope that it will be useful, |
1459 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1460 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1461 | +# GNU Affero General Public License for more details. |
1462 | +# |
1463 | +# You should have received a copy of the GNU Affero General Public License |
1464 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1465 | +# |
1466 | +############################################################################# |
1467 | + |
1468 | +from osv import osv, fields |
1469 | + |
1470 | +class purchase_order(osv.Model): |
1471 | + _inherit = 'purchase.order' |
1472 | + |
1473 | + _columns = { |
1474 | + 'dollar_purchase': fields.boolean('Compra en dólares', readonly=True, states={'draft': [('readonly', False)]},help = "Selecciona esta opción si la compra será en dólares"), |
1475 | + 'exchange_rate': fields.float('Tipo de cambio', readonly=True, states={'draft': [('readonly', False)]}, help = "Ingresa el tipo de cambio del dólar a pesos"), |
1476 | + } |
1477 | + |
1478 | + _defaults = { |
1479 | + 'dollar_purchase': False, |
1480 | + } |
1481 | + |
1482 | + def action_invoice_create(self, cr, uid, ids, context=None): |
1483 | + invoice_id = super(purchase_order, self).action_invoice_create(cr, uid, ids, context) |
1484 | + purchase_row = self.browse(cr, uid, ids, context)[0] |
1485 | + if purchase_row.dollar_purchase: |
1486 | + self.pool.get('account.invoice').write(cr, uid, [invoice_id], {'dollar_invoice': True, 'exchange_rate':purchase_row.exchange_rate, 'currency_id':2}) |
1487 | + return invoice_id |
1488 | + |
1489 | |
1490 | === added file 'dollars_altegra/purchase_view.xml' |
1491 | --- dollars_altegra/purchase_view.xml 1970-01-01 00:00:00 +0000 |
1492 | +++ dollars_altegra/purchase_view.xml 2013-07-03 23:03:28 +0000 |
1493 | @@ -0,0 +1,22 @@ |
1494 | +<?xml version="1.0" encoding="utf-8"?> |
1495 | +<openerp> |
1496 | + <data> |
1497 | + |
1498 | + <!-- sale_view_order_form_dollars_inh --> |
1499 | + <record model="ir.ui.view" id="purchase_order_form_inh"> |
1500 | + <field name="name">purchase.order.form.inh</field> |
1501 | + <field name="model">purchase.order</field> |
1502 | + <field name="inherit_id" ref="purchase.purchase_order_form" /> |
1503 | + <field name="type">form</field> |
1504 | + <field name="arch" type="xml" > |
1505 | + <field name="shipped" position="after"> |
1506 | + <field name="dollar_purchase" /> |
1507 | + </field> |
1508 | + <field name="origin" position="after"> |
1509 | + <field name="exchange_rate" attrs="{'invisible': [('dollar_purchase','!=',True)], 'required': [('dollar_purchase','=',True)]}"/> |
1510 | + </field> |
1511 | + </field> |
1512 | + </record> |
1513 | + |
1514 | + </data> |
1515 | +</openerp> |
1516 | |
1517 | === modified file 'dollars_altegra/sale.py' |
1518 | --- dollars_altegra/sale.py 2013-03-28 22:40:30 +0000 |
1519 | +++ dollars_altegra/sale.py 2013-07-03 23:03:28 +0000 |
1520 | @@ -44,6 +44,16 @@ |
1521 | _defaults = { |
1522 | 'dollar_sale': False, |
1523 | } |
1524 | + |
1525 | + def get_internal_order_vals(self, cr, uid, ids, line, context=None): |
1526 | + internal_order_line = super(sale_order, self).get_internal_order_vals(cr, uid, ids, line, context) |
1527 | + # Si es venta en dólares |
1528 | + if line.order_id.dollar_sale: |
1529 | + if line.order_id.exchange_rate <= 0: |
1530 | + raise osv.except_osv(_('¡Tu cotización es en dólares'),_('Ingresa un tipo de cambio mayor a cero')) |
1531 | + else: |
1532 | + internal_order_line.update({'currency_id':2}) |
1533 | + return internal_order_line |
1534 | |
1535 | def action_wait(self, cr, uid, ids, context=None): |
1536 | """ |
1537 | |
1538 | === added file 'dollars_altegra/stock.py' |
1539 | --- dollars_altegra/stock.py 1970-01-01 00:00:00 +0000 |
1540 | +++ dollars_altegra/stock.py 2013-07-03 23:03:28 +0000 |
1541 | @@ -0,0 +1,47 @@ |
1542 | +#!/usr/bin/env python |
1543 | +#-*- coding:utf-8 -*- |
1544 | + |
1545 | +############################################################################# |
1546 | +# Module Writen to OpenERP, Open Source Management Solution |
1547 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
1548 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
1549 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
1550 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
1551 | +# |
1552 | +############################################################################# |
1553 | +# |
1554 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
1555 | +# |
1556 | +############################################################################# |
1557 | +# |
1558 | +# This program is free software: you can redistribute it and/or modify |
1559 | +# it under the terms of the GNU Affero General Public License as |
1560 | +# published by the Free Software Foundation, either version 3 of the |
1561 | +# License, or (at your option) any later version. |
1562 | +# |
1563 | +# This program is distributed in the hope that it will be useful, |
1564 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1565 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1566 | +# GNU Affero General Public License for more details. |
1567 | +# |
1568 | +# You should have received a copy of the GNU Affero General Public License |
1569 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1570 | +# |
1571 | +############################################################################# |
1572 | + |
1573 | +from osv import osv, fields |
1574 | + |
1575 | +class stock_picking(osv.Model): |
1576 | + |
1577 | + _inherit = "stock.picking" |
1578 | + |
1579 | + def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None): |
1580 | + """ Se redefine el método para sabes si la compra se cotizo en dolares """ |
1581 | + invoice_vals = super(stock_picking, self)._prepare_invoice(cr, uid, picking, partner, inv_type, journal_id, context) |
1582 | + # Validamos si el picking tiene compra |
1583 | + if picking.purchase_id: |
1584 | + # Validamos si la compra fue cotizada en Dolares |
1585 | + if picking.purchase_id.dollar_purchase: |
1586 | + # Si fue cotizada en dolares actualizamos el diccionario para agregarle la moneda y ponerle el tipo de cambio de la compra |
1587 | + invoice_vals.update({'dollar_invoice': True, 'exchange_rate':picking.purchase_id.exchange_rate, 'currency_id':2}) |
1588 | + return invoice_vals |
1589 | |
1590 | === added directory 'dollars_altegra/wizard' |
1591 | === added file 'dollars_altegra/wizard/__init__.py' |
1592 | --- dollars_altegra/wizard/__init__.py 1970-01-01 00:00:00 +0000 |
1593 | +++ dollars_altegra/wizard/__init__.py 2013-07-03 23:03:28 +0000 |
1594 | @@ -0,0 +1,32 @@ |
1595 | +#!/usr/bin/env python |
1596 | +#-*- coding:utf-8 -*- |
1597 | + |
1598 | +############################################################################# |
1599 | +# Module Writen to OpenERP, Open Source Management Solution |
1600 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
1601 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
1602 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
1603 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
1604 | +# |
1605 | +############################################################################# |
1606 | +# |
1607 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
1608 | +# |
1609 | +############################################################################# |
1610 | +# |
1611 | +# This program is free software: you can redistribute it and/or modify |
1612 | +# it under the terms of the GNU Affero General Public License as |
1613 | +# published by the Free Software Foundation, either version 3 of the |
1614 | +# License, or (at your option) any later version. |
1615 | +# |
1616 | +# This program is distributed in the hope that it will be useful, |
1617 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1618 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1619 | +# GNU Affero General Public License for more details. |
1620 | +# |
1621 | +# You should have received a copy of the GNU Affero General Public License |
1622 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1623 | +# |
1624 | +############################################################################ |
1625 | + |
1626 | +import create_purchase |
1627 | |
1628 | === added file 'dollars_altegra/wizard/create_purchase.py' |
1629 | --- dollars_altegra/wizard/create_purchase.py 1970-01-01 00:00:00 +0000 |
1630 | +++ dollars_altegra/wizard/create_purchase.py 2013-07-03 23:03:28 +0000 |
1631 | @@ -0,0 +1,62 @@ |
1632 | +#!/usr/bin/env python |
1633 | +#-*- coding:utf-8 -*- |
1634 | + |
1635 | +############################################################################# |
1636 | +# Module Writen to OpenERP, Open Source Management Solution |
1637 | +# CopyLeft 2012 - http://www.grupoaltegra.com |
1638 | +# You are free to share, copy, distribute, transmit, adapt and use for commercial purpose |
1639 | +# More information about license: http://www.gnu.org/licenses/agpl.html |
1640 | +# info Grupo Altegra (openerp@grupoaltegra.com) |
1641 | +# |
1642 | +############################################################################# |
1643 | +# |
1644 | +# Coded by: Carlos Blanco (carlos.blanco@grupoaltegra.com) |
1645 | +# |
1646 | +############################################################################# |
1647 | +# |
1648 | +# This program is free software: you can redistribute it and/or modify |
1649 | +# it under the terms of the GNU Affero General Public License as |
1650 | +# published by the Free Software Foundation, either version 3 of the |
1651 | +# License, or (at your option) any later version. |
1652 | +# |
1653 | +# This program is distributed in the hope that it will be useful, |
1654 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1655 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1656 | +# GNU Affero General Public License for more details. |
1657 | +# |
1658 | +# You should have received a copy of the GNU Affero General Public License |
1659 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1660 | +# |
1661 | +############################################################################# |
1662 | + |
1663 | +from osv import osv ,fields |
1664 | +from tools.translate import _ |
1665 | + |
1666 | +class create_purchase(osv.TransientModel): |
1667 | + _inherit = 'create.purchase' |
1668 | + |
1669 | + def get_io_by_supplier(self, cr, uid, ids, supplier_ids, internal_order_rows, context=None): |
1670 | + """ Método que crea un diccionario con las internal orders por proveedor """ |
1671 | + vals = {} |
1672 | + # Clasificamos las lineas por proveedor |
1673 | + for supplier_id in supplier_ids: |
1674 | + aux = [] |
1675 | + currency_id = False |
1676 | + for index in range(len(internal_order_rows)): |
1677 | + # Si es del proveedor se agrega a una lista auxiliar |
1678 | + if supplier_id == internal_order_rows[index].supplier_id.id: |
1679 | + if not currency_id: |
1680 | + currency_id = internal_order_rows[index].currency_id.id |
1681 | + elif currency_id != internal_order_rows[index].currency_id.id: |
1682 | + raise osv.except_osv(_('¡Error!'),_('No puedes seleccionar compras con diferentes monedas y el mismo proveedor')) |
1683 | + aux.append(internal_order_rows[index]) |
1684 | + # Se agrega las lineas por proveedor |
1685 | + vals.update({supplier_id:aux}) |
1686 | + return vals |
1687 | + |
1688 | + def get_purchase_vals(self, cr, uid, ids, supplier_id, internal_row, context=None): |
1689 | + """ Método para obtener el diccionario para crear la compra """ |
1690 | + purchase_vals = super(create_purchase, self).get_purchase_vals(cr, uid, ids, supplier_id, internal_row, context) |
1691 | + if internal_row.currency_id.id == 2: |
1692 | + purchase_vals.update({'dollar_purchase':True}) |
1693 | + return purchase_vals |
1694 | |
1695 | === modified file 'internal_order_altegra/purchase.py' |
1696 | --- internal_order_altegra/purchase.py 2013-04-23 00:23:24 +0000 |
1697 | +++ internal_order_altegra/purchase.py 2013-07-03 23:03:28 +0000 |
1698 | @@ -120,14 +120,17 @@ |
1699 | - Se redefine la función para agregar la fecha de entrega y la paquetería al picking de entrada |
1700 | proveniente de purchase_order. |
1701 | """ |
1702 | + customer_id = False |
1703 | picking_id = super(purchase_order, self)._create_pickings(cr, uid, order, order_lines, picking_id=False, context=None) |
1704 | if picking_id: |
1705 | # Actualizamos fecha de llegada y paqueteria en orden de entrada |
1706 | self.pool.get('stock.picking').write(cr, uid, picking_id, {'date_arrival': order.date_arrival or False, 'package_id': order.package_id.id or False,'min_date':order.date_arrival}) |
1707 | picking_row = self.pool.get('stock.picking').browse(cr,uid,picking_id)[0] |
1708 | for stock_move_row in picking_row.move_lines: |
1709 | + if stock_move_row.purchase_line_id.internal_order_id: |
1710 | + customer_id = stock_move_row.purchase_line_id.internal_order_id.customer_id and stock_move_row.purchase_line_id.internal_order_id.customer_id.id or False |
1711 | # Actualizamos fecha de llegada y cliente del movimiento |
1712 | - self.pool.get('stock.move').write(cr, uid, [stock_move_row.id], {'date_arrival':order.date_arrival, 'customer_id': stock_move_row.purchase_line_id.internal_order_id.customer_id.id or False}) |
1713 | + self.pool.get('stock.move').write(cr, uid, [stock_move_row.id], {'date_arrival':order.date_arrival, 'customer_id': customer_id}) |
1714 | return picking_id |
1715 | |
1716 | class purchase_order_line(osv.Model): |
1717 | |
1718 | === modified file 'internal_order_altegra/sale.py' |
1719 | --- internal_order_altegra/sale.py 2013-04-22 23:17:45 +0000 |
1720 | +++ internal_order_altegra/sale.py 2013-07-03 23:03:28 +0000 |
1721 | @@ -62,6 +62,26 @@ |
1722 | 'name': self.pool.get('ir.sequence').get(cr, uid, 'sale.order'), |
1723 | }) |
1724 | return super(sale_order, self).copy(cr, uid, id, default, context=context) |
1725 | + |
1726 | + def get_internal_order_vals(self, cr, uid, ids, line, context=None): |
1727 | + """ Método que genera el diccionario para crear las lineas internas """ |
1728 | + internal_order_line = { |
1729 | + 'sale_id' : ids[0], |
1730 | + 'special_price' : line.special_price, |
1731 | + 'qty_order' : line.product_uom_qty, |
1732 | + 'qty_buy': line.product_uom_qty, |
1733 | + 'product_id' : line.product_id.id, |
1734 | + 'part_number' : line.product_id.default_code, |
1735 | + 'price_unit' : line.price_unit, |
1736 | + 'customer_id': line.order_id.partner_id.id, |
1737 | + 'user_id': line.order_id.user_id.id, |
1738 | + 'brand_id' : line.product_id.categ_id.id, |
1739 | + 'delivery_date' : line.order_id.delivery or False, |
1740 | + 'supplier_id' : line.supplier_id.id, |
1741 | + 'price_buy': line.supplier_price, |
1742 | + 'note': line.order_id.note, |
1743 | + } |
1744 | + return internal_order_line |
1745 | |
1746 | def create_internal_lines(self, cr, uid, ids, context=None): |
1747 | """ |
1748 | @@ -70,7 +90,7 @@ |
1749 | """ |
1750 | # Sale order row |
1751 | sale_order_row = self.browse(cr, uid, ids, context=None)[0] |
1752 | - |
1753 | + internal_order_ids = [] |
1754 | # Verificamos que haya sido ingresada la fecha de entrega |
1755 | if sale_order_row.delivery: |
1756 | if sale_order_row: |
1757 | @@ -87,40 +107,15 @@ |
1758 | # Si todas las líneas son servicio se cambia el método de facturación |
1759 | if types[0][0] == 'service': |
1760 | self.pool.get('sale.order').write(cr, uid, ids, {'order_policy': 'manual'}, context=None) |
1761 | - |
1762 | - # Si es venta en dólares |
1763 | - if sale_order_row.dollar_sale: |
1764 | - if sale_order_row.exchange_rate <= 0: |
1765 | - raise osv.except_osv(_('¡Tu cotización es en dólares'),_('Ingresa un tipo de cambio mayor a cero')) |
1766 | - else: |
1767 | - conversion_factor = float(round(sale_order_row.exchange_rate, 2)) |
1768 | - else: |
1769 | - conversion_factor = 1 |
1770 | - |
1771 | # Recorremos líneas de sale_order |
1772 | for line in self.pool.get('sale.order.line').browse(cr, uid, sale_order_lines, context=None): |
1773 | # Se crean líneas de pedido interno únicamente de productos que no son servicios |
1774 | if line.product_id.type != 'service': |
1775 | - # Creamos líneas de pedido interno |
1776 | - internal_order_line = { |
1777 | - 'sale_id' : ids[0], |
1778 | - 'special_price' : line.special_price, |
1779 | - 'qty_order' : line.product_uom_qty, |
1780 | - 'qty_buy': line.product_uom_qty, |
1781 | - 'product_id' : line.product_id.id, |
1782 | - 'part_number' : line.product_id.default_code, |
1783 | - 'price_unit' : line.price_unit * conversion_factor, |
1784 | - 'customer_id': sale_order_row.partner_id.id, |
1785 | - 'user_id': sale_order_row.user_id.id, |
1786 | - 'brand_id' : line.product_id.categ_id.id, |
1787 | - 'delivery_date' : sale_order_row.delivery or False, |
1788 | - 'supplier_id' : line.supplier_id.id, |
1789 | - 'price_buy': line.supplier_price * conversion_factor, |
1790 | - 'note': sale_order_row.note, |
1791 | - } |
1792 | + internal_order_line = self.get_internal_order_vals(cr, uid, ids, line, context) |
1793 | # Creamos línea |
1794 | internal_order_line_id = self.pool.get('internal.order').create(cr, uid, internal_order_line, context=None) |
1795 | + internal_order_ids.append(internal_order_line_id) |
1796 | else: |
1797 | raise osv.except_osv(_('¡Verifica los datos!'),_('Debes ingresar Tiempo de entrega')) |
1798 | |
1799 | - return True |
1800 | + return internal_order_ids |
1801 | |
1802 | === modified file 'internal_order_altegra/wizard/create_purchase.py' |
1803 | --- internal_order_altegra/wizard/create_purchase.py 2013-04-23 00:23:24 +0000 |
1804 | +++ internal_order_altegra/wizard/create_purchase.py 2013-07-03 23:03:28 +0000 |
1805 | @@ -35,6 +35,33 @@ |
1806 | class create_purchase(osv.TransientModel): |
1807 | _name = 'create.purchase' |
1808 | |
1809 | + |
1810 | + def get_io_by_supplier(self, cr, uid, ids, supplier_ids, internal_order_rows, context=None): |
1811 | + """ Método que crea un diccionario con las internal orders por proveedor """ |
1812 | + vals = {} |
1813 | + # Clasificamos las lineas por proveedor |
1814 | + for supplier_id in supplier_ids: |
1815 | + aux = [] |
1816 | + for index in range(len(internal_order_rows)): |
1817 | + # Si es del proveedor se agrega a una lista auxiliar |
1818 | + if supplier_id == internal_order_rows[index].supplier_id.id: |
1819 | + aux.append(internal_order_rows[index]) |
1820 | + # Se agrega las lineas por proveedor |
1821 | + vals.update({supplier_id:aux}) |
1822 | + return vals |
1823 | + |
1824 | + def get_purchase_vals(self, cr, uid, ids, supplier_id, internal_row, context=None): |
1825 | + """ Método para obtener el diccionario para crear la compra """ |
1826 | + purchase_vals = { |
1827 | + 'partner_id':supplier_id, |
1828 | + 'partner_address_id': self.pool.get('res.partner').address_get(cr, uid, [supplier_id], ['default'])['default'], |
1829 | + 'pricelist_id': self.pool.get('res.partner').browse(cr, uid, supplier_id).property_product_pricelist_purchase.id, |
1830 | + 'company_id': internal_row.sale_id.company_id.id, |
1831 | + 'warehouse_id':internal_row.sale_id.shop_id.warehouse_id.id, |
1832 | + 'location_id':internal_row.sale_id.shop_id.warehouse_id.lot_stock_id.id, |
1833 | + } |
1834 | + return purchase_vals |
1835 | + |
1836 | def action_create_purchase(self,cr,uid,ids,context=None): |
1837 | """ Crea las ordenes de compra de los internal orders seleccionadas """ |
1838 | # Objetos |
1839 | @@ -57,28 +84,14 @@ |
1840 | if not internal_order_row.supplier_id.id in supplier_ids: |
1841 | supplier_ids.append(internal_order_row.supplier_id.id) |
1842 | # Clasificamos las lineas por proveedor |
1843 | - for supplier_id in supplier_ids: |
1844 | - aux = [] |
1845 | - for index in range(len(internal_order_rows)): |
1846 | - # Si es del proveedor se agrega a una lista auxiliar |
1847 | - if supplier_id == internal_order_rows[index].supplier_id.id: |
1848 | - aux.append(internal_order_rows[index]) |
1849 | - # Se agrega las lineas por proveedor |
1850 | - vals.update({supplier_id:aux}) |
1851 | + vals = self.get_io_by_supplier(cr, uid, ids, supplier_ids, internal_order_rows, context) |
1852 | # Creamos las compras |
1853 | for supplier_id in supplier_ids: |
1854 | # Obtenemos el primer registro del proveedor |
1855 | internal_row = vals[supplier_id][0] |
1856 | origin = internal_row.sale_id.name |
1857 | # Obtenemos los valores para crear la compra |
1858 | - purchase_vals = { |
1859 | - 'partner_id':supplier_id, |
1860 | - 'partner_address_id': self.pool.get('res.partner').address_get(cr, uid, [supplier_id], ['default'])['default'], |
1861 | - 'pricelist_id': self.pool.get('res.partner').browse(cr, uid, supplier_id).property_product_pricelist_purchase.id, |
1862 | - 'company_id': internal_row.sale_id.company_id.id, |
1863 | - 'warehouse_id':internal_row.sale_id.shop_id.warehouse_id.id, |
1864 | - 'location_id':internal_row.sale_id.shop_id.warehouse_id.lot_stock_id.id, |
1865 | - } |
1866 | + purchase_vals = self.get_purchase_vals(cr, uid, ids, supplier_id, internal_row, context) |
1867 | # Creamos la compra |
1868 | fiscal_position_id = False |
1869 | purchase_id = purchase_obj.create(cr,uid,purchase_vals) |
1870 | |
1871 | === modified file 'product_altegra/product.py' |
1872 | --- product_altegra/product.py 2013-04-23 17:36:34 +0000 |
1873 | +++ product_altegra/product.py 2013-07-03 23:03:28 +0000 |
1874 | @@ -76,7 +76,7 @@ |
1875 | return res |
1876 | |
1877 | _columns = { |
1878 | - 'model' : fields.char('Modelo', size=20), |
1879 | + 'model' : fields.char('Modelo', size=64), |
1880 | 'government_description': fields.text('Descripción Gobierno', help="Descripción utilizada en cotizaciones y facturas de la UEE Gobierno", translate=True), |
1881 | 'qty_zero_stock': fields.function(_get_qty_stock, type='float', string='Costo Cero', store=False, multi='all', digits_compute=dp.get_precision('Product UoM')), |
1882 | } |