wip purchase_collective.
ToDo: Plantillas de correo, crear picking por supplier
This commit is contained in:
parent
d2ac963ee1
commit
4abeea64a5
13 changed files with 836 additions and 0 deletions
3
purchase_collective/models/__init__.py
Normal file
3
purchase_collective/models/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from . import purchase_collective
|
||||
from . import sale_order
|
||||
|
||||
254
purchase_collective/models/purchase_collective.py
Normal file
254
purchase_collective/models/purchase_collective.py
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
import pytz
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from operator import attrgetter
|
||||
|
||||
from odoo import models, fields, api, osv, _
|
||||
from odoo.exceptions import Warning
|
||||
from odoo.tools.safe_eval import safe_eval as eval
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class PurchaseCollectiveOrder(models.Model):
|
||||
_name = 'purchase_collective.order'
|
||||
_inherit = ['purchase.order']
|
||||
_description = 'Collective Purchases'
|
||||
|
||||
sales_order_lines = fields.One2many('sale.order','cp_order_id','Collective Order Lines',states={'approved':[('readonly',True)],'done':[('readonly',True)]},copy=True )
|
||||
deadline_date = fields.Date(string='Order Deadline', required=True, help="End date of the order. Place your orders before this date")
|
||||
amount_untaxed = fields.Float('Amount untaxed')
|
||||
amount_tax = fields.Float('Taxes')
|
||||
amount_total = fields.Float('Amount Total')
|
||||
wh_id = fields.Many2one('stock.warehouse',string="Almacén asociado",help="El almacén central de distribución.")
|
||||
qty_min =fields.Float('Cantidad mínima del pedido', required=True, help='Cantidad mínima del pedido requerida para ejecutar la orden de compra')
|
||||
|
||||
#@api.onchange('sales_order_lines')
|
||||
def onchange_order_line(self, args=None):
|
||||
_logger.info("onchange_order_lines -- args: %s" %(args))
|
||||
res = {
|
||||
'amount_untaxed': 0.0,
|
||||
'amount_tax': 0.0,
|
||||
'amount_total': 0.0,
|
||||
}
|
||||
val = val1 = 0.0
|
||||
order_list = self.sales_order_lines
|
||||
#_logger.info("order %s " %order.id)
|
||||
val_tax = 0.0
|
||||
val_untax = 0.0
|
||||
if order_list:
|
||||
cur = self.pricelist_id.currency_id
|
||||
for line in order.sales_order_lines:
|
||||
if line.state in ['done','approved']:
|
||||
val += line.amount_total
|
||||
#val_tax += val.get('amount_tax',0.0)
|
||||
#val_untax += val.get('amount_untaxed',0.0)
|
||||
|
||||
res['amount_tax'] = cur.round(val_tax)
|
||||
res['amount_untaxed'] = val
|
||||
res['amount_total']= val
|
||||
|
||||
#_logger.info("Res : %s " %res)
|
||||
|
||||
order.write({'amount_untaxed': res['amount_untaxed']})
|
||||
order.write({'amount_tax': res['amount_tax']})
|
||||
order.write({'amount_total': res['amount_total']})
|
||||
_logger.info("res : %s" %(res))
|
||||
_logger.warning("returning : %s" %res)
|
||||
return res
|
||||
|
||||
|
||||
@api.multi
|
||||
def subscribe(self, partner):
|
||||
self.message_subscribe(partner_ids=[(partner.id)])
|
||||
self.message_post(body=("Order line created by %s" %(partner.name)))
|
||||
|
||||
@api.multi
|
||||
def button_details(self):
|
||||
context = self.env.context.copy()
|
||||
view_id = self.env.ref(
|
||||
'sale.'
|
||||
'view_order_form').id
|
||||
|
||||
context['default_is_cp'] = True
|
||||
context['default_cp_order_id'] = self.id
|
||||
context['supplier'] = self.partner_id
|
||||
#context['default_partner_id'] = self.partner_id.id
|
||||
context['default_pricelist_id'] = self.pricelist_id.id
|
||||
context['default_order_date'] = self.date_order
|
||||
context['default_date_planned'] = self.deadline_date
|
||||
context['view_buttons'] = True
|
||||
#context['fiscal_position'] = self.fiscal_position
|
||||
#context['state'] = self.state
|
||||
#context['parent'] = self.id
|
||||
|
||||
#partial_id = self.pool.get("purchase.collective.order.line").create(context=context)
|
||||
|
||||
view = {
|
||||
'name': _('Details'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'sale.order',
|
||||
'view_id': view_id,
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
'readonly': False,
|
||||
#'res_id': partial_id,
|
||||
'context': context
|
||||
}
|
||||
return view
|
||||
|
||||
def _get_order(self, ids):
|
||||
result = {}
|
||||
for line in self.pool.get('sale.order').browse(ids):
|
||||
result[line.id] = True
|
||||
return result.keys()
|
||||
"""
|
||||
def create(self, vals=None):
|
||||
_logger.warning("Creating order %s" %(vals))
|
||||
|
||||
if vals.get('name','/')=='/':
|
||||
vals['name'] = self.env['ir.sequence'].get('purchase_collective.order', context=context) or '/'
|
||||
if not vals.get('location_id'):
|
||||
for user_obj in self.env['res.users'].browse(uid, context=context):
|
||||
vals['location_id'] = user_obj.partner_id.property_stock_supplier.id
|
||||
#logging.info('adding location info %s' %vals.get('location_id'))
|
||||
if not vals.get('pricelist_id'):
|
||||
for user_obj in self.env['res.users'].browse(uid, context=context):
|
||||
vals['pricelist_id'] = user_obj.partner_id.property_product_pricelist.id
|
||||
#logging.info('adding pricelist %s' %vals.get('pricelist_id'))
|
||||
order = super(PurchaseCollectiveOrder, self).create(vals)
|
||||
return order
|
||||
"""
|
||||
|
||||
def unlink(self, ids):
|
||||
purchase_orders = self.read(ids, ['state'], context=context)
|
||||
unlink_ids = []
|
||||
for s in purchase_orders:
|
||||
if s['state'] in ['draft','cancel']:
|
||||
unlink_ids.append(s['id'])
|
||||
else:
|
||||
raise Warning(_('Invalid Action!'), _('In order to delete a purchase order, you must cancel it first.'))
|
||||
|
||||
# automatically sending subflow.delete upon deletion
|
||||
self.signal_workflow(unlink_ids, 'purchase_cancel')
|
||||
|
||||
return super(PurchaseCollectiveOrder, self).unlink(unlink_ids, context=context)
|
||||
|
||||
def copy(self, id, default=None, context=None):
|
||||
new_id = super(PurchaseCollectiveOrder, self).copy(id, default=default, context=context)
|
||||
for po in self.browse([new_id], context=context):
|
||||
for line in po.order_line:
|
||||
vals = self.env['purchase_collective.order_line'].onchange_product_id(
|
||||
line.id, po.pricelist_id.id, line.product_id.id, line.product_qty,
|
||||
line.product_uom.id, po.partner_id.id, date_order=po.date_order, context=context
|
||||
)
|
||||
if vals.get('value', {}).get('date_planned'):
|
||||
line.write({'date_planned': vals['value']['date_planned']})
|
||||
return new_id
|
||||
|
||||
def set_order_line_status(self, ids, status, context=None):
|
||||
"""
|
||||
line = self.pool.get('purchase_collective.order_line')
|
||||
order_line_ids = []
|
||||
proc_obj = self.pool.get('procurement.order')
|
||||
for order in self.browse(cr, uid, ids, context=context):
|
||||
if status in ('draft', 'cancel'):
|
||||
order_line_ids += [po_line.id for po_line in order.order_line]
|
||||
else: # Do not change the status of already cancelled lines
|
||||
order_line_ids += [po_line.id for po_line in order.order_line if po_line.state != 'cancel']
|
||||
if order_line_ids:
|
||||
line.write(cr, uid, order_line_ids, {'state': status}, context=context)
|
||||
if order_line_ids and status == 'cancel':
|
||||
procs = proc_obj.search(cr, uid, [('purchase_line_id', 'in', order_line_ids)], context=context)
|
||||
if procs:
|
||||
proc_obj.write(cr, uid, procs, {'state': 'exception'}, context=context)
|
||||
"""
|
||||
return True
|
||||
|
||||
def wkf_confirm_order(self, ids, context=None):
|
||||
#_logger.info("Confirmando orden : %s" %ids)
|
||||
todo = []
|
||||
for po in self.browse(ids, context=context):
|
||||
if not any(line.state != 'cancel' for line in po.order_line):
|
||||
raise Warning(_('Error!'),_('You cannot confirm a purchase order without any purchase order line.'))
|
||||
#if po.invoice_method == 'picking' and not any([l.product_id and l.product_id.type in ('product', 'consu') and l.state != 'cancel' for l in po.order_line]):
|
||||
# raise osv.except_osv(
|
||||
# _('Error!'),
|
||||
# _("You cannot confirm a purchase order with Invoice Control Method 'Based on incoming shipments' that doesn't contain any stockable item."))
|
||||
#for line in po.order_line:
|
||||
# if line.state=='draft':
|
||||
# todo.append(line.id)
|
||||
#self.pool.get('purchase_collective.order_line').action_confirm(cr, uid, todo, context)
|
||||
for id in ids:
|
||||
self.write(id, {'state' : 'confirmed', 'validator' : uid}, context=context)
|
||||
return True
|
||||
|
||||
def _set_po_lines_invoiced(self, ids, context=None):
|
||||
"""
|
||||
for po in self.browse(cr, uid, ids, context=context):
|
||||
is_invoiced = []
|
||||
if po.invoice_method == 'picking':
|
||||
# We determine the invoiced state of the PO line based on the invoiced state
|
||||
# of the associated moves. This should cover all possible cases:
|
||||
# - all moves are done and invoiced
|
||||
# - a PO line is split into multiple moves (e.g. if multiple pickings): some
|
||||
# pickings are done, some are in progress, some are cancelled
|
||||
for po_line in po.order_line:
|
||||
if (po_line.move_ids and
|
||||
all(move.state in ('done', 'cancel') for move in po_line.move_ids) and
|
||||
not all(move.state == 'cancel' for move in po_line.move_ids) and
|
||||
all(move.invoice_state == 'invoiced' for move in po_line.move_ids if move.state == 'done')
|
||||
and po_line.invoice_lines and all(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines)):
|
||||
is_invoiced.append(po_line.id)
|
||||
elif po_line.product_id.type == 'service':
|
||||
is_invoiced.append(po_line.id)
|
||||
else:
|
||||
for po_line in po.order_line:
|
||||
if (po_line.invoice_lines and
|
||||
all(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines)):
|
||||
is_invoiced.append(po_line.id)
|
||||
if is_invoiced:
|
||||
self.pool['purchase_collective.order_line'].write(cr, uid, is_invoiced, {'invoiced': True})
|
||||
workflow.trg_write(uid, 'purchase_colective.order', po.id, cr)
|
||||
"""
|
||||
|
||||
def action_picking_create(self, ids, context=None):
|
||||
for order in self.browse(ids):
|
||||
picking_vals = {
|
||||
'picking_type_id': order.picking_type_id.id,
|
||||
'partner_id': order.partner_id.id,
|
||||
'date': order.date_order,
|
||||
'origin': order.name
|
||||
}
|
||||
picking_id = self.env['stock.picking'].create(picking_vals, context=context)
|
||||
# esta llamada da fallo
|
||||
#self._create_stock_moves(cr, uid, order, order.order_line, picking_id, context=context)
|
||||
return picking_id
|
||||
|
||||
# get the picking type for the warehouse defined in order
|
||||
def _get_picking_in(self, context=None):
|
||||
type_obj = self.env['stock.picking.type']
|
||||
types = type_obj.search([('code', '=', 'incoming'),('warehouse_id.id','=',self.wh_id.id)], context=context)
|
||||
if not types:
|
||||
types = type_obj.search(cr, uid, [('code', '=', 'incoming'), ('warehouse_id', '=', False)], context=context)
|
||||
if not types:
|
||||
raise Warning(_('Error!'), _("Make sure you have defined the warehouse in the order!"))
|
||||
#logging.info("Types %s" %types)
|
||||
return types[0]
|
||||
|
||||
_defaults = {
|
||||
'date_order': fields.datetime.now,
|
||||
'state': 'draft',
|
||||
'name': '/',
|
||||
'shipped': 0,
|
||||
'invoice_method': 'order',
|
||||
'invoiced': 0,
|
||||
'picking_type_id': _get_picking_in,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
16
purchase_collective/models/sale_order.py
Normal file
16
purchase_collective/models/sale_order.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import random
|
||||
|
||||
from odoo import models, api, fields
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = "sale.order"
|
||||
|
||||
cp_order_id = fields.Many2one(
|
||||
'purchase_collective.order',
|
||||
string='Parent Collective Purchase',
|
||||
help='The collective purchase wich this order belongs',
|
||||
ondelete='restrict'
|
||||
)
|
||||
is_cp = fields.Boolean(string="Is part of a Collective Purchase")
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue