1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # POS Membership module for OpenERP, Manage membership payments from POS.
5 # Copyright (C) 2013 L'Heureux Cyclage (<http://www.heureux-cyclage.org>)
7 # This file is a part of POS Membership
9 # POS Membership is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # ReMembership is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ##############################################################################
23 from openerp
import netsvc
24 from openerp
.osv
import fields
, osv
25 from openerp
.tools
.translate
import _
27 from datetime
import datetime
, date
28 from dateutil
.relativedelta
import relativedelta
32 ('none', 'Non Member'),
33 ('canceled', 'Cancelled Member'),
34 ('old', 'Old Member'),
35 ('waiting', 'Waiting Member'),
36 ('invoiced', 'Invoiced Member'),
37 ('free', 'Free Member'),
38 ('paid', 'Paid Member'),
41 class pos_order(osv
.osv
):
42 _inherit
= 'pos.order'
44 def create_partner_from_ui(self
, cr
, uid
, partners
, context
=None):
45 print ("DEV: [pos_membership] [create_partner_from_ui] partners=%s" % str(partners
))
47 partner_obj
= self
.pool
.get('res.partner')
48 for tmp_partner
in partners
:
49 partner
= tmp_partner
['data']
50 partner_id
= partner_obj
.create(cr
, uid
, {
51 'name': partner
['name'],
53 partner_ids
.append(partner_id
)
54 #self.signal_paid(cr, uid, [partner_id])
57 def create_from_ui(self
, cr
, uid
, orders
, context
=None):
58 # NOTE: copied from openerp/addons/point_of_sale/point_of_sale.py
59 #_logger.info("orders: %r", orders)
60 print ("DEV: [pos_membership] [create_from_ui] order=", str(orders
))
62 for tmp_order
in orders
:
63 order
= tmp_order
['data']
64 order_id
= self
.create(cr
, uid
, {
65 'name': order
['name'],
66 'user_id': order
['user_id'] or False,
67 'session_id': order
['pos_session_id'],
68 'lines': order
['lines'],
69 'pos_reference':order
['name'],
70 #-- BEGIN pos_membership
71 'partner_id':order
['partner_id'],
72 #-- END pos_membership
75 for payments
in order
['statement_ids']:
77 self
.add_payment(cr
, uid
, order_id
, {
78 'amount': payment
['amount'] or 0.0,
79 'payment_date': payment
['name'],
80 'statement_id': payment
['statement_id'],
81 'payment_name': payment
.get('note', False),
82 'journal': payment
['journal_id']
85 if order
['amount_return']:
86 session
= self
.pool
.get('pos.session').browse(cr
, uid
, order
['pos_session_id'], context
=context
)
87 cash_journal
= session
.cash_journal_id
88 cash_statement
= False
90 cash_journal_ids
= filter(lambda st
: st
.journal_id
.type=='cash', session
.statement_ids
)
91 if not len(cash_journal_ids
):
92 raise osv
.except_osv( _('error!'),
93 _("No cash statement found for this session. Unable to record returned cash."))
94 cash_journal
= cash_journal_ids
[0].journal_id
95 self
.add_payment(cr
, uid
, order_id
, {
96 'amount': -order
['amount_return'],
97 'payment_date': time
.strftime('%Y-%m-%d %H:%M:%S'),
98 'payment_name': _('return'),
99 'journal': cash_journal
.id,
101 order_ids
.append(order_id
)
102 wf_service
= netsvc
.LocalService("workflow")
103 wf_service
.trg_validate(uid
, 'pos.order', order_id
, 'paid', cr
)
108 class membership_line(osv
.osv
):
110 _inherit
= 'membership.membership_line'
112 def _get_partners(self
, cr
, uid
, ids
, context
=None):
113 list_membership_line
= []
114 member_line_obj
= self
.pool
.get('membership.membership_line')
115 for partner
in self
.pool
.get('res.partner').browse(cr
, uid
, ids
, context
=context
):
116 if partner
.member_lines
:
117 list_membership_line
+= member_line_obj
.search(cr
, uid
, [('id', 'in', [ l
.id for l
in partner
.member_lines
])], context
=context
)
118 print("DEV: [pos_membership] [membership_line] [_get_partners]: ids=%s res=%s" % (str(ids
), str(list_membership_line
)))
119 return list_membership_line
121 #def _get_membership_lines_from_account_invoice(self, cr, uid, ids, context=None):
122 # list_membership_line = []
123 # member_line_obj = self.pool.get('membership.membership_line')
124 # for invoice in self.pool.get('account.invoice').browse(cr, uid, ids, context=context):
125 # if invoice.invoice_line:
126 # list_membership_line += member_line_obj.search(cr, uid, [('account_invoice_line', 'in', [ l.id for l in invoice.invoice_line])], context=context)
128 # { 'class': 'account.invoice'
129 # , 'ids': list_membership_line
131 # #res= list_membership_line
132 # print("DEV: [pos_membership] [membership_line] [_get_membership_lines_from_account_invoice]: res=%s" % str(res))
134 def _get_membership_lines_from_pos_order(self
, cr
, uid
, ids
, context
=None):
135 list_membership_line
= []
136 member_line_obj
= self
.pool
.get('membership.membership_line')
137 print("DEV: [pos_membership] [membership_line] [_get_membership_lines_from_pos_order]: ids=%s context=%s" % (str(ids
), str(context
)))
138 for order
in self
.pool
.get('pos.order').browse(cr
, uid
, ids
, context
=context
):
140 list_membership_line
+= member_line_obj
.search(cr
, uid
, [('pos_order_line', 'in', [ l
.id for l
in order
.lines
])], context
=context
)
142 # { 'class': 'pos.order'
143 # , 'ids': list_membership_line
145 res
= list_membership_line
146 print("DEV: [pos_membership] [membership_line] [_get_membership_lines_from_pos_order]: res=%s" % str(res
))
149 def _check_membership_date(self
, cr
, uid
, ids
, context
=None):
150 """Check if membership product is not in the past
151 @param self: The object pointer
152 @param cr: the current row, from the database cursor,
153 @param uid: the current user’s ID for security checks,
154 @param ids: List of Membership Line IDs
155 @param context: A standard dictionary for contextual values
159 SELECT MIN(ml.date_to - ai.date_invoice)
160 FROM membership_membership_line ml
161 JOIN account_invoice_line ail ON (
162 ml.account_invoice_line = ail.id
164 JOIN account_invoice ai ON (
165 ai.id = ail.invoice_id)
166 WHERE ml.id IN %s''', (tuple(ids
),))
169 if r
[0] and r
[0] < 0:
172 SELECT MIN(ml.date_to - ai.date_order)
173 FROM membership_membership_line ml
174 JOIN pos_order_line ail ON (
175 ml.pos_order_line = ail.id
177 JOIN pos_order ai ON (
178 ai.id = ail.order_id)
179 WHERE ml.id IN %s''', (tuple(ids
),))
182 if r
[0] and r
[0] < 0:
186 def _state(self
, cr
, uid
, ids
, name
, args
, context
=None):
187 """Compute the state lines
188 @param self: The object pointer
189 @param cr: the current row, from the database cursor,
190 @param uid: the current user’s ID for security checks,
191 @param ids: List of Membership Line IDs
192 @param name: Field Name
193 @param context: A standard dictionary for contextual values
194 @param return: Dictionary of state Value
197 print("DEV: [pos_membership] [membership_line] [_state]: name=%s ids=%s args=%s context=%s" % (str(name
), str(ids
), str(args
), str(context
)))
198 inv_obj
= self
.pool
.get('account.invoice')
199 ord_obj
= self
.pool
.get('pos.order')
200 for line
in self
.browse(cr
, uid
, ids
, context
=context
):
202 SELECT i.state, i.id FROM
206 SELECT l.invoice_id FROM
207 account_invoice_line l WHERE
209 SELECT ml.account_invoice_line FROM
210 membership_membership_line ml WHERE
215 fetched
= cr
.fetchone()
219 if (istate
== 'draft') |
(istate
== 'proforma'):
221 elif istate
== 'open':
223 elif istate
== 'paid':
225 inv
= inv_obj
.browse(cr
, uid
, fetched
[1], context
=context
)
226 for payment
in inv
.payment_ids
:
227 if payment
.invoice
and payment
.invoice
.type == 'out_refund':
229 elif istate
== 'cancel':
234 SELECT i.state, i.id, i.partner_id FROM
238 SELECT l.order_id FROM
239 pos_order_line l WHERE
241 SELECT ml.pos_order_line FROM
242 membership_membership_line ml WHERE
247 fetched
= cr
.fetchone()
249 res
[line
.id] = 'canceled'
251 partner_id
= fetched
[2]
252 self
.write(cr
, uid
, line
.id, {'partner': partner_id
})
253 # NOTE: force une mise à jour du partner,
254 # car il n'y en a pas lors de la création du pos.order
255 # dans le PoS (pour le moment)
258 if (ostate
== 'paid') |
(ostate
== 'draft'):
260 elif (ostate
== 'done') |
(ostate
== 'invoiced'):
262 # XXX: regarder l'équivalent de out_refund pour un pos.order
263 print("DEV: [pos_membership] [membership_line] [_state]: paid: TODO")
264 #inv = ord_obj.browse(cr, uid, fetched[1], context=context)
265 #for payment in inv.payment_ids:
266 # if payment.invoice and payment.invoice.type == 'out_refund':
268 elif ostate
== 'cancel':
271 print("DEV: [pos_membership] [membership_line] [_state]: return=%s" % (str(res
)))
274 def write(self
, cr
, uid
, ids
, vals
, context
=None):
275 print("DEV: [pos_membership] [membership_line] [write]: ids=%s vals=%s" % (str(ids
), str(vals
)))
276 member_line_obj
= self
.pool
.get('membership.membership_line')
277 res
= super(membership_line
, self
).write(cr
, uid
, ids
, vals
, context
=context
)
278 print("DEV: [pos_membership] [membership_line] [write]: res=%s" % str(res
))
281 def create(self
, cr
, uid
, vals
, context
=None):
282 print("DEV: [pos_membership] [membership_line] [create]: vals=%s" % (str(vals
)))
283 member_line_obj
= self
.pool
.get('membership.membership_line')
284 res
= super(membership_line
, self
).create(cr
, uid
, vals
, context
=context
)
285 print("DEV: [pos_membership] [membership_line] [create]: res=%s" % (str(res
)))
289 'pos_order_line': fields
.many2one('pos.order.line', 'POS Order line', readonly
=True),
290 'pos_order_id': fields
.related('pos_order_line', 'order_id', type='many2one', relation
='pos.order', string
='Order', readonly
=True),
291 'state': fields
.function(_state
,
292 string
='Membership Status', type='selection',
295 #'account.invoice': (_get_membership_lines_from_account_invoice, ['state'], 10),
296 # NOTE: déjà géré par membership.membership_line._get_membership_lines
297 'pos.order': (_get_membership_lines_from_pos_order
, ['state', 'partner_id'], 10),
298 'res.partner': (_get_partners
, ['membership_state'], 12),
299 }, help="""It indicates the membership status.
300 -Non Member: A member who has not applied for any membership.
301 -Cancelled Member: A member who has cancelled his membership.
302 -Old Member: A member whose membership date has expired.
303 -Waiting Member: A member who has applied for the membership and whose invoice is going to be created.
304 -Invoiced Member: A member whose invoice has been created.
305 -Paid Member: A member who has paid the membership amount."""),
306 'company_id': fields
.related('account_invoice_line', 'invoice_id', 'company_id', type="many2one", relation
="res.company", string
="Company", readonly
=True, store
=True)
307 # XXX: pos_order_line a aussi un company_id
312 class Partner(osv
.osv
):
314 _inherit
= 'res.partner'
316 def _get_partner_id(self
, cr
, uid
, ids
, context
=None):
317 print("DEV: [pos_membership] [Partner] [_get_partner_id]: ids=%s context=%s" % (str(ids
), str(context
)))
318 member_line_obj
= self
.pool
.get('membership.membership_line')
319 res_obj
= self
.pool
.get('res.partner')
320 data_inv
= member_line_obj
.browse(cr
, uid
, ids
, context
=context
)
322 for data
in data_inv
:
323 list_partner
.append(data
.partner
.id)
326 ids2
= res_obj
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
328 print("DEV: [pos_membership] [Partner] [_get_partner_id]: res=%s" % (str(list_partner
)))
331 def _get_invoice_partner(self
, cr
, uid
, ids
, context
=None):
332 inv_obj
= self
.pool
.get('account.invoice')
333 res_obj
= self
.pool
.get('res.partner')
334 data_inv
= inv_obj
.browse(cr
, uid
, ids
, context
=context
)
336 for data
in data_inv
:
337 list_partner
.append(data
.partner_id
.id)
340 ids2
= res_obj
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
344 def _get_order_partner(self
, cr
, uid
, ids
, context
=None):
345 ord_obj
= self
.pool
.get('pos.order')
346 res_obj
= self
.pool
.get('res.partner')
347 data_ord
= ord_obj
.browse(cr
, uid
, ids
, context
=context
)
349 for data
in data_ord
:
350 list_partner
.append(data
.partner_id
.id)
353 ids2
= res_obj
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
357 def _membership_state(self
, cr
, uid
, ids
, name
, args
, context
=None):
358 """This Function return Membership State For Given Partner.
359 @param self: The object pointer
360 @param cr: the current row, from the database cursor,
361 @param uid: the current user’s ID for security checks,
362 @param ids: List of Partner IDs
363 @param name: Field Name
364 @param context: A standard dictionary for contextual values
365 @param return: Dictionary of Membership state Value
368 print("DEV: [pos_membership] [Partner] [_membership_state]: name=%s ids=%s args=%s context=%s" % (str(name
), str(ids
), str(args
), str(context
)))
371 today
= time
.strftime('%Y-%m-%d')
373 print("DEV: [pos_membership] [Partner] [_membership_state] id=%s" % (str(id)))
374 partner_data
= self
.browse(cr
, uid
, id, context
=context
)
375 if partner_data
.membership_cancel
and today
> partner_data
.membership_cancel
:
378 if partner_data
.membership_stop
and today
> partner_data
.membership_stop
:
382 print("DEV: [pos_membership] [Partner] [_membership_state] [partner_data] [member_lines] [test]")
383 if partner_data
.member_lines
:
384 print("DEV: [pos_membership] [Partner] [_membership_state] [partner_data] [member_lines]" % ())
385 for mline
in partner_data
.member_lines
:
386 print("DEV: [pos_membership] [Partner] [_membership_state] [mline]: id=%s" % str(mline
.id))
387 if mline
.date_to
>= today
:
388 if mline
.account_invoice_line
and mline
.account_invoice_line
.invoice_id
:
389 istate
= mline
.account_invoice_line
.invoice_id
.state
390 print("DEV: [pos_membership] [Partner] [_membership_state] [account_invoice_line]: id=%s istate=%s" % (str(mline
.account_invoice_line
.invoice_id
.id), str(istate
)))
393 inv
= mline
.account_invoice_line
.invoice_id
394 for payment
in inv
.payment_ids
:
395 if payment
.invoice
.type == 'out_refund':
398 elif istate
== 'open' and s
!=0:
400 elif istate
== 'cancel' and s
!=0 and s
!=1:
402 elif (istate
== 'draft' or istate
== 'proforma') and s
!=0 and s
!=1:
404 elif mline
.pos_order_line
and mline
.pos_order_line
.order_id
:
405 ostate
= mline
.pos_order_line
.order_id
.state
406 print("DEV: [pos_membership] [Partner] [_membership_state] [pos_order_line]: id=%s ostate=%s" % (str(mline
.pos_order_line
.order_id
.id), str(ostate
)))
407 if ostate
== 'paid' and s
!=0 and s
!=1:
409 if ostate
== 'invoiced':
413 # XXX: regarder l'équivalent de out_refund pour un pos.order
414 print("DEV: [pos_membership] [partner] [_membership_state]: paid: TODO")
415 #inv = mline.pos_order_line.order_id
416 #for payment in inv.payment_ids:
417 # if payment.invoice.type == 'out_refund':
420 elif ostate
== 'open' and s
!=0:
421 # XXX: 1 donne invoiced, c'est pitet pas bon
422 print("DEV: [pos_membership] [partner] [_membership_state]: invoiced: TODO")
424 elif ostate
== 'cancel' and s
!=0 and s
!=1:
426 elif ostate
== 'draft' and s
!=0 and s
!=1:
429 for mline
in partner_data
.member_lines
:
430 if mline
.date_from
< today
and \
431 mline
.date_to
< today
and \
432 mline
.date_from
<= mline
.date_to
and \
433 ( (mline
.account_invoice_line
and mline
.account_invoice_line
.invoice_id
.state
) == 'paid' or \
434 ( mline
.pos_order_line
and \
435 ( mline
.pos_order_line
.order_id
.state
== 'paid' or \
436 mline
.pos_order_line
.order_id
.state
== 'done' or \
437 mline
.pos_order_line
.order_id
.state
== 'invoiced' ))):
453 if partner_data
.free_member
and s
!=0:
455 if partner_data
.associate_member
:
456 res_state
= self
._membership
_state
(cr
, uid
, [partner_data
.associate_member
.id], name
, args
, context
=context
)
457 res
[id] = res_state
[partner_data
.associate_member
.id]
458 print("DEV: [pos_membership] [Partner] [_membership_state]: res=%s" % (str(res
)))
461 def _membership_date(self
, cr
, uid
, ids
, name
, args
, context
=None):
462 """Return date of membership"""
465 member_line_obj
= self
.pool
.get('membership.membership_line')
466 print("DEV: [pos_membership] [Partner] [_membership_date]: ids=%s" % (str(ids
)))
467 for partner
in self
.browse(cr
, uid
, ids
, context
=context
):
468 if partner
.associate_member
:
469 partner_id
= partner
.associate_member
.id
471 partner_id
= partner
.id
473 'membership_start': False,
474 'membership_stop': False,
475 'membership_cancel': False
477 if name
== 'membership_start':
478 line_id
= member_line_obj
.search(cr
, uid
, [('partner', '=', partner_id
),('date_cancel','=',False)],
479 limit
=1, order
='date_from', context
=context
)
481 res
[partner
.id]['membership_start'] = member_line_obj
.read(cr
, uid
, line_id
[0],
482 ['date_from'], context
=context
)['date_from']
483 print("DEV: [pos_membership] [Partner] [_membership_date] [membership_start]: ids=%s date=%s" % (str(ids
), str(res
[partner
.id]['membership_start'])))
485 if name
== 'membership_stop':
486 line_id1
= member_line_obj
.search(cr
, uid
, [('partner', '=', partner_id
),('date_cancel','=',False)],
487 limit
=1, order
='date_to desc', context
=context
)
489 res
[partner
.id]['membership_stop'] = member_line_obj
.read(cr
, uid
, line_id1
[0],
490 ['date_to'], context
=context
)['date_to']
491 print("DEV: [pos_membership] [Partner] [_membership_date] [membership_stop]: ids=%s date=%s" % (str(ids
), str(res
[partner
.id]['membership_stop'])))
493 if name
== 'membership_cancel':
494 if partner
.membership_state
== 'canceled':
495 line_id2
= member_line_obj
.search(cr
, uid
, [('partner', '=', partner
.id)], limit
=1, order
='date_cancel', context
=context
)
497 res
[partner
.id]['membership_cancel'] = member_line_obj
.read(cr
, uid
, line_id2
[0], ['date_cancel'], context
=context
)['date_cancel']
498 print("DEV: [pos_membership] [Partner] [_membership_date] [membership_cancel]: ids=%s date=%s" % (str(ids
), str(res
[partner
.id]['membership_cancel'])))
499 print("DEV: [pos_membership] [Partner] [_membership_date]: res=%s" % (str(res
)))
502 def _get_partners(self
, cr
, uid
, ids
, context
=None):
505 ids2
= self
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
509 def __get_membership_state(self
, *args
, **kwargs
):
510 return self
._membership
_state
(*args
, **kwargs
)
513 'membership_state': fields
.function(
514 __get_membership_state
,
515 string
= 'Current Membership Status', type = 'selection',
518 # NOTE: il est important que la priorité soit plus grande
519 # que les membership_{start,stop,cancel}
520 # car _membership_state s'en sert et doit donc les trouver à jour.
521 'account.invoice': (_get_invoice_partner
, ['state'], 20),
522 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 20),
523 'membership.membership_line': (_get_partner_id
, ['state'], 20),
524 'res.partner': (_get_partners
, ['free_member', 'membership_state', 'associate_member'], 20)
525 }, help="""It indicates the membership state.
526 -Non Member: A partner who has not applied for any membership.
527 -Cancelled Member: A member who has cancelled his membership.
528 -Old Member: A member whose membership date has expired.
529 -Waiting Member: A member who has applied for the membership and whose invoice is going to be created.
530 -Invoiced Member: A member whose invoice has been created.
531 -Paying member: A member who has paid the membership fee."""),
532 'membership_start': fields
.function(
533 _membership_date
, multi
= 'membeship_start',
534 string
= 'Membership Start Date', type = 'date',
536 'account.invoice': (_get_invoice_partner
, ['state'], 10),
537 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 10),
538 'membership.membership_line': (_get_partner_id
, ['state'], 10),
539 'res.partner': (lambda self
, cr
, uid
, ids
, c
={}: ids
, ['free_member'], 10)
540 }, help="Date from which membership becomes active."),
541 'membership_stop': fields
.function(
543 string
= 'Membership End Date', type='date', multi
='membership_stop',
545 'account.invoice': (_get_invoice_partner
, ['state'], 10),
546 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 10),
547 'membership.membership_line': (_get_partner_id
, ['state'], 10),
548 'res.partner': (lambda self
, cr
, uid
, ids
, c
={}: ids
, ['free_member'], 10)
549 }, help="Date until which membership remains active."),
550 'membership_cancel': fields
.function(
552 string
= 'Cancel Membership Date', type='date', multi
='membership_cancel',
554 'account.invoice': (_get_invoice_partner
, ['state'], 11),
555 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 11),
556 'membership.membership_line': (_get_partner_id
, ['state'], 10),
557 'res.partner': (lambda self
, cr
, uid
, ids
, c
={}: ids
, ['free_member'], 10)
558 }, help="Date on which membership has been cancelled"),
563 class pos_order(osv
.osv
):
564 _inherit
= 'pos.order'
566 # XXX: copied from openerp/addons/point_of_sale/point_of_sale.py
567 def action_invoice(self
, cr
, uid
, ids
, context
=None):
568 print ("DEV: [pos_membership] [pos_order] [action_invoice]")
569 wf_service
= netsvc
.LocalService("workflow")
570 inv_ref
= self
.pool
.get('account.invoice')
571 inv_line_ref
= self
.pool
.get('account.invoice.line')
572 product_obj
= self
.pool
.get('product.product')
575 for order
in self
.pool
.get('pos.order').browse(cr
, uid
, ids
, context
=context
):
577 inv_ids
.append(order
.invoice_id
.id)
580 if not order
.partner_id
:
581 raise osv
.except_osv(_('Error!'), _('Please provide a partner for the sale.'))
583 acc
= order
.partner_id
.property_account_receivable
.id
584 # XXX: copied from openerp/addons/point_of_sale/point_of_sale.py to fix account.invoice.line creation
587 'origin': order
.name
,
589 'journal_id': order
.sale_journal
.id or None,
590 'type': 'out_invoice',
591 'reference': order
.name
,
592 'partner_id': order
.partner_id
.id,
593 'comment': order
.note
or '',
594 'currency_id': order
.pricelist_id
.currency_id
.id, # considering partner's sale pricelist's currency
597 inv
.update(inv_ref
.onchange_partner_id(cr
, uid
, [], 'out_invoice', order
.partner_id
.id)['value'])
598 if not inv
.get('account_id', None):
599 inv
['account_id'] = acc
600 for line
in order
.lines
:
602 #'invoice_id': inv_id,
603 'product_id': line
.product_id
.id,
604 'quantity': line
.qty
,
606 inv_name
= product_obj
.name_get(cr
, uid
, [line
.product_id
.id], context
=context
)[0][1]
607 inv_line
.update(inv_line_ref
.product_id_change(cr
, uid
, [],
609 line
.product_id
.uom_id
.id,
610 line
.qty
, partner_id
= order
.partner_id
.id,
611 fposition_id
=order
.partner_id
.property_account_position
.id)['value'])
612 if line
.product_id
.description_sale
:
613 inv_line
['note'] = line
.product_id
.description_sale
614 inv_line
['price_unit'] = line
.price_unit
615 inv_line
['discount'] = line
.discount
616 inv_line
['name'] = inv_name
617 inv_line
['invoice_line_tax_id'] = ('invoice_line_tax_id' in inv_line
)\
618 and [(6, 0, inv_line
['invoice_line_tax_id'])] or []
619 #inv_line_ref.create(cr, uid, inv_line, context=context)
620 inv
['invoice_line'].append((0, 0, inv_line
))
621 inv_id
= inv_ref
.create(cr
, uid
, inv
, context
=context
)
623 self
.write(cr
, uid
, [order
.id], {'invoice_id': inv_id
, 'state': 'invoiced'}, context
=context
)
624 inv_ref
.confirm_paid(cr
, uid
, [inv_id
], context
=context
)
625 inv_ids
.append(inv_id
)
626 inv_ref
.button_reset_taxes(cr
, uid
, [inv_id
], context
=context
)
627 wf_service
.trg_validate(uid
, 'pos.order', order
.id, 'invoice', cr
)
629 if not inv_ids
: return {}
631 mod_obj
= self
.pool
.get('ir.model.data')
632 res
= mod_obj
.get_object_reference(cr
, uid
, 'account', 'invoice_form')
633 res_id
= res
and res
[1] or False
635 'name': _('Customer Invoice'),
639 'res_model': 'account.invoice',
640 'context': "{'type':'out_invoice'}",
641 'type': 'ir.actions.act_window',
644 'res_id': inv_ids
and inv_ids
[0] or False,
647 def write(self
, cr
, uid
, ids
, vals
, context
=None):
648 print("DEV: [pos_membership] [pos_order] [write]: ids=%s vals=%s" % (str(ids
), str(vals
)))
649 pos_order_obj
= self
.pool
.get('pos.order')
650 res
= super(pos_order
, self
).write(cr
, uid
, ids
, vals
, context
=context
)
651 print("DEV: [pos_membership] [pos_order] [write]: res=%s" % str(res
))
654 def create(self
, cr
, uid
, vals
, context
=None):
655 print("DEV: [pos_membership] [pos_order] [create]: vals=%s" % (str(vals
)))
656 pos_order_obj
= self
.pool
.get('pos.order')
657 res
= super(pos_order
, self
).create(cr
, uid
, vals
, context
=context
)
658 print("DEV: [pos_membership] [pos_order] [create]: res=%s" % (str(res
)))
663 class pos_order_line(osv
.osv
):
664 _inherit
= 'pos.order.line'
666 def write(self
, cr
, uid
, ids
, vals
, context
=None):
667 print("DEV: [pos_membership] [pos_order_line] [write]: ids=%s vals=%s context=%s" % (str(ids
), str(vals
), str(context
)))
668 member_line_obj
= self
.pool
.get('membership.membership_line')
669 res
= super(pos_order_line
, self
).write(cr
, uid
, ids
, vals
, context
=context
)
670 print ("DEV: [pos_membership] [pos_order_line] [write] [super] : res=%s" % str(res
))
671 for line
in self
.browse(cr
, uid
, ids
, context
=context
):
672 ml_ids
= member_line_obj
.search(cr
, uid
, [('pos_order_line', '=', line
.id)], context
=context
)
673 if line
.product_id
and line
.product_id
.membership
and not ml_ids
:
674 date_from
= line
.product_id
.membership_date_from
675 date_to
= line
.product_id
.membership_date_to
676 if line
.order_id
.date_order
> date_from
and \
677 line
.order_id
.date_order
< date_to
:
678 date_from
= line
.order_id
.date_order
679 if line
.product_id
.membership_date2date
:
680 date_from
= ('date_from' in context
681 and context
['date_from']
682 and datetime
.strptime(context
['date_from'], "%Y-%m-%d")
684 date_to
= date_from
+ relativedelta(months
= +12) # TODO: parameterize this delta?
685 date_from
= date_from
.strftime("%Y-%m-%d")
686 date_to
= date_to
.strftime("%Y-%m-%d")
687 print ("DEV: [pos_membership] [write] date_from: %s" % str(date_from
))
688 print ("DEV: [pos_membership] [write] date_to : %s" % str(date_to
))
689 member_line_obj
.create(cr
, uid
690 , { 'partner': line
.order_id
.partner_id
and line
.order_id
.partner_id
.id or False
691 , 'membership_id': line
.product_id
.id
692 , 'member_price': line
.price_unit
693 , 'date': time
.strftime('%Y-%m-%d')
694 , 'date_from': date_from
696 , 'pos_order_line': line
.id
699 if line
.product_id
.membership_grouped
:
700 if line
.order_id
.partner_id
.associate_members
:
701 associate_member_line_ids
= member_line_obj
.search(cr
, uid
702 , [ ('pos_order_line', '=', line
.id)
703 , ('partner', '!=', line
.order_id
.partner_id
.id)
706 for associate_member_line
in member_line_obj
.browse(cr
, uid
, associate_member_line_ids
, context
=context
):
707 print ("DEV: [pos_membership] [write] [associate] date_from: %s" % str(date_from
))
708 print ("DEV: [pos_membership] [write] [associate] date_to : %s" % str(date_to
))
709 member_line_obj
.write(cr
, uid
, associate_member_line
.id
710 , {'date_from': date_from
715 print("DEV: mettre une contrainte pour l'objet\
716 membership.membership_line interdisant les\
717 adhésions groupées reliées à des partenaires\
718 sans membres associés")
720 associate_member_line_ids
= member_line_obj
.search(cr
, uid
721 , [ ('pos_order_line', '=', line
.id)
722 , ('partner', '!=', line
.order_id
.partner_id
.id)
725 member_line_obj
.unlink(cr
, uid
, associate_member_line_ids
, context
=context
)
727 #Define member ident if it's necessary
728 partners
= [line
.order_id
.partner_id
]
729 if line
.order_id
.partner_id
.associate_members
:
730 partners
.extend(line
.order_id
.partner_id
.associate_members
)
732 if not i
.member_ident
:
733 mbr_id
= self
.pool
.get('ir.sequence').get(cr
, uid
, 'member_ident')
734 self
.pool
.get('res.partner').write(cr
, uid
, i
.id, {'member_ident': mbr_id
})
735 if line
.product_id
and not line
.product_id
.membership
and ml_ids
:
736 # Product line has changed to a non membership product
737 member_line_obj
.unlink(cr
, uid
, ml_ids
, context
=context
)
738 print("DEV: [pos_membership] [pos_order_line] [write]: res=%s" % str(res
))
741 def unlink(self
, cr
, uid
, ids
, context
=None):
742 """Remove Membership Line Record for Account Invoice Line
744 member_line_obj
= self
.pool
.get('membership.membership_line')
746 ml_ids
= member_line_obj
.search(cr
, uid
, [('pos_order_line', '=', id)], context
=context
)
747 member_line_obj
.unlink(cr
, uid
, ml_ids
, context
=context
)
748 return super(pos_order_line
, self
).unlink(cr
, uid
, ids
, context
=context
)
750 def create(self
, cr
, uid
, vals
, context
=None):
751 member_line_obj
= self
.pool
.get('membership.membership_line')
752 print("DEV: [pos_membership] [pos_order_line] [create]: vals=%s context=%s" % (str(vals
), str(context
)))
753 res
= super(pos_order_line
, self
).create(cr
, uid
, vals
, context
=context
)
754 print ("DEV: [pos_membership] [pos_order_line] [create] [super] : res=%s" % str(res
))
755 line
= self
.browse(cr
, uid
, res
, context
=context
)
757 ml_ids
= member_line_obj
.search(cr
, uid
, [('pos_order_line', '=', line
.id)], context
=context
)
758 if line
.product_id
and line
.product_id
.membership
and not ml_ids
:
759 date_from
= line
.product_id
.membership_date_from
760 date_to
= line
.product_id
.membership_date_to
761 if line
.order_id
.date_order
> date_from
and line
.order_id
.date_order
< date_to
:
762 date_from
= line
.order_id
.date_order
763 if line
.product_id
.membership_date2date
:
764 date_from
= ('date_from' in context
765 and context
.get('date_from')
766 and datetime
.strptime(context
.get('date_from'), "%Y-%m-%d")
768 date_to
= date_from
+ relativedelta(days
= +364) # TODO: parameterize this delta?
769 date_from
= date_from
.strftime("%Y-%m-%d")
770 date_to
= date_to
.strftime("%Y-%m-%d")
771 print ("DEV: [pos_membership] [pos_order_line] [create] date_from: %s" % str(date_from
))
772 print ("DEV: [pos_membership] [pos_order_line] [create] date_to : %s" % str(date_to
))
773 member_line_obj
.create(cr
, uid
, {
774 'partner': line
.order_id
.partner_id
and line
.order_id
.partner_id
.id or False,
775 'membership_id': line
.product_id
.id,
776 'member_price': line
.price_unit
,
777 'date': time
.strftime('%Y-%m-%d'),
778 'date_from': date_from
,
780 'pos_order_line': line
.id,
782 partners
= [line
.order_id
.partner_id
]
783 if line
.product_id
.membership_grouped
and line
.order_id
.partner_id
.associate_members
:
784 partners
.extend(line
.order_id
.partner_id
.associate_members
)
785 #Adding membership lines just for associate partners
786 for associate_member
in line
.order_id
.partner_id
.associate_members
:
787 print ("DEV: [pos_membership] [pos_order_line] [create] [associate] date_from: %s" % str(date_from
))
788 print ("DEV: [pos_membership] [pos_order_line] [create] [associate] date_to : %s" % str(date_to
))
789 member_line_obj
.create(cr
, uid
, {
790 'partner': associate_member
.id,
791 'membership_id': line
.product_id
.id,
792 'member_price': line
.price_unit
,
793 'date': time
.strftime('%Y-%m-%d'),
794 'date_from': date_from
,
796 'pos_order_line': line
.id,
798 elif line
.product_id
.membership_grouped
and not line
.order_id
.partner_id
.associate_members
:
799 raise osv
.except_osv(_('Error!!!'), _('You try to order grouped membership product to a partner who hasn\'t associated partners.'))
800 #Define member ident if it's necessary
803 print ("\033[7mXXX: [pos_membership] [pos_order_line] [create] : pos_order_line has no partner_id!\033[0m")
805 if not i
.member_ident
:
806 print ("DEV: [pos_membership] [pos_order_line] [create] [partners] : i=%s i.id=%s" % (str(i
), str(i
.id)))
807 mbr_id
= self
.pool
.get('ir.sequence').get(cr
, uid
, 'member_ident')
808 self
.pool
.get('res.partner').write(cr
, uid
, i
.id, {'member_ident': mbr_id
})
809 print ("DEV: [pos_membership] [pos_order_line] [create] : return=%s" % str(res
))
814 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: