1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# Copyright (c) 2010 Vauxoo C.A. (http://openerp.com.ve/) All Rights Reserved.
5
# Javier Duran <javier@vauxoo.com>
8
# WARNING: This program as such is intended to be used by professional
9
# programmers who take the whole responsability of assessing all potential
10
# consequences resulting from its eventual inadequacies and bugs
11
# End users who are looking for a ready-to-use solution with commercial
12
# garantees and support are strongly adviced to contract a Free Software
15
# This program is Free Software; you can redistribute it and/or
16
# modify it under the terms of the GNU General Public License
17
# as published by the Free Software Foundation; either version 2
18
# of the License, or (at your option) any later version.
20
# This program is distributed in the hope that it will be useful,
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
# GNU General Public License for more details.
25
# You should have received a copy of the GNU General Public License
26
# along with this program; if not, write to the Free Software
27
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
##############################################################################
31
from openerp.osv import osv, fields
32
from openerp.tools.sql import drop_view_if_exists
36
from mx.DateTime import *
37
import decimal_precision as dp
40
class report_profit_picking(osv.Model):
41
def _get_invoice_line(self, cr, uid, ids, field_name, arg, context={}):
43
aml_obj = self.pool.get('account.move.line')
44
purchase_obj = self.pool.get('purchase.order')
45
sale_obj = self.pool.get('sale.order')
46
il_obj = self.pool.get('account.invoice.line')
47
loc_obj = self.pool.get('stock.location')
49
for rpp in self.browse(cr, uid, ids, context):
52
if getattr(rpp, 'purchase_line_id', False) and \
53
rpp.purchase_line_id.id:
54
loc_ids = loc_obj.search(cr, uid, [('name', '=', 'Stock')])
55
supp_loc_ids = loc_obj.search(
56
cr, uid, [('name', '=', 'Suppliers')])
59
inv_type = 'in_invoice'
62
'Error', 'No hay una ubicacion stock definida')
66
'Error', 'No hay una ubicacion proveedor definida')
68
if getattr(rpp.purchase_line_id.order_id,
69
'invoice_ids', False):
70
inv_id = self.purchase_invoice_get(
71
cr, uid, rpp.purchase_line_id.order_id.id,
73
inv = self.pool.get('account.invoice').browse(
74
cr, uid, inv_id, context=context)
76
if inv.id not in lst_inv:
77
lst_inv.append(inv.id)
79
for inv_nc in inv.child_ids:
80
if inv_nc.id not in lst_inv:
81
lst_inv.append(inv_nc.id)
84
str_inv = ','.join(map(str, lst_inv))
86
if rpp.location_id.id == loc_ids[0] and \
87
rpp.location_dest_id.id == supp_loc_ids[0]:
88
inv_type = 'in_refund'
93
from account_invoice_line l
94
inner join account_invoice i on
96
where i.id in (%s) and
98
l.product_id=%s and l.quantity=%s
99
''' % (str_inv, inv_type, rpp.product_id.id, rpp.picking_qty)
101
il_ids = [x[0] for x in cr.fetchall()]
103
if rpp.sale_line_id and rpp.sale_line_id.id:
104
cust_loc_ids = loc_obj.search(
105
cr, uid, [('name', '=', 'Customers')])
109
inv_type = 'out_invoice'
111
raise osv.except_osv(
112
'Error', 'No hay una ubicacion cliente definida')
114
if rpp.sale_line_id.order_id.invoice_ids:
115
for inv in rpp.sale_line_id.order_id.invoice_ids:
116
if inv.id not in lst_inv:
117
lst_inv.append(inv.id)
119
for inv_nc in inv.child_ids:
120
if inv_nc.id not in lst_inv:
121
lst_inv.append(inv_nc.id)
124
str_inv = ','.join(map(str, lst_inv))
126
if rpp.location_id.id == cust_loc_ids[0]:
127
inv_type = 'out_refund'
131
from account_invoice_line l
132
inner join account_invoice i on
134
where i.id in (%s) and
138
''' % (str_inv, inv_type, rpp.product_id.id, rpp.picking_qty)
140
il_ids = [x[0] for x in cr.fetchall()]
143
il = il_obj.browse(cr, uid, il_ids[0], context)
144
# print 'lineas consultaxxx: ',il
145
result[rpp.id] = (il.id, il.name)
149
def _get_aml_cost(self, cr, uid, ids, field_name, arg, context={}):
151
aml_obj = self.pool.get('account.move.line')
152
for rpp in self.browse(cr, uid, ids, context):
154
if rpp.invoice_line_id and rpp.invoice_line_id.id:
155
moves = self.aml_cost_get(cr, uid, [rpp.invoice_line_id.id])
157
aml = aml_obj.browse(cr, uid, moves[0], context)
158
result[rpp.id] = (aml.id, aml.name)
160
moves = self.aml_internal_get(cr, uid, [rpp.stk_mov_id.id])
162
aml = aml_obj.browse(cr, uid, moves[0], context)
163
result[rpp.id] = (aml.id, aml.name)
167
def _get_invoice_qty(self, cr, uid, ids, name, arg, context={}):
169
for rpp in self.browse(cr, uid, ids, context):
171
if rpp.invoice_line_id and rpp.invoice_line_id.id:
172
res[rpp.id] = rpp.invoice_line_id.quantity
175
def _get_aml_cost_qty(self, cr, uid, ids, name, arg, context={}):
177
for rpp in self.browse(cr, uid, ids, context):
179
if rpp.aml_cost_id and rpp.aml_cost_id.id:
180
res[rpp.id] = rpp.aml_cost_id.quantity
183
def _get_aml_inv_qty(self, cr, uid, ids, name, arg, context={}):
185
for rpp in self.browse(cr, uid, ids, context):
187
if rpp.aml_inv_id and rpp.aml_inv_id.id:
188
res[rpp.id] = rpp.aml_inv_id.quantity
191
def _get_invoice_price(self, cr, uid, ids, name, arg, context={}):
193
for rpp in self.browse(cr, uid, ids, context):
195
if rpp.invoice_line_id and rpp.invoice_line_id.id:
196
res[rpp.id] = rpp.invoice_line_id.price_unit
197
if rpp.invoice_line_id.invoice_id.type in\
198
['in_invoice', 'in_refund']:
199
res[rpp.id] = rpp.invoice_line_id.price_subtotal / \
200
rpp.invoice_line_id.quantity or \
201
rpp.invoice_line_id.price_unit
204
def _get_aml_cost_price(self, cr, uid, ids, name, arg, context={}):
206
for rpp in self.browse(cr, uid, ids, context):
208
if rpp.aml_cost_id and rpp.aml_cost_id.id:
209
if rpp.aml_cost_id.quantity and rpp.aml_cost_id.quantity > 0:
211
if rpp.aml_cost_id.debit:
212
amount = rpp.aml_cost_id.debit
214
amount = rpp.aml_cost_id.credit
215
price_unit = amount/rpp.aml_cost_id.quantity
216
res[rpp.id] = price_unit
219
def _get_aml_inv_price(self, cr, uid, ids, name, arg, context={}):
221
for rpp in self.browse(cr, uid, ids, context):
223
if rpp.aml_inv_id and rpp.aml_inv_id.id:
224
if rpp.aml_inv_id.quantity and rpp.aml_inv_id.quantity > 0:
226
if rpp.aml_inv_id.debit:
227
amount = rpp.aml_inv_id.debit
229
amount = rpp.aml_inv_id.credit
230
price_unit = amount/rpp.aml_inv_id.quantity
231
res[rpp.id] = price_unit
234
def _get_prod_stock_before(self, cr, uid, ids, name, arg, context={}):
236
prod_obj = self.pool.get('product.product')
239
for line in self.browse(cr, uid, ids, context=context):
240
# print 'fechaxxx: ',line.name
241
startf = datetime.datetime.fromtimestamp(time.mktime(
242
time.strptime(line.name, "%Y-%m-%d:%H:%M:%S")))
243
# print 'ffff: ',startf
244
start = DateTime(int(startf.year), 1, 1)
246
# DateTime(int(startf.year),int(startf.month),int(startf.day))
247
end = startf - datetime.timedelta(seconds=1)
248
d1 = start.strftime('%Y-%m-%d %H:%M:%S')
249
d2 = end.strftime('%Y-%m-%d %H:%M:%S')
250
# print 'd1xxxxxxx: ',d1
251
# print 'd2yyyyyyy: ',d2
253
c.update({'location': loc_ids, 'from_date': d1, 'to_date': d2})
254
res.setdefault(line.id, 0.0)
255
if line.product_id and line.product_id.id:
256
prd = prod_obj.browse(cr, uid, line.product_id.id, context=c)
257
res[line.id] = prd.qty_available
260
def _get_prod_stock_after(self, cr, uid, ids, name, arg, context={}):
262
prod_obj = self.pool.get('product.product')
265
for line in self.browse(cr, uid, ids, context=context):
266
startf = datetime.datetime.fromtimestamp(time.mktime(
267
time.strptime(line.name, "%Y-%m-%d:%H:%M:%S")))
268
start = DateTime(int(startf.year), 1, 1)
269
end = startf + datetime.timedelta(seconds=1)
270
d1 = start.strftime('%Y-%m-%d %H:%M:%S')
271
d2 = end.strftime('%Y-%m-%d %H:%M:%S')
273
c.update({'location': loc_ids, 'from_date': d1, 'to_date': d2})
274
res.setdefault(line.id, 0.0)
275
if line.product_id and line.product_id.id:
276
prd = prod_obj.browse(cr, uid, line.product_id.id, context=c)
277
res[line.id] = prd.qty_available
280
def _get_invoice(self, cr, uid, ids, name, arg, context={}):
282
for rpp in self.browse(cr, uid, ids, context):
284
if rpp.invoice_line_id and rpp.invoice_line_id.id:
285
res[rpp.id] = rpp.invoice_line_id.invoice_id.id
288
def _get_date_invoice(self, cr, uid, ids, name, arg, context={}):
290
for rpp in self.browse(cr, uid, ids, context):
292
if rpp.invoice_line_id and rpp.invoice_line_id.id:
293
if rpp.invoice_line_id.invoice_id.date_invoice:
294
date = rpp.invoice_line_id.invoice_id.date_invoice
295
startf = datetime.datetime.fromtimestamp(
296
time.mktime(time.strptime(date, "%Y-%m-%d")))
297
res[rpp.id] = startf.strftime('%Y-%m-%d:16:00:%S')
300
def _get_stock_invoice(self, cr, uid, ids, name, arg, context={}):
302
prod_obj = self.pool.get('product.product')
305
for line in self.browse(cr, uid, ids, context=context):
306
res.setdefault(line.id, 0.0)
308
startf = datetime.datetime.fromtimestamp(time.mktime(
309
time.strptime(line.date_inv, "%Y-%m-%d:%H:%M:%S")))
310
start = DateTime(int(startf.year), 1, 1)
311
end = startf - datetime.timedelta(seconds=1)
312
d1 = start.strftime('%Y-%m-%d %H:%M:%S')
313
d2 = end.strftime('%Y-%m-%d %H:%M:%S')
315
c.update({'location': loc_ids, 'from_date': d1, 'to_date': d2})
316
if line.product_id and line.product_id.id:
317
prd = prod_obj.browse(
318
cr, uid, line.product_id.id, context=c)
319
res[line.id] = prd.qty_available
322
def _compute_subtotal(self, cr, uid, ids, name, arg, context={}):
330
for line in self.browse(cr, uid, ids, context=context):
332
res.setdefault(line.id, 0.0)
334
if line.invoice_id and line.invoice_id.id:
335
if line.location_dest_id.id == loc_ids and \
336
line.invoice_id.type == 'in_invoice':
337
subtot = line.picking_qty*line.invoice_price_unit
339
if line.location_id.id == loc_ids and \
340
line.invoice_id.type == 'out_invoice':
341
subtot = line.picking_qty*avg
343
if line.location_dest_id.id == loc_ids and\
344
line.invoice_id.type == 'in_refund':
345
if line.invoice_id.parent_id and\
346
line.invoice_id.parent_id.id:
347
for il in line.invoice_id.parent_id.invoice_line:
348
if il.product_id.id == line.product_id.id:
349
subtot = line.picking_qty*il.price_unit
351
res[line.id] = subtot
354
def _compute_total(self, cr, uid, ids, name, arg, context={}):
361
for line in self.browse(cr, uid, ids, context=context):
362
tot.setdefault(line.product_id.id, 'xxx')
363
res.setdefault(line.id, 0.0)
365
if tot[line.product_id.id] == 'xxx':
366
tot[line.product_id.id] = avg*q
368
if line.invoice_id and line.invoice_id.id:
369
if line.location_dest_id.id == loc_ids and\
370
line.invoice_id.type == 'in_invoice':
371
tot[line.product_id.id] += line.subtotal
373
if line.location_id.id == loc_ids and\
374
line.invoice_id.type == 'out_invoice':
375
tot[line.product_id.id] -= line.subtotal
377
if line.location_dest_id.id == loc_ids and\
378
line.invoice_id.type == 'in_refund':
379
tot[line.product_id.id] -= line.subtotal
380
res[line.id] = tot[line.product_id.id]
383
def _get_aml_inv(self, cr, uid, ids, field_name, arg, context={}):
385
aml_obj = self.pool.get('account.move.line')
386
for rpp in self.browse(cr, uid, ids, context):
388
if rpp.invoice_line_id and rpp.invoice_line_id.id:
389
moves = self.aml_inv_get(cr, uid, [rpp.invoice_line_id.id])
391
aml = aml_obj.browse(cr, uid, moves[0], context)
392
result[rpp.id] = (aml.id, aml.name)
394
moves = self.aml_internal_get(cr, uid, [rpp.stk_mov_id.id])
396
aml = aml_obj.browse(cr, uid, moves[1], context)
397
result[rpp.id] = (aml.id, aml.name)
401
def aml_cost_get(self, cr, uid, il_id):
403
il_obj = self.pool.get('account.invoice.line')
404
res = il_obj.move_line_id_cost_get(cr, uid, il_id)
407
def aml_internal_get(self, cr, uid, sm_id):
409
sm_obj = self.pool.get('stock.move')
410
res = sm_obj.move_line_get(cr, uid, sm_id)
413
def aml_inv_get(self, cr, uid, il_id):
415
il_obj = self.pool.get('account.invoice.line')
416
res = il_obj.move_line_id_inv_get(cr, uid, il_id)
419
def purchase_invoice_get(self, cr, uid, purchase_id, product_id):
423
FROM account_invoice i
424
INNER JOIN purchase_invoice_rel r
426
INNER JOIN account_invoice_line l
428
WHERE r.purchase_id=%s
430
""", (purchase_id, product_id))
431
res = map(lambda x: x[0], cr.fetchall())
434
_name = "report.profit.picking"
435
_description = "Move by Picking"
438
'name': fields.char('Date', size=20, readonly=True, select=True),
439
'date': fields.date('Date Done', readonly=True),
440
'year': fields.char('Year', size=4, readonly=True),
441
'month': fields.selection([('01', 'January'),
453
'Month', readonly=True),
454
'day': fields.char('Day', size=128, readonly=True),
455
'picking_id': fields.many2one('stock.picking', 'Picking',
456
readonly=True, select=True),
457
'purchase_line_id': fields.many2one('purchase.order.line',
458
'Purchase Line', readonly=True,
460
'sale_line_id': fields.many2one('sale.order.line', 'Sale Line',
461
readonly=True, select=True),
462
'product_id': fields.many2one('product.product', 'Product',
463
readonly=True, select=True),
464
'location_id': fields.many2one('stock.location', 'Source Location',
465
readonly=True, select=True),
466
'location_dest_id': fields.many2one('stock.location', 'Dest. Location',
467
readonly=True, select=True),
468
'stk_mov_id': fields.many2one('stock.move', 'Picking line',
469
readonly=True, select=True),
470
'picking_qty': fields.float('Picking quantity', readonly=True),
471
'type': fields.selection([
472
('out', 'Sending Goods'),
473
('in', 'Getting Goods'),
474
('internal', 'Internal'),
475
('delivery', 'Delivery')
476
], 'Type', readonly=True, select=True),
477
'state': fields.selection([
479
('waiting', 'Waiting'),
480
('confirmed', 'Confirmed'),
481
('assigned', 'Available'),
483
('cancel', 'Cancelled')
484
], 'Status', readonly=True, select=True),
485
'aml_cost_id': fields.function(_get_aml_cost, method=True,
487
relation='account.move.line',
488
string='Cost entry'),
489
'invoice_line_id': fields.function(_get_invoice_line,
490
method=True, type='many2one',
491
relation='account.invoice.line',
492
string='Invoice line'),
493
'invoice_qty': fields.function(_get_invoice_qty, method=True,
494
type='float', string='Invoice quantity',
496
dp.get_precision('Account')),
497
'aml_cost_qty': fields.function(_get_aml_cost_qty, method=True,
499
string='Cost entry quantity',
501
dp.get_precision('Account')),
502
'invoice_price_unit': fields.function(_get_invoice_price, method=True,
504
string='Invoice price unit',
506
dp.get_precision('Account')),
507
'aml_cost_price_unit': fields.function(_get_aml_cost_price,
508
method=True, type='float',
509
string='Cost entry price unit',
511
dp.get_precision('Account')),
512
'invoice_id': fields.function(_get_invoice, method=True,
514
relation='account.invoice',
516
'stock_before': fields.function(_get_prod_stock_before, method=True,
517
type='float', string='Stock before',
519
dp.get_precision('Account')),
520
'stock_after': fields.function(_get_prod_stock_after, method=True,
521
type='float', string='Stock after',
523
dp.get_precision('Account')),
524
'date_inv': fields.function(_get_date_invoice, method=True,
525
type='char', string='Date invoice',
527
'stock_invoice': fields.function(_get_stock_invoice, method=True,
528
type='float', string='Stock invoice',
530
dp.get_precision('Account')),
531
'subtotal': fields.function(_compute_subtotal, method=True,
532
type='float', string='Subtotal',
534
dp.get_precision('Account')),
535
'total': fields.function(_compute_total, method=True, type='float',
537
digits_compute=dp.get_precision('Account')),
538
'aml_inv_id': fields.function(_get_aml_inv, method=True,
540
relation='account.move.line',
542
'aml_inv_price_unit': fields.function(_get_aml_inv_price, method=True,
544
string='Inv entry price unit',
546
dp.get_precision('Account')),
547
'aml_inv_qty': fields.function(_get_aml_inv_qty, method=True,
549
string='Inv entry quantity',
551
dp.get_precision('Account')),
555
drop_view_if_exists(cr, 'report_profit_picking')
557
create or replace view report_profit_picking as (
560
to_char(sm.date, 'YYYY-MM-DD:HH24:MI:SS') as name,
562
to_char(sm.date, 'YYYY') as year,
563
to_char(sm.date, 'MM') as month,
564
to_char(sm.date, 'YYYY-MM-DD') as day,
565
sm.picking_id as picking_id,
567
sm.purchase_line_id as purchase_line_id,
568
sm.sale_line_id as sale_line_id,
569
sm.product_id as product_id,
570
sm.location_id as location_id,
571
sm.location_dest_id as location_dest_id,
573
sm.product_qty as picking_qty,
575
from stock_picking sp
576
right join stock_move sm on (sp.id=sm.picking_id)
577
left join product_product d on (d.id=sm.product_id)
578
left join product_template pt on (pt.id=d.product_tmpl_id)
579
where sm.state='done' and pt.type!='service'
585
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: