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 # POS Membership 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'),
42 class pos_session(osv
.osv
):
43 _inherit
= 'pos.session'
45 def open_cb(self
, cr
, uid
, ids
, context
=None):
47 Avoid call the Point Of Sale interface and set the pos.session to 'opened' (in progress)
52 if isinstance(ids
, (int, long)):
55 this_record
= self
.browse(cr
, uid
, ids
[0], context
=context
)
56 this_record
._workflow
_signal
('open')
58 context
.update(active_id
=this_record
.id)
66 class pos_order(osv
.osv
):
67 _inherit
= 'pos.order'
69 def create_partner_from_ui(self
, cr
, uid
, partners
, context
=None):
70 print ("DEV: [pos_membership] [create_partner_from_ui] partners=%s" % str(partners
))
72 partner_obj
= self
.pool
.get('res.partner')
73 for tmp_partner
in partners
:
74 partner
= tmp_partner
['data']
75 partner_id
= partner_obj
.create(cr
, uid
, {
76 'name': partner
['name'],
78 partner_ids
.append(partner_id
)
79 #self.signal_paid(cr, uid, [partner_id])
82 def create_from_ui(self
, cr
, uid
, orders
, context
=None):
83 # NOTE: copied from openerp/addons/point_of_sale/point_of_sale.py
84 #_logger.info("orders: %r", orders)
85 print ("DEV: [pos_membership] [create_from_ui] order=", str(orders
))
87 for tmp_order
in orders
:
88 order
= tmp_order
['data']
89 order_id
= self
.create(cr
, uid
, {
90 'name': order
['name'],
91 'user_id': order
['user_id'] or False,
92 'session_id': order
['pos_session_id'],
93 'lines': order
['lines'],
94 'pos_reference': order
['name'],
95 #-- BEGIN pos_membership
96 'partner_id': order
['partner_id'],
97 #-- END pos_membership
100 for payments
in order
['statement_ids']:
101 payment
= payments
[2]
102 self
.add_payment(cr
, uid
, order_id
, {
103 'amount': payment
['amount'] or 0.0,
104 'payment_date': payment
['name'],
105 'statement_id': payment
['statement_id'],
106 'payment_name': payment
.get('note', False),
107 'journal': payment
['journal_id']
110 if order
['amount_return']:
111 session
= self
.pool
.get('pos.session').browse(cr
, uid
, order
['pos_session_id'], context
=context
)
112 cash_journal
= session
.cash_journal_id
113 cash_statement
= False
115 cash_journal_ids
= filter(lambda st
: st
.journal_id
.type == 'cash', session
.statement_ids
)
116 if not len(cash_journal_ids
):
117 raise osv
.except_osv(_('error!'),
118 _("No cash statement found for this session. Unable to record returned cash."))
119 cash_journal
= cash_journal_ids
[0].journal_id
120 self
.add_payment(cr
, uid
, order_id
, {
121 'amount': -order
['amount_return'],
122 'payment_date': time
.strftime('%Y-%m-%d %H:%M:%S'),
123 'payment_name': _('return'),
124 'journal': cash_journal
.id,
126 order_ids
.append(order_id
)
127 wf_service
= netsvc
.LocalService("workflow")
128 wf_service
.trg_validate(uid
, 'pos.order', order_id
, 'paid', cr
)
134 class membership_line(osv
.osv
):
136 _inherit
= 'membership.membership_line'
138 def _get_partners(self
, cr
, uid
, ids
, context
=None):
139 list_membership_line
= []
140 member_line_obj
= self
.pool
.get('membership.membership_line')
141 for partner
in self
.pool
.get('res.partner').browse(cr
, uid
, ids
, context
=context
):
142 if partner
.member_lines
:
143 list_membership_line
+= member_line_obj
.search(cr
, uid
, [('id', 'in', [l
.id for l
in partner
.member_lines
])], context
=context
)
144 print("DEV: [pos_membership] [membership_line] [_get_partners]: ids=%s res=%s" % (str(ids
), str(list_membership_line
)))
145 return list_membership_line
147 #def _get_membership_lines_from_account_invoice(self, cr, uid, ids, context=None):
148 # list_membership_line = []
149 # member_line_obj = self.pool.get('membership.membership_line')
150 # for invoice in self.pool.get('account.invoice').browse(cr, uid, ids, context=context):
151 # if invoice.invoice_line:
152 # list_membership_line += member_line_obj.search(cr, uid, [('account_invoice_line', 'in', [ l.id for l in invoice.invoice_line])], context=context)
154 # { 'class': 'account.invoice'
155 # , 'ids': list_membership_line
157 # #res= list_membership_line
158 # print("DEV: [pos_membership] [membership_line] [_get_membership_lines_from_account_invoice]: res=%s" % str(res))
160 def _get_membership_lines_from_pos_order(self
, cr
, uid
, ids
, context
=None):
161 list_membership_line
= []
162 member_line_obj
= self
.pool
.get('membership.membership_line')
163 print("DEV: [pos_membership] [membership_line] [_get_membership_lines_from_pos_order]: ids=%s context=%s" % (str(ids
), str(context
)))
164 for order
in self
.pool
.get('pos.order').browse(cr
, uid
, ids
, context
=context
):
166 list_membership_line
+= member_line_obj
.search(cr
, uid
, [('pos_order_line', 'in', [l
.id for l
in order
.lines
])], context
=context
)
168 # { 'class': 'pos.order'
169 # , 'ids': list_membership_line
171 res
= list_membership_line
172 print("DEV: [pos_membership] [membership_line] [_get_membership_lines_from_pos_order]: res=%s" % str(res
))
175 def _check_membership_date(self
, cr
, uid
, ids
, context
=None):
176 """Check if membership product is not in the past
177 @param self: The object pointer
178 @param cr: the current row, from the database cursor,
179 @param uid: the current user’s ID for security checks,
180 @param ids: List of Membership Line IDs
181 @param context: A standard dictionary for contextual values
185 SELECT MIN(ml.date_to - ai.date_invoice)
186 FROM membership_membership_line ml
187 JOIN account_invoice_line ail ON (
188 ml.account_invoice_line = ail.id
190 JOIN account_invoice ai ON (
191 ai.id = ail.invoice_id)
192 WHERE ml.id IN %s''', (tuple(ids
),))
195 if r
[0] and r
[0] < 0:
198 SELECT MIN(ml.date_to - ai.date_order)
199 FROM membership_membership_line ml
200 JOIN pos_order_line ail ON (
201 ml.pos_order_line = ail.id
203 JOIN pos_order ai ON (
204 ai.id = ail.order_id)
205 WHERE ml.id IN %s''', (tuple(ids
),))
208 if r
[0] and r
[0] < 0:
212 def _state(self
, cr
, uid
, ids
, name
, args
, context
=None):
213 """Compute the state lines
214 @param self: The object pointer
215 @param cr: the current row, from the database cursor,
216 @param uid: the current user’s ID for security checks,
217 @param ids: List of Membership Line IDs
218 @param name: Field Name
219 @param context: A standard dictionary for contextual values
220 @param return: Dictionary of state Value
223 print("DEV: [pos_membership] [membership_line] [_state]: name=%s ids=%s args=%s context=%s" % (str(name
), str(ids
), str(args
), str(context
)))
224 inv_obj
= self
.pool
.get('account.invoice')
225 ord_obj
= self
.pool
.get('pos.order')
226 for line
in self
.browse(cr
, uid
, ids
, context
=context
):
228 SELECT i.state, i.id FROM
232 SELECT l.invoice_id FROM
233 account_invoice_line l WHERE
235 SELECT ml.account_invoice_line FROM
236 membership_membership_line ml WHERE
241 fetched
= cr
.fetchone()
245 if (istate
== 'draft') |
(istate
== 'proforma'):
247 elif istate
== 'open':
249 elif istate
== 'paid':
251 inv
= inv_obj
.browse(cr
, uid
, fetched
[1], context
=context
)
252 for payment
in inv
.payment_ids
:
253 if payment
.invoice
and payment
.invoice
.type == 'out_refund':
255 elif istate
== 'cancel':
260 SELECT i.state, i.id, i.partner_id FROM
264 SELECT l.order_id FROM
265 pos_order_line l WHERE
267 SELECT ml.pos_order_line FROM
268 membership_membership_line ml WHERE
273 fetched
= cr
.fetchone()
275 res
[line
.id] = 'canceled'
277 partner_id
= fetched
[2]
278 self
.write(cr
, uid
, line
.id, {'partner': partner_id
})
279 # NOTE: force une mise à jour du partner,
280 # car il n'y en a pas lors de la création du pos.order
281 # dans le PoS (pour le moment)
282 partner_obj
= self
.pool
.get('res.partner')
283 for partner
in partner_obj
.browse(cr
, uid
, [partner_id
], context
=context
):
284 if not partner
.member_ident
:
285 mbr_id
= self
.pool
.get('ir.sequence').get(cr
, uid
, 'member_ident')
286 partner_obj
.write(cr
, uid
, partner
.id, {'member_ident': mbr_id
})
289 if (ostate
== 'paid') |
(ostate
== 'draft'):
291 elif (ostate
== 'done') |
(ostate
== 'invoiced'):
293 # XXX: regarder l'équivalent de out_refund pour un pos.order
294 print("DEV: [pos_membership] [membership_line] [_state]: paid: TODO")
295 #inv = ord_obj.browse(cr, uid, fetched[1], context=context)
296 #for payment in inv.payment_ids:
297 # if payment.invoice and payment.invoice.type == 'out_refund':
299 elif ostate
== 'cancel':
302 print("DEV: [pos_membership] [membership_line] [_state]: return=%s" % (str(res
)))
305 def write(self
, cr
, uid
, ids
, vals
, context
=None):
306 print("DEV: [pos_membership] [membership_line] [write]: ids=%s vals=%s" % (str(ids
), str(vals
)))
307 member_line_obj
= self
.pool
.get('membership.membership_line')
308 res
= super(membership_line
, self
).write(cr
, uid
, ids
, vals
, context
=context
)
309 print("DEV: [pos_membership] [membership_line] [write]: res=%s" % str(res
))
312 def create(self
, cr
, uid
, vals
, context
=None):
313 print("DEV: [pos_membership] [membership_line] [create]: vals=%s" % (str(vals
)))
314 member_line_obj
= self
.pool
.get('membership.membership_line')
315 res
= super(membership_line
, self
).create(cr
, uid
, vals
, context
=context
)
316 print("DEV: [pos_membership] [membership_line] [create]: res=%s" % (str(res
)))
320 'pos_order_line': fields
.many2one('pos.order.line', 'POS Order line', readonly
=True),
321 'pos_order_id': fields
.related('pos_order_line', 'order_id', type='many2one', relation
='pos.order', string
='Order', readonly
=True),
322 'state': fields
.function(_state
,
323 string
='Membership Status', type='selection',
326 #'account.invoice': (_get_membership_lines_from_account_invoice, ['state'], 10),
327 # NOTE: déjà géré par membership.membership_line._get_membership_lines
328 'pos.order': (_get_membership_lines_from_pos_order
, ['state', 'partner_id'], 10),
329 'res.partner': (_get_partners
, ['membership_state'], 12),
330 }, help="""It indicates the membership status.
331 -Non Member: A member who has not applied for any membership.
332 -Cancelled Member: A member who has cancelled his membership.
333 -Old Member: A member whose membership date has expired.
334 -Waiting Member: A member who has applied for the membership and whose invoice is going to be created.
335 -Invoiced Member: A member whose invoice has been created.
336 -Paid Member: A member who has paid the membership amount."""),
337 'company_id': fields
.related('account_invoice_line', 'invoice_id', 'company_id', type="many2one", relation
="res.company", string
="Company", readonly
=True, store
=True)
338 # XXX: pos_order_line a aussi un company_id
344 class Partner(osv
.osv
):
346 _inherit
= 'res.partner'
348 def _get_partner_id(self
, cr
, uid
, ids
, context
=None):
349 print("DEV: [pos_membership] [Partner] [_get_partner_id]: ids=%s context=%s" % (str(ids
), str(context
)))
350 member_line_obj
= self
.pool
.get('membership.membership_line')
351 res_obj
= self
.pool
.get('res.partner')
352 data_inv
= member_line_obj
.browse(cr
, uid
, ids
, context
=context
)
354 for data
in data_inv
:
355 list_partner
.append(data
.partner
.id)
358 ids2
= res_obj
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
360 print("DEV: [pos_membership] [Partner] [_get_partner_id]: res=%s" % (str(list_partner
)))
363 def _get_invoice_partner(self
, cr
, uid
, ids
, context
=None):
364 inv_obj
= self
.pool
.get('account.invoice')
365 res_obj
= self
.pool
.get('res.partner')
366 data_inv
= inv_obj
.browse(cr
, uid
, ids
, context
=context
)
368 for data
in data_inv
:
369 list_partner
.append(data
.partner_id
.id)
372 ids2
= res_obj
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
376 def _get_order_partner(self
, cr
, uid
, ids
, context
=None):
377 ord_obj
= self
.pool
.get('pos.order')
378 res_obj
= self
.pool
.get('res.partner')
379 data_ord
= ord_obj
.browse(cr
, uid
, ids
, context
=context
)
381 for data
in data_ord
:
382 list_partner
.append(data
.partner_id
.id)
385 ids2
= res_obj
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
389 def _membership_state(self
, cr
, uid
, ids
, name
, args
, context
=None):
390 """This Function return Membership State For Given Partner.
391 @param self: The object pointer
392 @param cr: the current row, from the database cursor,
393 @param uid: the current user’s ID for security checks,
394 @param ids: List of Partner IDs
395 @param name: Field Name
396 @param context: A standard dictionary for contextual values
397 @param return: Dictionary of Membership state Value
400 print("DEV: [pos_membership] [Partner] [_membership_state]: name=%s ids=%s args=%s context=%s" % (str(name
), str(ids
), str(args
), str(context
)))
403 today
= time
.strftime('%Y-%m-%d')
405 print("DEV: [pos_membership] [Partner] [_membership_state] id=%s" % (str(id)))
406 partner_data
= self
.browse(cr
, uid
, id, context
=context
)
407 if partner_data
.membership_cancel
and today
> partner_data
.membership_cancel
:
410 if partner_data
.membership_stop
and today
> partner_data
.membership_stop
:
414 print("DEV: [pos_membership] [Partner] [_membership_state] [partner_data] [member_lines] [test]")
415 if partner_data
.member_lines
:
416 print("DEV: [pos_membership] [Partner] [_membership_state] [partner_data] [member_lines]" % ())
417 for mline
in partner_data
.member_lines
:
418 print("DEV: [pos_membership] [Partner] [_membership_state] [mline]: id=%s" % str(mline
.id))
419 if mline
.date_to
>= today
:
420 if mline
.account_invoice_line
and mline
.account_invoice_line
.invoice_id
:
421 istate
= mline
.account_invoice_line
.invoice_id
.state
422 print("DEV: [pos_membership] [Partner] [_membership_state] [account_invoice_line]: id=%s istate=%s" % (str(mline
.account_invoice_line
.invoice_id
.id), str(istate
)))
425 inv
= mline
.account_invoice_line
.invoice_id
426 for payment
in inv
.payment_ids
:
427 if payment
.invoice
.type == 'out_refund':
430 elif istate
== 'open' and s
!= 0:
432 elif istate
== 'cancel' and s
!= 0 and s
!= 1:
434 elif (istate
== 'draft' or istate
== 'proforma') and s
!= 0 and s
!= 1:
436 elif mline
.pos_order_line
and mline
.pos_order_line
.order_id
:
437 ostate
= mline
.pos_order_line
.order_id
.state
438 print("DEV: [pos_membership] [Partner] [_membership_state] [pos_order_line]: id=%s ostate=%s" % (str(mline
.pos_order_line
.order_id
.id), str(ostate
)))
439 if ostate
== 'paid' and s
!= 0 and s
!= 1:
441 if ostate
== 'invoiced':
445 # XXX: regarder l'équivalent de out_refund pour un pos.order
446 print("DEV: [pos_membership] [partner] [_membership_state]: paid: TODO")
447 #inv = mline.pos_order_line.order_id
448 #for payment in inv.payment_ids:
449 # if payment.invoice.type == 'out_refund':
452 elif ostate
== 'open' and s
!= 0:
453 # XXX: 1 donne invoiced, c'est pitet pas bon
454 print("DEV: [pos_membership] [partner] [_membership_state]: invoiced: TODO")
456 elif ostate
== 'cancel' and s
!= 0 and s
!= 1:
458 elif ostate
== 'draft' and s
!= 0 and s
!= 1:
461 for mline
in partner_data
.member_lines
:
462 if mline
.date_from
< today
and \
463 mline
.date_to
< today
and \
464 mline
.date_from
<= mline
.date_to
and \
465 ((mline
.account_invoice_line
and mline
.account_invoice_line
.invoice_id
.state
) == 'paid' or \
466 (mline
.pos_order_line
and \
467 (mline
.pos_order_line
.order_id
.state
== 'paid' or \
468 mline
.pos_order_line
.order_id
.state
== 'done' or \
469 mline
.pos_order_line
.order_id
.state
== 'invoiced' ))):
485 if partner_data
.free_member
and s
!= 0:
487 if partner_data
.associate_member
:
488 res_state
= self
._membership
_state
(cr
, uid
, [partner_data
.associate_member
.id], name
, args
, context
=context
)
489 res
[id] = res_state
[partner_data
.associate_member
.id]
490 print("DEV: [pos_membership] [Partner] [_membership_state]: res=%s" % (str(res
)))
493 def _membership_date(self
, cr
, uid
, ids
, name
, args
, context
=None):
494 """Return date of membership"""
497 member_line_obj
= self
.pool
.get('membership.membership_line')
498 print("DEV: [pos_membership] [Partner] [_membership_date]: ids=%s" % (str(ids
)))
499 for partner
in self
.browse(cr
, uid
, ids
, context
=context
):
500 if partner
.associate_member
:
501 partner_id
= partner
.associate_member
.id
503 partner_id
= partner
.id
505 'membership_start': False,
506 'membership_stop': False,
507 'membership_cancel': False
509 if name
== 'membership_start':
510 line_id
= member_line_obj
.search(cr
, uid
, [('partner', '=', partner_id
),('date_cancel','=',False)],
511 limit
=1, order
='date_from', context
=context
)
513 res
[partner
.id]['membership_start'] = member_line_obj
.read(cr
, uid
, line_id
[0],
514 ['date_from'], context
=context
)['date_from']
515 print("DEV: [pos_membership] [Partner] [_membership_date] [membership_start]: ids=%s date=%s" % (str(ids
), str(res
[partner
.id]['membership_start'])))
517 if name
== 'membership_stop':
518 line_id1
= member_line_obj
.search(cr
, uid
, [('partner', '=', partner_id
),('date_cancel','=',False)],
519 limit
=1, order
='date_to desc', context
=context
)
521 res
[partner
.id]['membership_stop'] = member_line_obj
.read(cr
, uid
, line_id1
[0],
522 ['date_to'], context
=context
)['date_to']
523 print("DEV: [pos_membership] [Partner] [_membership_date] [membership_stop]: ids=%s date=%s" % (str(ids
), str(res
[partner
.id]['membership_stop'])))
525 if name
== 'membership_cancel':
526 if partner
.membership_state
== 'canceled':
527 line_id2
= member_line_obj
.search(cr
, uid
, [('partner', '=', partner
.id)], limit
=1, order
='date_cancel', context
=context
)
529 res
[partner
.id]['membership_cancel'] = member_line_obj
.read(cr
, uid
, line_id2
[0], ['date_cancel'], context
=context
)['date_cancel']
530 print("DEV: [pos_membership] [Partner] [_membership_date] [membership_cancel]: ids=%s date=%s" % (str(ids
), str(res
[partner
.id]['membership_cancel'])))
531 print("DEV: [pos_membership] [Partner] [_membership_date]: res=%s" % (str(res
)))
534 def _get_partners(self
, cr
, uid
, ids
, context
=None):
537 ids2
= self
.search(cr
, uid
, [('associate_member', 'in', ids2
)], context
=context
)
541 def __get_membership_state(self
, *args
, **kwargs
):
542 return self
._membership
_state
(*args
, **kwargs
)
545 'membership_state': fields
.function(
546 __get_membership_state
,
547 string
= 'Current Membership Status', type = 'selection',
550 # NOTE: il est important que la priorité soit plus grande
551 # que les membership_{start,stop,cancel}
552 # car _membership_state s'en sert et doit donc les trouver à jour.
553 'account.invoice': (_get_invoice_partner
, ['state'], 20),
554 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 20),
555 'membership.membership_line': (_get_partner_id
, ['state'], 20),
556 'res.partner': (_get_partners
, ['free_member', 'membership_state', 'associate_member'], 20)
557 }, help="""It indicates the membership state.
558 -Non Member: A partner who has not applied for any membership.
559 -Cancelled Member: A member who has cancelled his membership.
560 -Old Member: A member whose membership date has expired.
561 -Waiting Member: A member who has applied for the membership and whose invoice is going to be created.
562 -Invoiced Member: A member whose invoice has been created.
563 -Paying member: A member who has paid the membership fee."""),
564 'membership_start': fields
.function(
565 _membership_date
, multi
= 'membership_start',
566 string
= 'Membership Start Date', type = 'date',
568 'account.invoice': (_get_invoice_partner
, ['state'], 10),
569 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 10),
570 'membership.membership_line': (_get_partner_id
, ['state'], 10),
571 'res.partner': (lambda self
, cr
, uid
, ids
, c
={}: ids
, ['free_member'], 10)
572 }, help="Date from which membership becomes active."),
573 'membership_stop': fields
.function(
575 string
= 'Membership End Date', type='date', multi
='membership_stop',
577 'account.invoice': (_get_invoice_partner
, ['state'], 10),
578 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 10),
579 'membership.membership_line': (_get_partner_id
, ['state'], 10),
580 'res.partner': (lambda self
, cr
, uid
, ids
, c
={}: ids
, ['free_member'], 10)
581 }, help="Date until which membership remains active."),
582 'membership_cancel': fields
.function(
584 string
= 'Cancel Membership Date', type='date', multi
='membership_cancel',
586 'account.invoice': (_get_invoice_partner
, ['state'], 11),
587 'pos.order': (_get_order_partner
, ['state', 'partner_id'], 11),
588 'membership.membership_line': (_get_partner_id
, ['state'], 10),
589 'res.partner': (lambda self
, cr
, uid
, ids
, c
={}: ids
, ['free_member'], 10)
590 }, help="Date on which membership has been cancelled"),
595 class pos_order(osv
.osv
):
596 _inherit
= 'pos.order'
598 # XXX: copied from openerp/addons/point_of_sale/point_of_sale.py
599 def action_invoice(self
, cr
, uid
, ids
, context
=None):
600 print ("DEV: [pos_membership] [pos_order] [action_invoice]")
601 wf_service
= netsvc
.LocalService("workflow")
602 inv_ref
= self
.pool
.get('account.invoice')
603 inv_line_ref
= self
.pool
.get('account.invoice.line')
604 product_obj
= self
.pool
.get('product.product')
607 for order
in self
.pool
.get('pos.order').browse(cr
, uid
, ids
, context
=context
):
609 inv_ids
.append(order
.invoice_id
.id)
612 if not order
.partner_id
:
613 raise osv
.except_osv(_('Error!'), _('Please provide a partner for the sale.'))
615 acc
= order
.partner_id
.property_account_receivable
.id
616 # XXX: copied from openerp/addons/point_of_sale/point_of_sale.py to fix account.invoice.line creation
619 'origin': order
.name
,
621 'journal_id': order
.sale_journal
.id or None,
622 'type': 'out_invoice',
623 'reference': order
.name
,
624 'partner_id': order
.partner_id
.id,
625 'comment': order
.note
or '',
626 'currency_id': order
.pricelist_id
.currency_id
.id, # considering partner's sale pricelist's currency
629 inv
.update(inv_ref
.onchange_partner_id(cr
, uid
, [], 'out_invoice', order
.partner_id
.id)['value'])
630 if not inv
.get('account_id', None):
631 inv
['account_id'] = acc
632 for line
in order
.lines
:
634 #'invoice_id': inv_id,
635 'product_id': line
.product_id
.id,
636 'quantity': line
.qty
,
638 inv_name
= product_obj
.name_get(cr
, uid
, [line
.product_id
.id], context
=context
)[0][1]
639 inv_line
.update(inv_line_ref
.product_id_change(cr
, uid
, [],
641 line
.product_id
.uom_id
.id,
642 line
.qty
, partner_id
= order
.partner_id
.id,
643 fposition_id
=order
.partner_id
.property_account_position
.id)['value'])
644 if line
.product_id
.description_sale
:
645 inv_line
['note'] = line
.product_id
.description_sale
646 inv_line
['price_unit'] = line
.price_unit
647 inv_line
['discount'] = line
.discount
648 inv_line
['name'] = inv_name
649 inv_line
['invoice_line_tax_id'] = ('invoice_line_tax_id' in inv_line
)\
650 and [(6, 0, inv_line
['invoice_line_tax_id'])] or []
651 #inv_line_ref.create(cr, uid, inv_line, context=context)
652 inv
['invoice_line'].append((0, 0, inv_line
))
653 inv_id
= inv_ref
.create(cr
, uid
, inv
, context
=context
)
655 self
.write(cr
, uid
, [order
.id], {'invoice_id': inv_id
, 'state': 'invoiced'}, context
=context
)
656 inv_ref
.confirm_paid(cr
, uid
, [inv_id
], context
=context
)
657 inv_ids
.append(inv_id
)
658 inv_ref
.button_reset_taxes(cr
, uid
, [inv_id
], context
=context
)
659 wf_service
.trg_validate(uid
, 'pos.order', order
.id, 'invoice', cr
)
661 if not inv_ids
: return {}
663 mod_obj
= self
.pool
.get('ir.model.data')
664 res
= mod_obj
.get_object_reference(cr
, uid
, 'account', 'invoice_form')
665 res_id
= res
and res
[1] or False
667 'name': _('Customer Invoice'),
671 'res_model': 'account.invoice',
672 'context': "{'type':'out_invoice'}",
673 'type': 'ir.actions.act_window',
676 'res_id': inv_ids
and inv_ids
[0] or False,
679 def write(self
, cr
, uid
, ids
, vals
, context
=None):
680 print("DEV: [pos_membership] [pos_order] [write]: ids=%s vals=%s" % (str(ids
), str(vals
)))
681 pos_order_obj
= self
.pool
.get('pos.order')
682 res
= super(pos_order
, self
).write(cr
, uid
, ids
, vals
, context
=context
)
683 print("DEV: [pos_membership] [pos_order] [write]: res=%s" % str(res
))
686 def create(self
, cr
, uid
, vals
, context
=None):
687 print("DEV: [pos_membership] [pos_order] [create]: vals=%s" % (str(vals
)))
688 pos_order_obj
= self
.pool
.get('pos.order')
689 res
= super(pos_order
, self
).create(cr
, uid
, vals
, context
=context
)
690 print("DEV: [pos_membership] [pos_order] [create]: res=%s" % (str(res
)))
695 class pos_order_line(osv
.osv
):
696 _inherit
= 'pos.order.line'
698 def write(self
, cr
, uid
, ids
, vals
, context
=None):
699 print("DEV: [pos_membership] [pos_order_line] [write]: ids=%s vals=%s context=%s" % (str(ids
), str(vals
), str(context
)))
700 member_line_obj
= self
.pool
.get('membership.membership_line')
701 res
= super(pos_order_line
, self
).write(cr
, uid
, ids
, vals
, context
=context
)
702 print ("DEV: [pos_membership] [pos_order_line] [write] [super] : res=%s" % str(res
))
703 for line
in self
.browse(cr
, uid
, ids
, context
=context
):
704 ml_ids
= member_line_obj
.search(cr
, uid
, [('pos_order_line', '=', line
.id)], context
=context
)
705 if line
.product_id
and line
.product_id
.membership
and not ml_ids
:
706 date_from
= line
.product_id
.membership_date_from
707 date_to
= line
.product_id
.membership_date_to
708 if line
.order_id
.date_order
> date_from
and \
709 line
.order_id
.date_order
< date_to
:
710 date_from
= line
.order_id
.date_order
711 if line
.product_id
.membership_date2date
:
712 date_from
= ('date_from' in context
713 and context
['date_from']
714 and datetime
.strptime(context
['date_from'], "%Y-%m-%d")
716 date_to
= date_from
+ relativedelta(months
= +12) # TODO: parameterize this delta?
717 date_from
= date_from
.strftime("%Y-%m-%d")
718 date_to
= date_to
.strftime("%Y-%m-%d")
719 print ("DEV: [pos_membership] [write] date_from: %s" % str(date_from
))
720 print ("DEV: [pos_membership] [write] date_to : %s" % str(date_to
))
721 member_line_obj
.create(cr
, uid
722 , { 'partner': line
.order_id
.partner_id
and line
.order_id
.partner_id
.id or False
723 , 'membership_id': line
.product_id
.id
724 , 'member_price': line
.price_unit
725 , 'date': time
.strftime('%Y-%m-%d')
726 , 'date_from': date_from
728 , 'pos_order_line': line
.id
731 if line
.product_id
.membership_grouped
:
732 if line
.order_id
.partner_id
.associate_members
:
733 associate_member_line_ids
= member_line_obj
.search(cr
, uid
734 , [ ('pos_order_line', '=', line
.id)
735 , ('partner', '!=', line
.order_id
.partner_id
.id)
738 for associate_member_line
in member_line_obj
.browse(cr
, uid
, associate_member_line_ids
, context
=context
):
739 print ("DEV: [pos_membership] [write] [associate] date_from: %s" % str(date_from
))
740 print ("DEV: [pos_membership] [write] [associate] date_to : %s" % str(date_to
))
741 member_line_obj
.write(cr
, uid
, associate_member_line
.id
742 , {'date_from': date_from
747 print("DEV: mettre une contrainte pour l'objet\
748 membership.membership_line interdisant les\
749 adhésions groupées reliées à des partenaires\
750 sans membres associés")
752 associate_member_line_ids
= member_line_obj
.search(cr
, uid
753 , [ ('pos_order_line', '=', line
.id)
754 , ('partner', '!=', line
.order_id
.partner_id
.id)
757 member_line_obj
.unlink(cr
, uid
, associate_member_line_ids
, context
=context
)
759 #Define member ident if it's necessary
760 partners
= [line
.order_id
.partner_id
]
761 if line
.order_id
.partner_id
.associate_members
:
762 partners
.extend(line
.order_id
.partner_id
.associate_members
)
764 if not i
.member_ident
:
765 mbr_id
= self
.pool
.get('ir.sequence').get(cr
, uid
, 'member_ident')
766 self
.pool
.get('res.partner').write(cr
, uid
, i
.id, {'member_ident': mbr_id
})
767 if line
.product_id
and not line
.product_id
.membership
and ml_ids
:
768 # Product line has changed to a non membership product
769 member_line_obj
.unlink(cr
, uid
, ml_ids
, context
=context
)
770 print("DEV: [pos_membership] [pos_order_line] [write]: res=%s" % str(res
))
773 def unlink(self
, cr
, uid
, ids
, context
=None):
774 """Remove Membership Line Record for Account Invoice Line
776 member_line_obj
= self
.pool
.get('membership.membership_line')
778 ml_ids
= member_line_obj
.search(cr
, uid
, [('pos_order_line', '=', id)], context
=context
)
779 member_line_obj
.unlink(cr
, uid
, ml_ids
, context
=context
)
780 return super(pos_order_line
, self
).unlink(cr
, uid
, ids
, context
=context
)
782 def create(self
, cr
, uid
, vals
, context
=None):
783 member_line_obj
= self
.pool
.get('membership.membership_line')
784 print("DEV: [pos_membership] [pos_order_line] [create]: vals=%s context=%s" % (str(vals
), str(context
)))
785 res
= super(pos_order_line
, self
).create(cr
, uid
, vals
, context
=context
)
786 print ("DEV: [pos_membership] [pos_order_line] [create] [super] : res=%s" % str(res
))
787 line
= self
.browse(cr
, uid
, res
, context
=context
)
789 ml_ids
= member_line_obj
.search(cr
, uid
, [('pos_order_line', '=', line
.id)], context
=context
)
790 if line
.product_id
and line
.product_id
.membership
and not ml_ids
:
791 date_from
= line
.product_id
.membership_date_from
792 date_to
= line
.product_id
.membership_date_to
793 if line
.order_id
.date_order
> date_from
and line
.order_id
.date_order
< date_to
:
794 date_from
= line
.order_id
.date_order
795 if line
.product_id
.membership_date2date
:
796 date_from
= ('date_from' in context
797 and context
.get('date_from')
798 and datetime
.strptime(context
.get('date_from'), "%Y-%m-%d")
800 date_to
= date_from
+ relativedelta(days
= +364) # TODO: parameterize this delta?
801 date_from
= date_from
.strftime("%Y-%m-%d")
802 date_to
= date_to
.strftime("%Y-%m-%d")
803 print ("DEV: [pos_membership] [pos_order_line] [create] date_from: %s" % str(date_from
))
804 print ("DEV: [pos_membership] [pos_order_line] [create] date_to : %s" % str(date_to
))
805 member_line_obj
.create(cr
, uid
, {
806 'partner': line
.order_id
.partner_id
and line
.order_id
.partner_id
.id or False,
807 'membership_id': line
.product_id
.id,
808 'member_price': line
.price_unit
,
809 'date': time
.strftime('%Y-%m-%d'),
810 'date_from': date_from
,
812 'pos_order_line': line
.id,
814 partners
= [line
.order_id
.partner_id
]
815 if line
.product_id
.membership_grouped
and line
.order_id
.partner_id
.associate_members
:
816 partners
.extend(line
.order_id
.partner_id
.associate_members
)
817 #Adding membership lines just for associate partners
818 for associate_member
in line
.order_id
.partner_id
.associate_members
:
819 print ("DEV: [pos_membership] [pos_order_line] [create] [associate] date_from: %s" % str(date_from
))
820 print ("DEV: [pos_membership] [pos_order_line] [create] [associate] date_to : %s" % str(date_to
))
821 member_line_obj
.create(cr
, uid
, {
822 'partner': associate_member
.id,
823 'membership_id': line
.product_id
.id,
824 'member_price': line
.price_unit
,
825 'date': time
.strftime('%Y-%m-%d'),
826 'date_from': date_from
,
828 'pos_order_line': line
.id,
830 elif line
.product_id
.membership_grouped
and not line
.order_id
.partner_id
.associate_members
:
831 raise osv
.except_osv(_('Error!!!'), _('You try to order grouped membership product to a partner who hasn\'t associated partners.'))
832 #Define member ident if it's necessary
835 print ("\033[7mXXX: [pos_membership] [pos_order_line] [create] : pos_order_line has no partner_id!\033[0m")
837 if not i
.member_ident
:
838 print ("DEV: [pos_membership] [pos_order_line] [create] [partners] : i=%s i.id=%s" % (str(i
), str(i
.id)))
839 mbr_id
= self
.pool
.get('ir.sequence').get(cr
, uid
, 'member_ident')
840 self
.pool
.get('res.partner').write(cr
, uid
, i
.id, {'member_ident': mbr_id
})
841 print ("DEV: [pos_membership] [pos_order_line] [create] : return=%s" % str(res
))
846 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: