20
20
##############################################################################
22
22
from osv import osv, fields
23
from tools.translate import _
23
from order_types import ORDER_PRIORITY, ORDER_CATEGORY
25
25
from datetime import datetime, timedelta
26
26
from dateutil.relativedelta import relativedelta
27
from mx.DateTime import *
28
from tools.translate import _
28
30
class sale_order(osv.osv):
29
32
_inherit = 'sale.order'
34
def copy(self, cr, uid, id, default, context={}):
36
Delete the loan_id field on the new sale.order
38
return super(sale_order, self).copy(cr, uid, id, default={'loan_id': False}, context=context)
40
#@@@override sale.sale_order._invoiced
41
def _invoiced(self, cr, uid, ids, name, arg, context={}):
43
Return True is the sale order is an uninvoiced order
45
partner_obj = self.pool.get('res.partner')
49
for sale in self.browse(cr, uid, ids):
51
partner = partner_obj.browse(cr, uid, [sale.partner_id.id])[0]
52
if sale.state != 'draft' and (sale.order_type != 'regular' or (partner and partner.partner_type == 'internal')):
56
for invoice in sale.invoice_ids:
57
if invoice.state != 'paid':
60
if not sale.invoice_ids:
65
#@@@override sale.sale_order._invoiced_search
66
def _invoiced_search(self, cursor, user, obj, name, args, context={}):
75
clause += 'AND inv.state = \'paid\' OR (sale.state != \'draft\' AND (sale.order_type != \'regular\' OR part.partner_type = \'internal\'))'
77
clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\' AND inv.state <> \'paid\' AND sale.order_type = \'regular\''
80
cursor.execute('SELECT rel.order_id ' \
81
'FROM sale_order_invoice_rel AS rel, account_invoice AS inv, sale_order AS sale, res_partner AS part '+ sale_clause + \
82
'WHERE rel.invoice_id = inv.id AND rel.order_id = sale.id AND sale.partner_id = part.id ' + clause)
83
res = cursor.fetchall()
85
cursor.execute('SELECT sale.id ' \
86
'FROM sale_order AS sale, res_partner AS part ' \
87
'WHERE sale.id NOT IN ' \
88
'(SELECT rel.order_id ' \
89
'FROM sale_order_invoice_rel AS rel) and sale.state != \'cancel\'' \
90
'AND sale.partner_id = part.id ' \
91
'AND sale.order_type = \'regular\' AND part.partner_type != \'internal\'')
92
res.extend(cursor.fetchall())
94
return [('id', '=', 0)]
95
return [('id', 'in', [x[0] for x in res])]
98
#@@@override sale.sale_order._invoiced_rate
99
def _invoiced_rate(self, cursor, user, ids, name, arg, context=None):
101
for sale in self.browse(cursor, user, ids, context=context):
106
for invoice in sale.invoice_ids:
107
if invoice.state not in ('draft', 'cancel'):
108
tot += invoice.amount_untaxed
110
res[sale.id] = min(100.0, tot * 100.0 / (sale.amount_untaxed or 1.00))
116
def _get_noinvoice(self, cr, uid, ids, name, arg, context={}):
118
for sale in self.browse(cr, uid, ids):
119
res[sale.id] = sale.order_type != 'regular' or sale.partner_id.partner_type == 'internal'
123
'order_type': fields.selection([('regular', 'Regular'), ('donation_exp', 'Donation before expiry'),
124
('donation_st', 'Standard donation (for help)'), ('loan', 'Loan'),],
125
string='Order Type', required=True, readonly=True, states={'draft': [('readonly', False)]}),
126
'loan_id': fields.many2one('purchase.order', string='Linked loan', readonly=True),
127
'priority': fields.selection(ORDER_PRIORITY, string='Priority', readonly=True, states={'draft': [('readonly', False)]}),
128
'categ': fields.selection(ORDER_CATEGORY, string='Order category', required=True, readonly=True, states={'draft': [('readonly', False)]}),
129
'details': fields.char(size=30, string='Details', readonly=True, states={'draft': [('readonly', False)]}),
130
'invoiced': fields.function(_invoiced, method=True, string='Paid',
131
fnct_search=_invoiced_search, type='boolean', help="It indicates that an invoice has been paid."),
132
'invoiced_rate': fields.function(_invoiced_rate, method=True, string='Invoiced', type='float'),
133
'noinvoice': fields.function(_get_noinvoice, method=True, string="Don't create an invoice", type='boolean'),
134
'loan_duration': fields.integer(string='Loan duration', help='Loan duration in months', readonly=True, states={'draft': [('readonly', False)]}),
138
'order_type': lambda *a: 'regular',
139
'priority': lambda *a: 'normal',
140
'categ': lambda *a: 'mixed',
141
'loan_duration': lambda *a: 2,
146
def action_wait(self, cr, uid, ids, *args):
148
Checks if the invoice should be create from the sale order
151
line_obj = self.pool.get('sale.order.line')
153
if isinstance(ids, (int, long)):
156
for order in self.browse(cr, uid, ids):
157
if order.partner_id.partner_type == 'internal' and order.order_type == 'regular':
158
self.write(cr, uid, [order.id], {'order_policy': 'manual'})
159
for line in order.order_line:
160
lines.append(line.id)
161
elif order.order_type in ['donation_exp', 'donation_st', 'loan']:
162
self.write(cr, uid, [order.id], {'order_policy': 'manual'})
163
for line in order.order_line:
164
lines.append(line.id)
166
self.write(cr, uid, [order.id], {'order_policy': 'manual'})
168
line_obj.write(cr, uid, lines, {'invoiced': 1})
170
return super(sale_order, self).action_wait(cr, uid, ids, args)
172
def action_purchase_order_create(self, cr, uid, ids, context={}):
174
Create a purchase order as counterpart for the loan.
176
if isinstance(ids, (int, long)):
179
purchase_obj = self.pool.get('purchase.order')
180
purchase_line_obj = self.pool.get('purchase.order.line')
181
partner_obj = self.pool.get('res.partner')
183
for order in self.browse(cr, uid, ids):
184
two_months = today() + RelativeDateTime(months=+2)
185
order_id = purchase_obj.create(cr, uid, {'partner_id': order.partner_id.id,
186
'partner_address_id': partner_obj.address_get(cr, uid, [order.partner_id.id], ['contact'])['contact'],
187
'pricelist_id': order.partner_id.property_product_pricelist_purchase.id,
189
'loan_duration': order.loan_duration,
190
'origin': order.name,
191
'order_type': 'loan',
192
'delivery_requested_date': (today() + RelativeDateTime(months=+order.loan_duration)).strftime('%Y-%m-%d'),
193
'categ': order.categ,
194
'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
195
'priority': order.priority,})
196
for line in order.order_line:
197
purchase_line_obj.create(cr, uid, {'product_id': line.product_id and line.product_id.id or False,
198
'product_uom': line.product_uom.id,
199
'order_id': order_id,
200
'price_unit': line.price_unit,
201
'product_qty': line.product_uom_qty,
202
'date_planned': (today() + RelativeDateTime(months=+order.loan_duration)).strftime('%Y-%m-%d'),
204
self.write(cr, uid, [order.id], {'loan_id': order_id})
206
purchase = purchase_obj.browse(cr, uid, order_id)
208
message = _("Loan counterpart '%s' is created.") % (purchase.name,)
210
purchase_obj.log(cr, uid, order_id, message)
214
def has_stockable_products(self, cr, uid, ids, *args):
216
Override the has_stockable_product to return False
217
when the internal_type of the order is 'direct'
219
for order in self.browse(cr, uid, ids):
220
if order.order_type != 'direct':
221
return super(sale_order, self).has_stockable_product(cr, uid, ids, args)
225
#@@@override sale.sale_order.action_invoice_end
226
def action_invoice_end(self, cr, uid, ids, context=None):
228
Modified to set lines invoiced when order_type is not regular
230
for order in self.browse(cr, uid, ids, context=context):
232
# Update the sale order lines state (and invoiced flag).
234
for line in order.order_line:
237
# Check if the line is invoiced (has asociated invoice
238
# lines from non-cancelled invoices).
240
invoiced = order.noinvoice
242
for iline in line.invoice_lines:
243
if iline.invoice_id and iline.invoice_id.state != 'cancel':
246
if line.invoiced != invoiced:
247
vals['invoiced'] = invoiced
248
# If the line was in exception state, now it gets confirmed.
249
if line.state == 'exception':
250
vals['state'] = 'confirmed'
251
# Update the line (only when needed).
253
self.pool.get('sale.order.line').write(cr, uid, [line.id], vals, context=context)
255
# Update the sales order state.
257
if order.state == 'invoice_except':
258
self.write(cr, uid, [order.id], {'state': 'progress'}, context=context)
32
262
def _hook_ship_create_stock_move(self, cr, uid, ids, move_data, order_line, *args, **kwargs):