from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import time
-from openerp import pooler
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP, float_compare
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'sale.shop', context=c),
}
-sale_shop()
class sale_order(osv.osv):
_name = "sale.order"
'order_policy': fields.selection([
('manual', 'On Demand'),
], 'Create Invoice', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
- help="""This field controls how invoice and delivery operations are synchronized.
- - With 'Before Delivery', a draft invoice is created, and it must be paid before delivery."""),
+ help="""This field controls how invoice and delivery operations are synchronized."""),
'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="Pricelist for current sales order."),
'currency_id': fields.related('pricelist_id', 'currency_id', type="many2one", relation="res.currency", string="Currency", readonly=True, required=True),
'project_id': fields.many2one('account.analytic.account', 'Contract / Analytic', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, help="The analytic account related to a sales order."),
if s['state'] in ['draft', 'cancel']:
unlink_ids.append(s['id'])
else:
- raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sales order, you must cancel it before !'))
+ raise osv.except_osv(_('Invalid Action!'), _('In order to delete a confirmed sales order, you must cancel it before!'))
return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'payment_term': False, 'fiscal_position': False}}
part = self.pool.get('res.partner').browse(cr, uid, part, context=context)
- #if the chosen partner is not a company and has a parent company, use the parent to choose the delivery, the
- #invoicing addresses and all the fields related to the partner.
- if part.parent_id and not part.is_company:
- part = part.parent_id
addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact'])
pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
payment_term = part.property_payment_term and part.property_payment_term.id or False
return {'value': val}
def create(self, cr, uid, vals, context=None):
- if vals.get('name','/')=='/':
+ if context is None:
+ context = {}
+ if vals.get('name', '/') == '/':
vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/'
- context = dict(context, mail_create_nolog=True)
- res = super(sale_order, self).create(cr, uid, vals, context=context)
- self.message_post(cr, uid, [res], body=_("Quotation created"), context=context)
- return res
+ context.update({'mail_create_nolog': True})
+ new_id = super(sale_order, self).create(cr, uid, vals, context=context)
+ self.message_post(cr, uid, [new_id], body=_("Quotation created"), context=context)
+ return new_id
def button_dummy(self, cr, uid, ids, context=None):
return True
invoice_ref += o.name + '|'
self.write(cr, uid, [o.id], {'state': 'progress'})
cr.execute('insert into sale_order_invoice_rel (order_id,invoice_id) values (%s,%s)', (o.id, res))
+ #remove last '|' in invoice_ref
+ if len(invoice_ref) >= 1:
+ invoice_ref = invoice_ref[:-1]
invoice.write(cr, uid, [res], {'origin': invoice_ref, 'name': invoice_ref})
else:
for order, il in val:
_description = 'Sales Order Line'
_columns = {
'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
- 'name': fields.text('Description', required=True, select=True, readonly=True, states={'draft': [('readonly', False)]}),
+ 'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
- 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
+ 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True, readonly=True, states={'draft': [('readonly', False)]}),
'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean',
- store={'account.invoice': (_order_lines_from_invoice, ['state'], 10)}),
+ store={
+ 'account.invoice': (_order_lines_from_invoice, ['state'], 10),
+ 'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}),
'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."),
'salesman_id':fields.related('order_id', 'user_id', type='many2one', relation='res.users', store=True, string='Salesperson'),
'company_id': fields.related('order_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
}
- _order = 'order_id desc, sequence'
+ _order = 'order_id desc, sequence, id'
_defaults = {
'product_uom' : _get_uom_id,
'discount': 0.0,
vals = self._prepare_order_line_invoice_line(cr, uid, line, False, context)
if vals:
inv_id = self.pool.get('account.invoice.line').create(cr, uid, vals, context=context)
- cr.execute('insert into sale_order_line_invoice_rel (order_line_id,invoice_id) values (%s,%s)', (line.id, inv_id))
+ self.write(cr, uid, [line.id], {'invoice_lines': [(4, inv_id)]}, context=context)
sales.add(line.order_id.id)
create_ids.append(inv_id)
# Trigger workflow events
context = context or {}
lang = lang or context.get('lang',False)
if not partner_id:
- raise osv.except_osv(_('No Customer Defined !'), _('Before choosing a product,\n select a customer in the sales form.'))
+ raise osv.except_osv(_('No Customer Defined!'), _('Before choosing a product,\n select a customer in the sales form.'))
warning = {}
product_uom_obj = self.pool.get('product.uom')
partner_obj = self.pool.get('res.partner')
'sale_note': fields.text('Default Terms and Conditions', translate=True, help="Default terms and conditions for quotations."),
}
+
class mail_compose_message(osv.Model):
_inherit = 'mail.compose.message'
self.pool.get('sale.order').signal_quotation_sent(cr, uid, [context['default_res_id']])
return super(mail_compose_message, self).send_mail(cr, uid, ids, context=context)
+
class account_invoice(osv.Model):
_inherit = 'account.invoice'
-
+
def confirm_paid(self, cr, uid, ids, context=None):
- so_ids = self.pool.get('sale.order').search(cr,uid,[('invoice_ids','in',ids)],context)
- res = super(account_invoice, self).confirm_paid(cr, uid, ids, context=None)
- self.pool.get('sale.order').message_post(cr, uid, so_ids, body=_("Invoice paid"), context=context)
+ sale_order_obj = self.pool.get('sale.order')
+ res = super(account_invoice, self).confirm_paid(cr, uid, ids, context=context)
+ so_ids = sale_order_obj.search(cr, uid, [('invoice_ids', 'in', ids)], context=context)
+ if so_ids:
+ sale_order_obj.message_post(cr, uid, so_ids, body=_("Invoice paid"), context=context)
return res
-
+
+ def unlink(self, cr, uid, ids, context=None):
+ """ Overwrite unlink method of account invoice to send a trigger to the sale workflow upon invoice deletion """
+ invoice_ids = self.search(cr, uid, [('id', 'in', ids), ('state', 'in', ['draft', 'cancel'])], context=context)
+ #if we can't cancel all invoices, do nothing
+ if len(invoice_ids) == len(ids):
+ #Cancel invoice(s) first before deleting them so that if any sale order is associated with them
+ #it will trigger the workflow to put the sale order in an 'invoice exception' state
+ wf_service = netsvc.LocalService("workflow")
+ for id in ids:
+ wf_service.trg_validate(uid, 'account.invoice', id, 'invoice_cancel', cr)
+ return super(account_invoice, self).unlink(cr, uid, ids, context=context)
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: