2010-08-09 11:14:53 +00:00
# -*- coding: utf-8 -*-
2008-08-24 14:45:43 +00:00
##############################################################################
2010-10-08 06:13:09 +00:00
#
2009-01-30 10:37:24 +00:00
# OpenERP, Open Source Management Solution
2010-08-09 11:14:53 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2008-11-03 19:18:56 +00:00
#
# This program is free software: you can redistribute it and/or modify
2010-08-09 11:14:53 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2008-11-03 19:18:56 +00:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2010-08-09 11:14:53 +00:00
# GNU Affero General Public License for more details.
2008-11-03 19:18:56 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2010-10-08 06:13:09 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2008-08-24 14:45:43 +00:00
#
##############################################################################
2012-06-04 10:56:10 +00:00
import pdb
2012-06-07 13:19:30 +00:00
import io
2012-07-13 14:36:47 +00:00
import openerp
2012-06-07 13:19:30 +00:00
import addons
2008-08-24 14:45:43 +00:00
import time
2010-10-15 14:01:53 +00:00
from datetime import datetime
from dateutil . relativedelta import relativedelta
2012-01-05 13:13:19 +00:00
import logging
2012-02-13 10:24:32 +00:00
from PIL import Image
2010-10-26 05:37:43 +00:00
import netsvc
from osv import fields , osv
2008-12-20 19:33:44 +00:00
from tools . translate import _
2009-06-16 08:10:56 +00:00
from decimal import Decimal
2010-04-26 10:30:38 +00:00
import decimal_precision as dp
2008-08-24 14:45:43 +00:00
2012-01-05 13:13:19 +00:00
_logger = logging . getLogger ( __name__ )
2012-04-04 12:31:14 +00:00
class pos_config ( osv . osv ) :
_name = ' pos.config '
2012-05-09 08:19:42 +00:00
POS_CONFIG_STATE = [
( ' active ' , ' Active ' ) ,
( ' inactive ' , ' Inactive ' ) ,
( ' deprecated ' , ' Deprecated ' )
]
2012-04-04 12:31:14 +00:00
_columns = {
2012-05-13 11:39:37 +00:00
' name ' : fields . char ( ' Point of Sale Name ' , size = 32 , select = 1 ,
required = True , help = " An internal identification of the point of sale " ) ,
' journal_ids ' : fields . many2many ( ' account.journal ' , ' pos_config_journal_rel ' ,
' pos_config_id ' , ' journal_id ' , ' Available Payment Methods ' ,
domain = " [( ' journal_user ' , ' = ' , True )] " , ) ,
2012-05-09 08:19:42 +00:00
' shop_id ' : fields . many2one ( ' sale.shop ' , ' Shop ' ,
2012-05-13 11:39:37 +00:00
required = True ) ,
' journal_id ' : fields . many2one ( ' account.journal ' , ' Sale Journal ' ,
required = True , domain = [ ( ' type ' , ' = ' , ' sale ' ) ] ,
help = " Accounting journal used to post sales entries. " ) ,
' iface_self_checkout ' : fields . boolean ( ' Self Checkout Mode ' ,
help = " Check this if this point of sale should open by default in a self checkout mode. If unchecked, OpenERP uses the normal cashier mode by default. " ) ,
' iface_websql ' : fields . boolean ( ' WebSQL (Faster but Chrome Only) ' ,
help = " If have more than 200 products, it ' s highly suggested to use WebSQL " \
" to store the data in the browser, instead of localStore mechanism. " \
" It ' s more efficient but works on the Chrome browser only. "
) ,
2012-06-04 13:22:39 +00:00
' iface_led ' : fields . boolean ( ' Help Notification ' ) ,
2012-04-04 12:31:14 +00:00
' iface_cashdrawer ' : fields . boolean ( ' Cashdrawer Interface ' ) ,
' iface_payment_terminal ' : fields . boolean ( ' Payment Terminal Interface ' ) ,
' iface_electronic_scale ' : fields . boolean ( ' Electronic Scale Interface ' ) ,
' iface_barscan ' : fields . boolean ( ' BarScan Interface ' ) ,
' iface_vkeyboard ' : fields . boolean ( ' Virtual KeyBoard Interface ' ) ,
2012-05-09 15:12:21 +00:00
' iface_print_via_proxy ' : fields . boolean ( ' Print via Proxy ' ) ,
2012-04-04 12:31:14 +00:00
2012-05-13 11:39:37 +00:00
' state ' : fields . selection ( POS_CONFIG_STATE , ' State ' , required = True , readonly = True ) ,
' sequence_id ' : fields . many2one ( ' ir.sequence ' , ' Order IDs Sequence ' , readonly = True ,
help = " This sequence is automatically created by OpenERP but you can change it " \
" to customize the reference numbers of your orders. " ) ,
2012-05-13 11:04:17 +00:00
' session_ids ' : fields . one2many ( ' pos.session ' , ' config_id ' , ' Sessions ' ) ,
2012-06-01 15:44:29 +00:00
' group_by ' : fields . boolean ( ' Group By ' , help = " Check this if you want to group the Journal Items by Product while a Session " ) ,
2012-04-04 12:31:14 +00:00
}
2012-05-13 11:04:17 +00:00
def name_get ( self , cr , uid , ids , context = None ) :
result = [ ]
states = {
' opening_control ' : _ ( ' Opening Control ' ) ,
' opened ' : _ ( ' In Progress ' ) ,
' closing_control ' : _ ( ' Closing Control ' ) ,
' closed ' : _ ( ' Closed & Posted ' ) ,
}
for record in self . browse ( cr , uid , ids , context = context ) :
if ( not record . session_ids ) or ( record . session_ids [ 0 ] . state == ' closed ' ) :
result . append ( ( record . id , record . name + ' ( ' + _ ( ' not used ' ) + ' ) ' ) )
continue
session = record . session_ids [ 0 ]
result . append ( ( record . id , record . name + ' ( ' + session . user_id . name + ' , ' + states [ session . state ] + ' ) ' ) )
return result
2012-05-12 22:37:43 +00:00
def _default_sale_journal ( self , cr , uid , context = None ) :
res = self . pool . get ( ' account.journal ' ) . search ( cr , uid , [ ( ' type ' , ' = ' , ' sale ' ) ] , limit = 1 )
return res and res [ 0 ] or False
2012-04-26 12:30:17 +00:00
2012-05-12 22:37:43 +00:00
def _default_shop ( self , cr , uid , context = None ) :
res = self . pool . get ( ' sale.shop ' ) . search ( cr , uid , [ ] )
return res and res [ 0 ] or False
2012-04-26 12:30:17 +00:00
2012-05-12 22:37:43 +00:00
_defaults = {
' state ' : POS_CONFIG_STATE [ 0 ] [ 0 ] ,
' shop_id ' : _default_shop ,
2012-06-01 15:44:29 +00:00
' journal_id ' : _default_sale_journal ,
' group_by ' : True ,
2012-05-12 22:37:43 +00:00
}
2012-04-04 12:31:14 +00:00
def set_active ( self , cr , uid , ids , context = None ) :
return self . write ( cr , uid , ids , { ' state ' : ' active ' } , context = context )
def set_inactive ( self , cr , uid , ids , context = None ) :
return self . write ( cr , uid , ids , { ' state ' : ' inactive ' } , context = context )
def set_deprecate ( self , cr , uid , ids , context = None ) :
return self . write ( cr , uid , ids , { ' state ' : ' deprecated ' } , context = context )
2012-04-26 12:30:17 +00:00
def create ( self , cr , uid , values , context = None ) :
proxy = self . pool . get ( ' ir.sequence ' )
sequence_values = dict (
2012-05-12 22:37:43 +00:00
name = ' PoS %s ' % values [ ' name ' ] ,
padding = 5 ,
prefix = " %s / " % values [ ' name ' ] ,
2012-04-26 12:30:17 +00:00
)
sequence_id = proxy . create ( cr , uid , sequence_values , context = context )
values [ ' sequence_id ' ] = sequence_id
return super ( pos_config , self ) . create ( cr , uid , values , context = context )
def unlink ( self , cr , uid , ids , context = None ) :
for obj in self . browse ( cr , uid , ids , context = context ) :
if obj . sequence_id :
obj . sequence_id . unlink ( )
return super ( pos_config , self ) . unlink ( cr , uid , ids , context = context )
2012-04-04 12:31:14 +00:00
pos_config ( )
class pos_session ( osv . osv ) :
_name = ' pos.session '
2012-05-13 11:04:17 +00:00
_order = ' id desc '
2012-04-04 12:31:14 +00:00
2012-05-09 13:30:18 +00:00
POS_SESSION_STATE = [
( ' opening_control ' , ' Opening Control ' ) , # Signal open
2012-05-13 11:04:17 +00:00
( ' opened ' , ' In Progress ' ) , # Signal closing
2012-05-09 13:30:18 +00:00
( ' closing_control ' , ' Closing Control ' ) , # Signal close
2012-05-10 07:48:04 +00:00
( ' closed ' , ' Closed & Posted ' ) ,
2012-05-09 13:30:18 +00:00
]
2012-04-10 11:24:29 +00:00
2012-05-09 14:22:11 +00:00
def _compute_cash_register_id ( self , cr , uid , ids , fieldnames , args , context = None ) :
result = dict . fromkeys ( ids , False )
for record in self . browse ( cr , uid , ids , context = context ) :
2012-05-12 22:37:43 +00:00
for st in record . statement_ids :
if st . journal_id . type == ' cash ' :
result [ record . id ] = st . id
2012-05-09 14:22:11 +00:00
break
2012-05-11 21:29:12 +00:00
return result
2012-05-30 14:35:43 +00:00
def _compute_controls ( self , cr , uid , ids , fieldnames , args , context = None ) :
result = { }
for record in self . browse ( cr , uid , ids , context = context ) :
has_opening_control = False
has_closing_control = False
for journal in record . config_id . journal_ids :
if journal . opening_control == True :
has_opening_control = True
if journal . closing_control == True :
has_closing_control = True
if has_opening_control and has_closing_control :
break
values = {
' has_opening_control ' : has_opening_control ,
' has_closing_control ' : has_closing_control ,
}
result [ record . id ] = values
return result
2012-04-04 12:31:14 +00:00
_columns = {
2012-05-12 22:37:43 +00:00
' config_id ' : fields . many2one ( ' pos.config ' , ' Point of Sale ' ,
2012-05-13 11:39:37 +00:00
help = " The physical point of sale you will use. " ,
2012-05-09 08:19:42 +00:00
required = True ,
select = 1 ,
domain = " [( ' state ' , ' = ' , ' active ' )] " ,
2012-05-09 13:30:18 +00:00
# readonly=True,
# states={'draft' : [('readonly', False)]}
2012-05-09 08:19:42 +00:00
) ,
2012-05-12 22:37:43 +00:00
' name ' : fields . char ( ' Session ID ' , size = 32 ,
2012-05-09 08:19:42 +00:00
required = True ,
2012-05-09 13:30:18 +00:00
# readonly=True,
# states={'draft' : [('readonly', False)]}
2012-05-09 08:19:42 +00:00
) ,
2012-05-12 22:37:43 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Responsible ' ,
2012-05-09 08:19:42 +00:00
required = True ,
select = 1 ,
2012-05-09 13:30:18 +00:00
# readonly=True,
# states={'draft' : [('readonly', False)]}
2012-05-09 08:19:42 +00:00
) ,
' start_at ' : fields . datetime ( ' Opening Date ' ) ,
2012-04-10 11:24:29 +00:00
' stop_at ' : fields . datetime ( ' Closing Date ' ) ,
2012-05-09 08:19:42 +00:00
' state ' : fields . selection ( POS_SESSION_STATE , ' State ' ,
2012-05-13 11:39:37 +00:00
required = True , readonly = True ,
select = 1 ) ,
2012-04-26 12:30:17 +00:00
2012-05-09 14:22:11 +00:00
' cash_register_id ' : fields . function ( _compute_cash_register_id , method = True ,
2012-05-13 11:39:37 +00:00
type = ' many2one ' , relation = ' account.bank.statement ' ,
string = ' Cash Register ' , store = True ) ,
2012-04-26 12:30:17 +00:00
2012-05-10 07:48:04 +00:00
' opening_details_ids ' : fields . related ( ' cash_register_id ' , ' opening_details_ids ' ,
2012-05-13 11:39:37 +00:00
type = ' one2many ' , relation = ' account.cashbox.line ' ,
string = ' Opening Cash Control ' ) ,
2012-04-26 12:30:17 +00:00
' details_ids ' : fields . related ( ' cash_register_id ' , ' details_ids ' ,
2012-05-13 11:39:37 +00:00
type = ' one2many ' , relation = ' account.cashbox.line ' ,
string = ' Cash Control ' ) ,
2012-05-11 21:29:12 +00:00
' cash_register_balance_end_real ' : fields . related ( ' cash_register_id ' , ' balance_end_real ' ,
2012-05-13 11:39:37 +00:00
type = ' float ' ,
digits_compute = dp . get_precision ( ' Account ' ) ,
string = " Ending Balance " ,
help = " Computed using the cash control lines " ,
readonly = True ) ,
2012-05-11 21:29:12 +00:00
' cash_register_balance_start ' : fields . related ( ' cash_register_id ' , ' balance_start ' ,
2012-05-13 11:39:37 +00:00
type = ' float ' ,
digits_compute = dp . get_precision ( ' Account ' ) ,
string = " Starting Balance " ,
help = " Computed using the cash control at the opening. " ,
readonly = True ) ,
2012-05-11 21:29:12 +00:00
' cash_register_total_entry_encoding ' : fields . related ( ' cash_register_id ' , ' total_entry_encoding ' ,
2012-05-13 11:39:37 +00:00
string = ' Total Cash Transaction ' ,
readonly = True ) ,
2012-05-11 21:29:12 +00:00
' cash_register_balance_end ' : fields . related ( ' cash_register_id ' , ' balance_end ' ,
2012-05-13 11:39:37 +00:00
type = ' float ' ,
digits_compute = dp . get_precision ( ' Account ' ) ,
string = " Computed Balance " ,
help = " Computed with the initial cash control and the sum of all payments. " ,
readonly = True ) ,
2012-05-11 21:29:12 +00:00
' cash_register_difference ' : fields . related ( ' cash_register_id ' , ' difference ' ,
2012-05-13 11:39:37 +00:00
type = ' float ' ,
string = ' Difference ' ,
help = " Difference between the counted cash control at the closing and the computed balance. " ,
readonly = True ) ,
2012-05-10 07:48:04 +00:00
2012-05-09 08:19:42 +00:00
' journal_ids ' : fields . related ( ' config_id ' , ' journal_ids ' ,
type = ' many2many ' ,
readonly = True ,
relation = ' account.journal ' ,
2012-05-13 11:39:37 +00:00
string = ' Available Payment Methods ' ) ,
2012-05-07 13:09:46 +00:00
' order_ids ' : fields . one2many ( ' pos.order ' , ' session_id ' , ' Orders ' ) ,
2012-05-09 14:22:11 +00:00
2012-05-10 07:48:04 +00:00
' statement_ids ' : fields . one2many ( ' account.bank.statement ' , ' pos_session_id ' , ' Bank Statement ' , readonly = True ) ,
2012-05-30 14:35:43 +00:00
' has_opening_control ' : fields . function ( _compute_controls , string = ' Has Opening Control ' , multi = ' control ' , type = ' boolean ' ) ,
' has_closing_control ' : fields . function ( _compute_controls , string = ' Has Closing Control ' , multi = ' control ' , type = ' boolean ' ) ,
2012-04-10 11:24:29 +00:00
}
_defaults = {
' name ' : ' / ' ,
' user_id ' : lambda obj , cr , uid , context : uid ,
2012-05-09 13:30:18 +00:00
' state ' : ' opening_control ' ,
2012-04-04 12:31:14 +00:00
}
2012-04-26 12:30:17 +00:00
_sql_constraints = [
( ' uniq_name ' , ' unique(name) ' , " The name of this POS Session must be unique ! " ) ,
]
2012-05-10 11:25:33 +00:00
def _check_unicity ( self , cr , uid , ids , context = None ) :
for session in self . browse ( cr , uid , ids , context = None ) :
# open if there is no session in 'opening_control', 'opened', 'closing_control' for one user
domain = [
( ' state ' , ' != ' , ' closed ' ) ,
2012-05-12 22:37:43 +00:00
( ' user_id ' , ' = ' , uid )
2012-05-10 11:25:33 +00:00
]
count = self . search_count ( cr , uid , domain , context = context )
2012-05-12 22:37:43 +00:00
if count > 1 :
2012-05-10 11:25:33 +00:00
return False
return True
def _check_pos_config ( self , cr , uid , ids , context = None ) :
for session in self . browse ( cr , uid , ids , context = None ) :
domain = [
( ' state ' , ' != ' , ' closed ' ) ,
2012-05-12 22:37:43 +00:00
( ' config_id ' , ' = ' , session . config_id . id )
2012-05-10 11:25:33 +00:00
]
count = self . search_count ( cr , uid , domain , context = context )
2012-05-12 22:37:43 +00:00
if count > 1 :
2012-05-10 11:25:33 +00:00
return False
return True
2012-05-12 22:37:43 +00:00
_constraints = [
( _check_unicity , " You can not create two active sessions with the same responsible! " , [ ' user_id ' , ' state ' ] ) ,
( _check_pos_config , " You can not create two active sessions related to the same point of sale! " , [ ' config_id ' ] ) ,
2012-05-10 11:25:33 +00:00
]
2012-04-10 11:24:29 +00:00
def create ( self , cr , uid , values , context = None ) :
2012-04-26 12:30:17 +00:00
config_id = values . get ( ' config_id ' , False ) or False
2012-05-09 14:22:11 +00:00
pos_config = None
2012-04-26 12:30:17 +00:00
if config_id :
pos_config = self . pool . get ( ' pos.config ' ) . browse ( cr , uid , config_id , context = context )
2012-05-09 14:22:11 +00:00
bank_statement_ids = [ ]
for journal in pos_config . journal_ids :
bank_values = {
' journal_id ' : journal . id ,
2012-05-12 22:37:43 +00:00
' user_id ' : uid ,
2012-05-09 14:22:11 +00:00
}
statement_id = self . pool . get ( ' account.bank.statement ' ) . create ( cr , uid , bank_values , context = context )
2012-05-12 22:37:43 +00:00
bank_statement_ids . append ( statement_id )
2012-05-09 14:22:11 +00:00
values . update ( {
' name ' : pos_config . sequence_id . _next ( ) ,
' statement_ids ' : [ ( 6 , 0 , bank_statement_ids ) ]
2012-05-12 22:37:43 +00:00
} )
2012-04-10 11:24:29 +00:00
return super ( pos_session , self ) . create ( cr , uid , values , context = context )
2012-05-08 15:28:05 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
for obj in self . browse ( cr , uid , ids , context = context ) :
2012-05-09 14:22:11 +00:00
for statement in obj . statement_ids :
statement . unlink ( context = context )
2012-05-08 15:28:05 +00:00
return True
2012-04-10 11:24:29 +00:00
def wkf_action_open ( self , cr , uid , ids , context = None ) :
# si pas de date start_at, je balance une date, sinon on utilise celle de l'utilisateur
2012-04-30 15:05:57 +00:00
for record in self . browse ( cr , uid , ids , context = context ) :
values = { }
if not record . start_at :
values [ ' start_at ' ] = time . strftime ( ' % Y- % m- %d % H: % M: % S ' )
values [ ' state ' ] = ' opened '
record . write ( values , context = context )
2012-05-09 14:22:11 +00:00
for st in record . statement_ids :
st . button_open ( context = context )
2012-04-30 15:05:57 +00:00
return True
2012-04-10 11:24:29 +00:00
2012-05-30 14:35:43 +00:00
def wkf_action_opening_control ( self , cr , uid , ids , context = None ) :
return self . write ( cr , uid , ids , { ' state ' : ' opening_control ' } , context = context )
2012-05-09 13:30:18 +00:00
def wkf_action_closing_control ( self , cr , uid , ids , context = None ) :
2012-05-13 12:08:12 +00:00
for session in self . browse ( cr , uid , ids , context = context ) :
for statement in session . statement_ids :
if not statement . journal_id . closing_control :
if statement . balance_end < > statement . balance_end_real :
self . pool . get ( ' account.bank.statement ' ) . write ( cr , uid ,
[ statement . id ] , { ' balance_end_real ' : statement . balance_end } )
2012-05-12 22:37:43 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' closing_control ' , ' stop_at ' : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) } , context = context )
def wkf_action_close ( self , cr , uid , ids , context = None ) :
2012-05-07 13:09:46 +00:00
# Close CashBox
2012-05-12 22:37:43 +00:00
bsl = self . pool . get ( ' account.bank.statement.line ' )
2012-05-09 10:39:59 +00:00
for record in self . browse ( cr , uid , ids , context = context ) :
2012-05-09 14:22:11 +00:00
for st in record . statement_ids :
2012-05-12 22:37:43 +00:00
if abs ( st . difference ) > st . journal_id . amount_authorized_diff :
2012-05-13 12:08:12 +00:00
# The pos manager can close statements with maximums.
if not self . pool . get ( ' ir.model.access ' ) . check_groups ( cr , uid , " point_of_sale.group_pos_manager " ) :
raise osv . except_osv ( _ ( ' Error ! ' ) ,
_ ( " Your ending balance is too different from the theorical cash closing ( %.2f ), the maximum allowed is: %.2f . You can contact your manager to force it. " ) % ( st . difference , st . journal_id . amount_authorized_diff ) )
2012-05-12 22:37:43 +00:00
if st . difference :
if st . difference > 0.0 :
name = _ ( ' Point of Sale Profit ' )
account_id = st . journal_id . profit_account_id . id
else :
account_id = st . journal_id . loss_account_id . id
name = _ ( ' Point of Sale Loss ' )
if not account_id :
raise osv . except_osv ( _ ( ' Error ! ' ) ,
_ ( " Please set your profit and loss accounts on your payment method ' %s ' . " ) % ( st . journal_id . name , ) )
bsl . create ( cr , uid , {
' statement_id ' : st . id ,
' amount ' : st . difference ,
' ref ' : record . name ,
' name ' : name ,
' account_id ' : account_id
} , context = context )
2012-04-10 11:24:29 +00:00
2012-05-12 22:37:43 +00:00
getattr ( st , ' button_confirm_ %s ' % st . journal_id . type ) ( context = context )
2012-05-07 13:09:46 +00:00
self . _confirm_orders ( cr , uid , ids , context = context )
2012-05-09 13:30:18 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' closed ' } , context = context )
2012-04-10 11:24:29 +00:00
2012-05-07 13:09:46 +00:00
def _confirm_orders ( self , cr , uid , ids , context = None ) :
wf_service = netsvc . LocalService ( " workflow " )
for session in self . browse ( cr , uid , ids , context = context ) :
2012-06-04 10:56:10 +00:00
order_ids = [ order . id for order in session . order_ids if order . state == ' paid ' ]
2012-06-01 09:53:56 +00:00
move_id = self . pool . get ( ' account.move ' ) . create ( cr , uid , { ' ref ' : session . name , ' journal_id ' : session . config_id . journal_id . id , } , context = context )
2012-06-04 10:56:10 +00:00
2012-06-01 15:44:29 +00:00
self . pool . get ( ' pos.order ' ) . _create_account_move_line ( cr , uid , order_ids , session , move_id , context = context )
2012-06-01 09:53:56 +00:00
2012-05-07 13:09:46 +00:00
for order in session . order_ids :
if order . state != ' paid ' :
raise osv . except_osv (
_ ( ' Error ! ' ) ,
_ ( " You can not confirm all orders of this session, because they have not the ' paid ' status " ) )
else :
wf_service . trg_validate ( uid , ' pos.order ' , order . id , ' done ' , cr )
return True
2012-05-25 13:07:59 +00:00
def open_frontend_cb ( self , cr , uid , ids , context = None ) :
if not context :
context = { }
if not ids :
return { }
context . update ( { ' session_id ' : ids [ 0 ] } )
return {
' type ' : ' ir.actions.client ' ,
' name ' : ' Start Point Of Sale ' ,
' tag ' : ' pos.ui ' ,
' context ' : context ,
}
2012-04-04 12:31:14 +00:00
pos_session ( )
2008-08-24 14:45:43 +00:00
class pos_order ( osv . osv ) :
_name = " pos.order "
_description = " Point of Sale "
2011-09-25 14:09:30 +00:00
_order = " id desc "
2012-03-30 08:27:51 +00:00
2012-01-05 13:13:19 +00:00
def create_from_ui ( self , cr , uid , orders , context = None ) :
#_logger.info("orders: %r", orders)
2012-06-04 11:15:50 +00:00
order_ids = [ ]
for tmp_order in orders :
order = tmp_order [ ' data ' ]
2012-02-13 16:12:01 +00:00
# order :: {'name': 'Order 1329148448062', 'amount_paid': 9.42, 'lines': [[0, 0, {'discount': 0, 'price_unit': 1.46, 'product_id': 124, 'qty': 5}], [0, 0, {'discount': 0, 'price_unit': 0.53, 'product_id': 62, 'qty': 4}]], 'statement_ids': [[0, 0, {'journal_id': 7, 'amount': 9.42, 'name': '2012-02-13 15:54:12', 'account_id': 12, 'statement_id': 21}]], 'amount_tax': 0, 'amount_return': 0, 'amount_total': 9.42}
# get statements out of order because they will be generated with add_payment to ensure
# the module behavior is the same when using the front-end or the back-end
2012-06-04 16:08:33 +00:00
statement_ids = order . get ( ' statement_ids ' , [ ] )
2012-02-13 11:28:23 +00:00
order_id = self . create ( cr , uid , order , context )
2012-06-04 11:15:50 +00:00
order_ids . append ( order_id )
2012-02-13 16:12:01 +00:00
# call add_payment; refer to wizard/pos_payment for data structure
# add_payment launches the 'paid' signal to advance the workflow to the 'paid' state
2012-06-04 16:08:33 +00:00
2012-02-13 16:12:01 +00:00
data = {
' journal ' : statement_ids [ 0 ] [ 2 ] [ ' journal_id ' ] ,
2012-06-04 11:15:50 +00:00
' amount ' : order [ ' amount_paid ' ] ,
' payment_name ' : order [ ' name ' ] ,
2012-02-13 16:12:01 +00:00
' payment_date ' : statement_ids [ 0 ] [ 2 ] [ ' name ' ] ,
}
2012-06-04 16:08:33 +00:00
wf_service = netsvc . LocalService ( " workflow " )
wf_service . trg_validate ( uid , ' pos.order ' , order_id , ' paid ' , cr )
wf_service . trg_write ( uid , ' pos.order ' , order_id , cr )
#self.add_payment(cr, uid, order_id, data, context=context)
2012-06-04 11:15:50 +00:00
return order_ids
2010-04-08 09:20:32 +00:00
2010-06-11 13:03:03 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
2008-12-20 09:43:37 +00:00
for rec in self . browse ( cr , uid , ids , context = context ) :
2011-09-25 14:09:30 +00:00
if rec . state not in ( ' draft ' , ' cancel ' ) :
raise osv . except_osv ( _ ( ' Unable to Delete ! ' ) , _ ( ' In order to delete a sale, it must be new or cancelled. ' ) )
2008-12-20 09:43:37 +00:00
return super ( pos_order , self ) . unlink ( cr , uid , ids , context = context )
2011-09-25 14:09:30 +00:00
def onchange_partner_id ( self , cr , uid , ids , part = False , context = None ) :
2008-12-20 09:43:37 +00:00
if not part :
2010-10-27 04:29:13 +00:00
return { ' value ' : { } }
2010-10-26 05:37:43 +00:00
pricelist = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , part , context = context ) . property_product_pricelist . id
return { ' value ' : { ' pricelist_id ' : pricelist } }
2008-08-24 14:45:43 +00:00
2010-04-26 10:30:38 +00:00
def _amount_all ( self , cr , uid , ids , name , args , context = None ) :
2010-07-12 13:40:45 +00:00
tax_obj = self . pool . get ( ' account.tax ' )
cur_obj = self . pool . get ( ' res.currency ' )
2010-10-26 05:37:43 +00:00
res = { }
for order in self . browse ( cr , uid , ids , context = context ) :
2010-04-26 10:30:38 +00:00
res [ order . id ] = {
' amount_paid ' : 0.0 ,
' amount_return ' : 0.0 ,
' amount_tax ' : 0.0 ,
2010-07-12 13:40:45 +00:00
}
2011-09-25 14:09:30 +00:00
val1 = val2 = 0.0
2010-07-12 13:40:45 +00:00
cur = order . pricelist_id . currency_id
2010-04-26 10:30:38 +00:00
for payment in order . statement_ids :
2010-10-05 06:30:26 +00:00
res [ order . id ] [ ' amount_paid ' ] + = payment . amount
res [ order . id ] [ ' amount_return ' ] + = ( payment . amount < 0 and payment . amount or 0 )
2008-08-24 14:45:43 +00:00
for line in order . lines :
2010-12-15 13:29:59 +00:00
val1 + = line . price_subtotal_incl
2011-09-25 14:09:30 +00:00
val2 + = line . price_subtotal
res [ order . id ] [ ' amount_tax ' ] = cur_obj . round ( cr , uid , cur , val1 - val2 )
res [ order . id ] [ ' amount_total ' ] = cur_obj . round ( cr , uid , cur , val1 )
2008-08-24 14:45:43 +00:00
return res
2010-07-12 13:40:45 +00:00
2010-06-11 13:03:03 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
2008-08-24 14:45:43 +00:00
if not default :
default = { }
2011-09-25 14:09:30 +00:00
d = {
2008-08-24 14:45:43 +00:00
' state ' : ' draft ' ,
' invoice_id ' : False ,
' account_move ' : False ,
2010-05-13 08:21:42 +00:00
' picking_id ' : False ,
2010-10-26 05:37:43 +00:00
' statement_ids ' : [ ] ,
2008-08-24 14:45:43 +00:00
' nb_print ' : 0 ,
2011-07-07 10:31:06 +00:00
' name ' : self . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' pos.order ' ) ,
2011-09-25 14:09:30 +00:00
}
d . update ( default )
return super ( pos_order , self ) . copy ( cr , uid , id , d , context = context )
2010-01-18 08:38:26 +00:00
2008-08-24 14:45:43 +00:00
_columns = {
2012-04-30 15:05:57 +00:00
' name ' : fields . char ( ' Order Ref ' , size = 64 , required = True , readonly = True ) ,
2010-01-18 08:38:26 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = True , readonly = True ) ,
2012-05-12 22:37:43 +00:00
' shop_id ' : fields . related ( ' session_id ' , ' config_id ' , ' shop_id ' , relation = ' sale.shop ' , type = ' many2one ' , string = ' Shop ' , store = True , readonly = True ) ,
' date_order ' : fields . datetime ( ' Order Date ' , readonly = True , select = True ) ,
2012-05-13 10:16:41 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Salesman ' , help = " Person who uses the the cash register. It could be a reliever, a student or an interim employee. " ) ,
2011-07-01 23:41:24 +00:00
' amount_tax ' : fields . function ( _amount_all , string = ' Taxes ' , digits_compute = dp . get_precision ( ' Point Of Sale ' ) , multi = ' all ' ) ,
' amount_total ' : fields . function ( _amount_all , string = ' Total ' , multi = ' all ' ) ,
' amount_paid ' : fields . function ( _amount_all , string = ' Paid ' , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , readonly = True , digits_compute = dp . get_precision ( ' Point Of Sale ' ) , multi = ' all ' ) ,
' amount_return ' : fields . function ( _amount_all , ' Returned ' , digits_compute = dp . get_precision ( ' Point Of Sale ' ) , multi = ' all ' ) ,
2010-01-18 08:38:26 +00:00
' lines ' : fields . one2many ( ' pos.order.line ' , ' order_id ' , ' Order Lines ' , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , readonly = True ) ,
2010-10-26 05:37:43 +00:00
' statement_ids ' : fields . one2many ( ' account.bank.statement.line ' , ' pos_statement_id ' , ' Payments ' , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , readonly = True ) ,
2010-01-18 08:38:26 +00:00
' pricelist_id ' : fields . many2one ( ' product.pricelist ' , ' Pricelist ' , required = True , states = { ' draft ' : [ ( ' readonly ' , False ) ] } , readonly = True ) ,
2010-10-26 05:37:43 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Customer ' , change_default = True , select = 1 , states = { ' draft ' : [ ( ' readonly ' , False ) ] , ' paid ' : [ ( ' readonly ' , False ) ] } ) ,
2011-09-25 14:09:30 +00:00
2012-04-30 15:05:57 +00:00
' session_id ' : fields . many2one ( ' pos.session ' , ' Session ' ,
2012-05-04 12:51:58 +00:00
#required=True,
2012-04-30 15:05:57 +00:00
select = 1 ,
domain = " [( ' state ' , ' = ' , ' opened ' )] " ,
states = { ' draft ' : [ ( ' readonly ' , False ) ] } ,
readonly = True ) ,
2012-04-10 11:24:29 +00:00
2011-09-25 14:09:30 +00:00
' state ' : fields . selection ( [ ( ' draft ' , ' New ' ) ,
2011-12-08 12:01:11 +00:00
( ' cancel ' , ' Cancelled ' ) ,
( ' paid ' , ' Paid ' ) ,
2011-09-25 14:09:30 +00:00
( ' done ' , ' Posted ' ) ,
2011-12-08 12:01:11 +00:00
( ' invoiced ' , ' Invoiced ' ) ] ,
2012-05-04 11:57:48 +00:00
' Status ' , readonly = True ) ,
2011-09-25 14:09:30 +00:00
2010-01-18 08:38:26 +00:00
' invoice_id ' : fields . many2one ( ' account.invoice ' , ' Invoice ' ) ,
2011-09-25 14:09:30 +00:00
' account_move ' : fields . many2one ( ' account.move ' , ' Journal Entry ' , readonly = True ) ,
' picking_id ' : fields . many2one ( ' stock.picking ' , ' Picking ' , readonly = True ) ,
2010-01-18 08:38:26 +00:00
' note ' : fields . text ( ' Internal Notes ' ) ,
2009-01-27 11:15:46 +00:00
' nb_print ' : fields . integer ( ' Number of Print ' , readonly = True ) ,
2012-05-12 22:37:43 +00:00
2012-05-13 10:16:41 +00:00
' sale_journal ' : fields . related ( ' session_id ' , ' config_id ' , ' journal_id ' , relation = ' account.journal ' , type = ' many2one ' , string = ' Sale Journal ' , store = True , readonly = True ) ,
2010-01-18 08:38:26 +00:00
}
2012-05-12 22:37:43 +00:00
def _default_session ( self , cr , uid , context = None ) :
so = self . pool . get ( ' pos.session ' )
session_ids = so . search ( cr , uid , [ ( ' state ' , ' = ' , ' opened ' ) , ( ' user_id ' , ' = ' , uid ) ] , context = context )
return session_ids and session_ids [ 0 ] or False
2011-09-25 14:09:30 +00:00
def _default_pricelist ( self , cr , uid , context = None ) :
2011-01-17 08:28:47 +00:00
res = self . pool . get ( ' sale.shop ' ) . search ( cr , uid , [ ] , context = context )
if res :
shop = self . pool . get ( ' sale.shop ' ) . browse ( cr , uid , res [ 0 ] , context = context )
return shop . pricelist_id and shop . pricelist_id . id or False
return False
2008-08-24 14:45:43 +00:00
_defaults = {
' user_id ' : lambda self , cr , uid , context : uid ,
2010-10-26 05:37:43 +00:00
' state ' : ' draft ' ,
2012-04-30 15:05:57 +00:00
' name ' : ' / ' ,
2010-11-04 12:27:41 +00:00
' date_order ' : lambda * a : time . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
2010-10-26 05:37:43 +00:00
' nb_print ' : 0 ,
2012-05-12 22:37:43 +00:00
' session_id ' : _default_session ,
2010-01-18 08:38:26 +00:00
' company_id ' : lambda self , cr , uid , c : self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , c ) . company_id . id ,
2011-09-25 14:09:30 +00:00
' pricelist_id ' : _default_pricelist ,
2008-08-24 14:45:43 +00:00
}
2012-04-30 15:05:57 +00:00
def create ( self , cr , uid , values , context = None ) :
values [ ' name ' ] = self . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' pos.order ' )
return super ( pos_order , self ) . create ( cr , uid , values , context = context )
2008-08-24 14:45:43 +00:00
def test_paid ( self , cr , uid , ids , context = None ) :
2011-09-25 14:09:30 +00:00
""" A Point of Sale is paid when the sum
2010-04-08 09:20:32 +00:00
@return : True
2010-07-12 13:40:45 +00:00
"""
2010-10-26 05:37:43 +00:00
for order in self . browse ( cr , uid , ids , context = context ) :
2008-08-24 14:45:43 +00:00
if order . lines and not order . amount_total :
return True
2010-01-18 08:38:26 +00:00
if ( not order . lines ) or ( not order . statement_ids ) or \
2011-09-25 14:09:30 +00:00
( abs ( order . amount_total - order . amount_paid ) > 0.00001 ) :
2008-08-24 14:45:43 +00:00
return False
return True
2010-06-11 13:03:03 +00:00
def create_picking ( self , cr , uid , ids , context = None ) :
2008-08-24 14:45:43 +00:00
""" Create a picking for each order and validate it. """
picking_obj = self . pool . get ( ' stock.picking ' )
2011-04-26 07:39:18 +00:00
partner_obj = self . pool . get ( ' res.partner ' )
2011-09-25 14:09:30 +00:00
move_obj = self . pool . get ( ' stock.move ' )
for order in self . browse ( cr , uid , ids , context = context ) :
2011-12-19 22:00:53 +00:00
if not order . state == ' draft ' :
continue
2011-04-26 07:39:18 +00:00
addr = order . partner_id and partner_obj . address_get ( cr , uid , [ order . partner_id . id ] , [ ' delivery ' ] ) or { }
2011-09-25 14:09:30 +00:00
picking_id = picking_obj . create ( cr , uid , {
' origin ' : order . name ,
2012-03-30 08:27:51 +00:00
' partner_id ' : addr . get ( ' delivery ' , False ) ,
2011-09-25 14:09:30 +00:00
' type ' : ' out ' ,
' company_id ' : order . company_id . id ,
' move_type ' : ' direct ' ,
' note ' : order . note or " " ,
' invoice_state ' : ' none ' ,
' auto_picking ' : True ,
} , context = context )
self . write ( cr , uid , [ order . id ] , { ' picking_id ' : picking_id } , context = context )
location_id = order . shop_id . warehouse_id . lot_stock_id . id
output_id = order . shop_id . warehouse_id . lot_output_id . id
for line in order . lines :
if line . product_id and line . product_id . type == ' service ' :
continue
if line . qty < 0 :
location_id , output_id = output_id , location_id
move_obj . create ( cr , uid , {
' name ' : line . name ,
' product_uom ' : line . product_id . uom_id . id ,
' product_uos ' : line . product_id . uom_id . id ,
' picking_id ' : picking_id ,
' product_id ' : line . product_id . id ,
' product_uos_qty ' : abs ( line . qty ) ,
' product_qty ' : abs ( line . qty ) ,
' tracking_id ' : False ,
2008-08-24 14:45:43 +00:00
' state ' : ' draft ' ,
2011-09-25 14:09:30 +00:00
' location_id ' : location_id ,
' location_dest_id ' : output_id ,
2010-10-26 05:37:43 +00:00
} , context = context )
2011-09-25 14:09:30 +00:00
if line . qty < 0 :
location_id , output_id = output_id , location_id
2008-08-24 14:45:43 +00:00
2008-12-20 09:43:37 +00:00
wf_service = netsvc . LocalService ( " workflow " )
2010-01-18 08:38:26 +00:00
wf_service . trg_validate ( uid , ' stock.picking ' , picking_id , ' button_confirm ' , cr )
2010-10-26 05:37:43 +00:00
picking_obj . force_assign ( cr , uid , [ picking_id ] , context )
2008-08-24 14:45:43 +00:00
return True
2010-01-18 08:38:26 +00:00
def cancel_order ( self , cr , uid , ids , context = None ) :
2010-07-12 13:40:45 +00:00
""" Changes order state to cancel
2010-04-08 09:20:32 +00:00
@return : True
2010-07-12 13:40:45 +00:00
"""
2011-09-25 14:09:30 +00:00
stock_picking_obj = self . pool . get ( ' stock.picking ' )
for order in self . browse ( cr , uid , ids , context = context ) :
wf_service . trg_validate ( uid , ' stock.picking ' , order . picking_id . id , ' button_cancel ' , cr )
if stock_picking_obj . browse ( cr , uid , order . picking_id . id , context = context ) . state < > ' cancel ' :
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' Unable to cancel the picking. ' ) )
2010-10-26 05:37:43 +00:00
self . write ( cr , uid , ids , { ' state ' : ' cancel ' } , context = context )
2008-08-24 14:45:43 +00:00
return True
2008-12-20 18:29:38 +00:00
def add_payment ( self , cr , uid , order_id , data , context = None ) :
2008-08-24 14:45:43 +00:00
""" Create a new payment for the order """
2012-05-08 15:28:05 +00:00
if not context :
context = { }
2010-11-05 01:29:52 +00:00
statement_obj = self . pool . get ( ' account.bank.statement ' )
2010-10-26 05:37:43 +00:00
statement_line_obj = self . pool . get ( ' account.bank.statement.line ' )
2010-01-18 08:38:26 +00:00
prod_obj = self . pool . get ( ' product.product ' )
2010-10-26 05:37:43 +00:00
property_obj = self . pool . get ( ' ir.property ' )
curr_c = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context ) . company_id
curr_company = curr_c . id
order = self . browse ( cr , uid , order_id , context = context )
2008-12-20 18:29:38 +00:00
args = {
' amount ' : data [ ' amount ' ] ,
2010-08-13 12:20:05 +00:00
}
2012-06-04 16:08:33 +00:00
if ' payment_date ' in data :
2010-01-18 08:38:26 +00:00
args [ ' date ' ] = data [ ' payment_date ' ]
2011-09-26 07:38:46 +00:00
args [ ' name ' ] = order . name
if data . get ( ' payment_name ' , False ) :
args [ ' name ' ] = args [ ' name ' ] + ' : ' + data [ ' payment_name ' ]
2010-06-11 13:03:03 +00:00
account_def = property_obj . get ( cr , uid , ' property_account_receivable ' , ' res.partner ' , context = context )
2011-10-07 13:22:46 +00:00
args [ ' account_id ' ] = ( order . partner_id and order . partner_id . property_account_receivable \
and order . partner_id . property_account_receivable . id ) or ( account_def and account_def . id ) or False
2010-01-18 08:38:26 +00:00
args [ ' partner_id ' ] = order . partner_id and order . partner_id . id or None
2011-09-30 07:12:48 +00:00
if not args [ ' account_id ' ] :
2011-10-07 13:22:46 +00:00
if not args [ ' partner_id ' ] :
msg = _ ( ' There is no receivable account defined to make payment ' )
else :
msg = _ ( ' There is no receivable account defined to make payment for the partner: " %s " (id: %d ) ' ) % ( order . partner_id . name , order . partner_id . id , )
raise osv . except_osv ( _ ( ' Configuration Error ! ' ) , msg )
2012-05-07 13:09:46 +00:00
context . pop ( ' pos_session_id ' , False )
2012-05-09 15:12:21 +00:00
try :
journal_id = long ( data [ ' journal ' ] )
except Exception :
journal_id = False
statement_id = False
for statement in order . session_id . statement_ids :
if statement . journal_id . id == journal_id :
statement_id = statement . id
break
if not statement_id :
2010-01-18 08:38:26 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' You have to open at least one cashbox ' ) )
2012-05-09 15:12:21 +00:00
args . update ( {
' statement_id ' : statement_id ,
' pos_statement_id ' : order_id ,
' journal_id ' : journal_id ,
' type ' : ' customer ' ,
' ref ' : order . name ,
} )
2010-10-26 05:37:43 +00:00
statement_line_obj . create ( cr , uid , args , context = context )
2008-08-24 14:45:43 +00:00
2008-12-20 09:43:37 +00:00
wf_service = netsvc . LocalService ( " workflow " )
2009-05-11 11:44:26 +00:00
wf_service . trg_validate ( uid , ' pos.order ' , order_id , ' paid ' , cr )
2008-12-20 09:43:37 +00:00
wf_service . trg_write ( uid , ' pos.order ' , order_id , cr )
2010-01-18 08:38:26 +00:00
return statement_id
2008-08-24 14:45:43 +00:00
2010-06-11 13:03:03 +00:00
def refund ( self , cr , uid , ids , context = None ) :
2010-10-08 06:13:09 +00:00
""" Create a copy of order for refund order """
2008-08-24 14:45:43 +00:00
clone_list = [ ]
line_obj = self . pool . get ( ' pos.order.line ' )
2010-10-26 05:37:43 +00:00
for order in self . browse ( cr , uid , ids , context = context ) :
2008-08-24 14:45:43 +00:00
clone_id = self . copy ( cr , uid , order . id , {
' name ' : order . name + ' REFUND ' ,
2011-09-25 14:09:30 +00:00
} , context = context )
2008-08-24 14:45:43 +00:00
clone_list . append ( clone_id )
2010-01-18 08:38:26 +00:00
2010-10-26 05:37:43 +00:00
for clone in self . browse ( cr , uid , clone_list , context = context ) :
2008-08-24 14:45:43 +00:00
for order_line in clone . lines :
line_obj . write ( cr , uid , [ order_line . id ] , {
2010-01-18 08:38:26 +00:00
' qty ' : - order_line . qty
2011-09-25 14:09:30 +00:00
} , context = context )
2011-01-17 11:20:56 +00:00
2011-09-25 14:09:30 +00:00
new_order = ' , ' . join ( map ( str , clone_list ) )
abs = {
#'domain': "[('id', 'in', ["+new_order+"])]",
' name ' : _ ( ' Return Products ' ) ,
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' pos.order ' ,
' res_id ' : clone_list [ 0 ] ,
' view_id ' : False ,
' context ' : context ,
' type ' : ' ir.actions.act_window ' ,
' nodestroy ' : True ,
' target ' : ' current ' ,
}
return abs
2011-01-17 11:20:56 +00:00
2011-12-18 18:33:39 +00:00
def action_invoice_state ( self , cr , uid , ids , context = None ) :
return self . write ( cr , uid , ids , { ' state ' : ' invoiced ' } , context = context )
2011-09-25 14:09:30 +00:00
def action_invoice ( self , cr , uid , ids , context = None ) :
2011-12-18 18:33:39 +00:00
wf_service = netsvc . LocalService ( " workflow " )
2008-08-24 14:45:43 +00:00
inv_ref = self . pool . get ( ' account.invoice ' )
inv_line_ref = self . pool . get ( ' account.invoice.line ' )
2010-10-26 05:37:43 +00:00
product_obj = self . pool . get ( ' product.product ' )
2008-08-24 14:45:43 +00:00
inv_ids = [ ]
2010-10-26 05:37:43 +00:00
for order in self . pool . get ( ' pos.order ' ) . browse ( cr , uid , ids , context = context ) :
2008-08-24 14:45:43 +00:00
if order . invoice_id :
inv_ids . append ( order . invoice_id . id )
continue
if not order . partner_id :
2009-03-06 22:18:24 +00:00
raise osv . except_osv ( _ ( ' Error ' ) , _ ( ' Please provide a partner for the sale. ' ) )
2008-08-24 14:45:43 +00:00
2010-10-26 05:37:43 +00:00
acc = order . partner_id . property_account_receivable . id
2008-08-24 14:45:43 +00:00
inv = {
2011-12-18 18:33:39 +00:00
' name ' : order . name ,
2008-08-24 14:45:43 +00:00
' origin ' : order . name ,
2010-10-26 05:37:43 +00:00
' account_id ' : acc ,
' journal_id ' : order . sale_journal . id or None ,
2008-08-24 14:45:43 +00:00
' type ' : ' out_invoice ' ,
' reference ' : order . name ,
' partner_id ' : order . partner_id . id ,
' comment ' : order . note or ' ' ,
2011-02-23 14:34:55 +00:00
' currency_id ' : order . pricelist_id . currency_id . id , # considering partner's sale pricelist's currency
2008-08-24 14:45:43 +00:00
}
inv . update ( inv_ref . onchange_partner_id ( cr , uid , [ ] , ' out_invoice ' , order . partner_id . id ) [ ' value ' ] )
2010-01-18 08:38:26 +00:00
if not inv . get ( ' account_id ' , None ) :
inv [ ' account_id ' ] = acc
2010-10-26 05:37:43 +00:00
inv_id = inv_ref . create ( cr , uid , inv , context = context )
2008-08-24 14:45:43 +00:00
2010-10-26 05:37:43 +00:00
self . write ( cr , uid , [ order . id ] , { ' invoice_id ' : inv_id , ' state ' : ' invoiced ' } , context = context )
2008-08-24 14:45:43 +00:00
inv_ids . append ( inv_id )
for line in order . lines :
inv_line = {
' invoice_id ' : inv_id ,
' product_id ' : line . product_id . id ,
' quantity ' : line . qty ,
}
2010-04-08 09:20:32 +00:00
inv_name = product_obj . name_get ( cr , uid , [ line . product_id . id ] , context = context ) [ 0 ] [ 1 ]
2008-08-24 14:45:43 +00:00
inv_line . update ( inv_line_ref . product_id_change ( cr , uid , [ ] ,
2010-01-18 08:38:26 +00:00
line . product_id . id ,
line . product_id . uom_id . id ,
2010-11-05 01:29:52 +00:00
line . qty , partner_id = order . partner_id . id ,
fposition_id = order . partner_id . property_account_position . id ) [ ' value ' ] )
2011-09-21 06:05:52 +00:00
if line . product_id . description_sale :
inv_line [ ' note ' ] = line . product_id . description_sale
2008-08-24 14:45:43 +00:00
inv_line [ ' price_unit ' ] = line . price_unit
inv_line [ ' discount ' ] = line . discount
2010-02-03 05:47:12 +00:00
inv_line [ ' name ' ] = inv_name
2008-08-24 14:45:43 +00:00
inv_line [ ' invoice_line_tax_id ' ] = ( ' invoice_line_tax_id ' in inv_line ) \
and [ ( 6 , 0 , inv_line [ ' invoice_line_tax_id ' ] ) ] or [ ]
2010-10-26 05:37:43 +00:00
inv_line_ref . create ( cr , uid , inv_line , context = context )
2011-09-25 17:04:16 +00:00
inv_ref . button_reset_taxes ( cr , uid , [ inv_id ] , context = context )
2011-12-18 18:33:39 +00:00
wf_service . trg_validate ( uid , ' pos.order ' , order . id , ' invoice ' , cr )
2008-08-24 14:45:43 +00:00
2011-09-25 14:09:30 +00:00
if not inv_ids : return { }
2012-03-30 08:27:51 +00:00
2011-09-25 14:09:30 +00:00
mod_obj = self . pool . get ( ' ir.model.data ' )
res = mod_obj . get_object_reference ( cr , uid , ' account ' , ' invoice_form ' )
2011-09-25 17:04:16 +00:00
res_id = res and res [ 1 ] or False
2011-09-25 14:09:30 +00:00
return {
2011-12-11 10:18:45 +00:00
' name ' : _ ( ' Customer Invoice ' ) ,
2011-09-25 14:09:30 +00:00
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
2011-12-28 09:06:08 +00:00
' view_id ' : [ res_id ] ,
2011-09-25 14:09:30 +00:00
' res_model ' : ' account.invoice ' ,
' context ' : " { ' type ' : ' out_invoice ' } " ,
' type ' : ' ir.actions.act_window ' ,
' nodestroy ' : True ,
' target ' : ' current ' ,
' res_id ' : inv_ids and inv_ids [ 0 ] or False ,
}
2008-08-24 14:45:43 +00:00
def create_account_move ( self , cr , uid , ids , context = None ) :
2012-06-01 15:44:29 +00:00
return self . _create_account_move_line ( cr , uid , ids , None , None , context = context )
2012-06-01 09:53:56 +00:00
2012-06-01 15:44:29 +00:00
def _create_account_move_line ( self , cr , uid , ids , session = None , move_id = None , context = None ) :
2012-06-01 09:53:56 +00:00
# Tricky, via the workflow, we only have one id in the ids variable
2011-09-25 14:09:30 +00:00
""" Create a account move line of order grouped by products or not. """
2008-08-24 14:45:43 +00:00
account_move_obj = self . pool . get ( ' account.move ' )
account_move_line_obj = self . pool . get ( ' account.move.line ' )
account_period_obj = self . pool . get ( ' account.period ' )
account_tax_obj = self . pool . get ( ' account.tax ' )
2012-06-01 15:44:29 +00:00
user_proxy = self . pool . get ( ' res.users ' )
property_obj = self . pool . get ( ' ir.property ' )
period = account_period_obj . find ( cr , uid , context = context ) [ 0 ]
2012-06-04 10:56:10 +00:00
#session_ids = set(order.session_id for order in self.browse(cr, uid, ids, context=context))
2012-06-01 15:44:29 +00:00
if session and not all ( session . id == order . session_id . id for order in self . browse ( cr , uid , ids , context = context ) ) :
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' The selected orders do not have the same session ! ' ) )
current_company = user_proxy . browse ( cr , uid , uid , context = context ) . company_id
grouped_data = { }
have_to_group_by = session and session . config_id . group_by or False
def compute_tax ( amount , tax , line ) :
if amount > 0 :
tax_code_id = tax [ ' base_code_id ' ]
tax_amount = line . price_subtotal * tax [ ' base_sign ' ]
else :
tax_code_id = tax [ ' ref_base_code_id ' ]
tax_amount = line . price_subtotal * tax [ ' ref_base_sign ' ]
return ( tax_code_id , tax_amount , )
2008-08-24 14:45:43 +00:00
for order in self . browse ( cr , uid , ids , context = context ) :
2012-06-01 09:53:56 +00:00
if order . account_move :
continue
2012-05-04 12:51:58 +00:00
if order . state != ' paid ' :
continue
2011-09-25 14:09:30 +00:00
2012-06-01 15:44:29 +00:00
user_company = user_proxy . browse ( cr , order . user_id . id , order . user_id . id ) . company_id
2008-08-24 14:45:43 +00:00
group_tax = { }
2010-05-17 08:44:20 +00:00
account_def = property_obj . get ( cr , uid , ' property_account_receivable ' , ' res.partner ' , context = context ) . id
2010-07-12 13:40:45 +00:00
2012-06-01 15:44:29 +00:00
order_account = order . partner_id and \
order . partner_id . property_account_receivable and \
order . partner_id . property_account_receivable . id or account_def or current_company . account_receivable . id
2008-08-24 14:45:43 +00:00
2012-06-01 09:53:56 +00:00
if move_id is None :
# Create an entry for the sale
move_id = account_move_obj . create ( cr , uid , {
' ref ' : order . name ,
' journal_id ' : order . sale_journal . id ,
} , context = context )
2008-08-24 14:45:43 +00:00
2012-06-01 15:44:29 +00:00
def insert_data ( data_type , values ) :
# if have_to_group_by:
2012-06-04 16:08:33 +00:00
sale_journal_id = order . sale_journal . id
2012-06-01 15:44:29 +00:00
# 'quantity': line.qty,
# 'product_id': line.product_id.id,
values . update ( {
' date ' : order . date_order [ : 10 ] ,
' ref ' : order . name ,
' journal_id ' : sale_journal_id ,
' period_id ' : period ,
' move_id ' : move_id ,
' company_id ' : user_company and user_company . id or False ,
} )
if data_type == ' product ' :
key = ( ' product ' , values [ ' product_id ' ] , )
elif data_type == ' tax ' :
key = ( ' tax ' , values [ ' tax_code_id ' ] , )
elif data_type == ' counter_part ' :
2012-06-04 16:08:33 +00:00
key = ( ' counter_part ' , values [ ' partner_id ' ] , values [ ' account_id ' ] )
2012-06-01 15:44:29 +00:00
else :
return
2012-06-04 10:56:10 +00:00
grouped_data . setdefault ( key , [ ] )
# if not have_to_group_by or (not grouped_data[key]):
# grouped_data[key].append(values)
# else:
# pass
2012-06-01 15:44:29 +00:00
if have_to_group_by :
2012-06-04 10:56:10 +00:00
if not grouped_data [ key ] :
grouped_data [ key ] . append ( values )
else :
current_value = grouped_data [ key ] [ 0 ]
current_value [ ' quantity ' ] = current_value . get ( ' quantity ' , 0.0 ) + values . get ( ' quantity ' , 0.0 )
current_value [ ' credit ' ] = current_value . get ( ' credit ' , 0.0 ) + values . get ( ' credit ' , 0.0 )
current_value [ ' debit ' ] = current_value . get ( ' debit ' , 0.0 ) + values . get ( ' debit ' , 0.0 )
current_value [ ' tax_amount ' ] = current_value . get ( ' tax_amount ' , 0.0 ) + values . get ( ' tax_amount ' , 0.0 )
2012-06-01 15:44:29 +00:00
else :
grouped_data [ key ] . append ( values )
2008-08-24 14:45:43 +00:00
# Create an move for each order line
2012-06-01 15:44:29 +00:00
2008-08-24 14:45:43 +00:00
for line in order . lines :
tax_amount = 0
taxes = [ t for t in line . product_id . taxes_id ]
2012-06-01 15:44:29 +00:00
computed_taxes = account_tax_obj . compute_all ( cr , uid , taxes , line . price_unit * ( 100.0 - line . discount ) / 100.0 , line . qty ) [ ' taxes ' ]
2008-08-24 14:45:43 +00:00
for tax in computed_taxes :
tax_amount + = round ( tax [ ' amount ' ] , 2 )
2012-06-01 15:44:29 +00:00
group_key = ( tax [ ' tax_code_id ' ] , tax [ ' base_code_id ' ] , tax [ ' account_collected_id ' ] , tax [ ' id ' ] )
group_tax . setdefault ( group_key , 0 )
group_tax [ group_key ] + = round ( tax [ ' amount ' ] , 2 )
2008-08-24 14:45:43 +00:00
2011-09-25 14:09:30 +00:00
amount = line . price_subtotal
2008-08-24 14:45:43 +00:00
# Search for the income account
if line . product_id . property_account_income . id :
2011-12-22 09:49:14 +00:00
income_account = line . product_id . property_account_income . id
elif line . product_id . categ_id . property_account_income_categ . id :
income_account = line . product_id . categ_id . property_account_income_categ . id
2008-08-24 14:45:43 +00:00
else :
2009-03-06 22:18:24 +00:00
raise osv . except_osv ( _ ( ' Error ! ' ) , _ ( ' There is no income ' \
' account defined for this product: " %s " (id: %d ) ' ) \
2008-08-24 14:45:43 +00:00
% ( line . product_id . name , line . product_id . id , ) )
# Empty the tax list as long as there is no tax code:
tax_code_id = False
tax_amount = 0
while computed_taxes :
tax = computed_taxes . pop ( 0 )
2012-06-01 15:44:29 +00:00
tax_code_id , tax_amount = compute_tax ( amount , tax , line )
2008-08-24 14:45:43 +00:00
# If there is one we stop
if tax_code_id :
break
# Create a move for the line
2012-06-01 15:44:29 +00:00
insert_data ( ' product ' , {
2012-05-04 12:51:58 +00:00
' name ' : line . product_id . name ,
2010-01-18 08:38:26 +00:00
' quantity ' : line . qty ,
2010-10-26 05:37:43 +00:00
' product_id ' : line . product_id . id ,
2008-08-24 14:45:43 +00:00
' account_id ' : income_account ,
' credit ' : ( ( amount > 0 ) and amount ) or 0.0 ,
' debit ' : ( ( amount < 0 ) and - amount ) or 0.0 ,
' tax_code_id ' : tax_code_id ,
' tax_amount ' : tax_amount ,
2010-11-22 09:50:07 +00:00
' partner_id ' : order . partner_id and order . partner_id . id or False
2012-06-01 15:44:29 +00:00
} )
2008-08-24 14:45:43 +00:00
# For each remaining tax with a code, whe create a move line
for tax in computed_taxes :
2012-06-01 15:44:29 +00:00
tax_code_id , tax_amount = compute_tax ( amount , tax , line )
2008-08-24 14:45:43 +00:00
if not tax_code_id :
continue
2012-06-01 15:44:29 +00:00
insert_data ( ' tax ' , {
2012-05-25 12:24:15 +00:00
' name ' : _ ( ' Tax ' ) ,
2010-01-18 08:38:26 +00:00
' product_id ' : line . product_id . id ,
' quantity ' : line . qty ,
2008-08-24 14:45:43 +00:00
' account_id ' : income_account ,
' credit ' : 0.0 ,
' debit ' : 0.0 ,
' tax_code_id ' : tax_code_id ,
' tax_amount ' : tax_amount ,
2012-06-01 15:44:29 +00:00
} )
2008-08-24 14:45:43 +00:00
# Create a move for each tax group
2012-05-25 12:24:15 +00:00
( tax_code_pos , base_code_pos , account_pos , tax_id ) = ( 0 , 1 , 2 , 3 )
2012-06-01 15:44:29 +00:00
for key , tax_amount in group_tax . items ( ) :
2012-05-25 12:24:15 +00:00
tax = self . pool . get ( ' account.tax ' ) . browse ( cr , uid , key [ tax_id ] , context = context )
2012-06-01 15:44:29 +00:00
insert_data ( ' tax ' , {
2012-05-25 12:24:15 +00:00
' name ' : _ ( ' Tax ' ) + ' ' + tax . name ,
2010-01-18 08:38:26 +00:00
' quantity ' : line . qty ,
2010-10-26 05:37:43 +00:00
' product_id ' : line . product_id . id ,
2008-08-24 14:45:43 +00:00
' account_id ' : key [ account_pos ] ,
2012-06-01 15:44:29 +00:00
' credit ' : ( ( tax_amount > 0 ) and tax_amount ) or 0.0 ,
' debit ' : ( ( tax_amount < 0 ) and - tax_amount ) or 0.0 ,
2008-08-24 14:45:43 +00:00
' tax_code_id ' : key [ tax_code_pos ] ,
2012-06-01 15:44:29 +00:00
' tax_amount ' : tax_amount ,
} )
2008-08-24 14:45:43 +00:00
# counterpart
2012-06-01 15:44:29 +00:00
insert_data ( ' counter_part ' , {
2012-05-10 07:48:04 +00:00
' name ' : _ ( " Trade Receivables " ) , #order.name,
2008-08-24 14:45:43 +00:00
' account_id ' : order_account ,
2012-06-01 15:44:29 +00:00
' credit ' : ( ( order . amount_total < 0 ) and - order . amount_total ) or 0.0 ,
' debit ' : ( ( order . amount_total > 0 ) and order . amount_total ) or 0.0 ,
2010-11-22 09:50:07 +00:00
' partner_id ' : order . partner_id and order . partner_id . id or False
2012-06-01 15:44:29 +00:00
} )
order . write ( { ' state ' : ' done ' , ' account_move ' : move_id } )
for group_key , group_data in grouped_data . iteritems ( ) :
for value in group_data :
account_move_line_obj . create ( cr , uid , value , context = context )
2012-05-04 12:51:58 +00:00
2008-08-24 14:45:43 +00:00
return True
2010-01-18 08:38:26 +00:00
def action_payment ( self , cr , uid , ids , context = None ) :
2011-09-25 14:09:30 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' payment ' } , context = context )
2010-01-18 08:38:26 +00:00
2008-08-24 14:45:43 +00:00
def action_paid ( self , cr , uid , ids , context = None ) :
2012-05-04 12:51:58 +00:00
self . create_picking ( cr , uid , ids , context = context )
2011-09-25 14:09:30 +00:00
self . write ( cr , uid , ids , { ' state ' : ' paid ' } , context = context )
2008-08-24 14:45:43 +00:00
return True
def action_cancel ( self , cr , uid , ids , context = None ) :
2010-10-26 05:37:43 +00:00
self . write ( cr , uid , ids , { ' state ' : ' cancel ' } , context = context )
2008-08-24 14:45:43 +00:00
return True
def action_done ( self , cr , uid , ids , context = None ) :
2011-09-25 14:09:30 +00:00
self . create_account_move ( cr , uid , ids , context = context )
2008-08-24 14:45:43 +00:00
return True
pos_order ( )
2010-04-23 14:57:42 +00:00
class account_bank_statement ( osv . osv ) :
_inherit = ' account.bank.statement '
2010-08-13 12:20:05 +00:00
_columns = {
2011-09-25 14:09:30 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' User ' , readonly = True ) ,
2010-04-23 14:57:42 +00:00
}
_defaults = {
2011-09-25 14:09:30 +00:00
' user_id ' : lambda self , cr , uid , c = { } : uid
2010-04-23 14:57:42 +00:00
}
account_bank_statement ( )
class account_bank_statement_line ( osv . osv ) :
_inherit = ' account.bank.statement.line '
2010-08-13 12:20:05 +00:00
_columns = {
2010-10-26 05:37:43 +00:00
' pos_statement_id ' : fields . many2one ( ' pos.order ' , ondelete = ' cascade ' ) ,
2010-04-23 14:57:42 +00:00
}
account_bank_statement_line ( )
2008-08-24 14:45:43 +00:00
class pos_order_line ( osv . osv ) :
_name = " pos.order.line "
_description = " Lines of Point of Sale "
2011-09-25 14:09:30 +00:00
_rec_name = " product_id "
2008-08-24 14:45:43 +00:00
2010-11-19 13:48:01 +00:00
def _amount_line_all ( self , cr , uid , ids , field_names , arg , context = None ) :
2010-09-27 14:40:24 +00:00
res = dict ( [ ( i , { } ) for i in ids ] )
account_tax_obj = self . pool . get ( ' account.tax ' )
2011-09-25 14:09:30 +00:00
cur_obj = self . pool . get ( ' res.currency ' )
2010-11-19 13:48:01 +00:00
for line in self . browse ( cr , uid , ids , context = context ) :
2011-09-25 14:09:30 +00:00
taxes = line . product_id . taxes_id
price = line . price_unit * ( 1 - ( line . discount or 0.0 ) / 100.0 )
taxes = account_tax_obj . compute_all ( cr , uid , line . product_id . taxes_id , price , line . qty , product = line . product_id , partner = line . order_id . partner_id or False )
2010-09-27 14:40:24 +00:00
2011-09-25 14:09:30 +00:00
cur = line . order_id . pricelist_id . currency_id
res [ line . id ] [ ' price_subtotal ' ] = cur_obj . round ( cr , uid , cur , taxes [ ' total ' ] )
res [ line . id ] [ ' price_subtotal_incl ' ] = cur_obj . round ( cr , uid , cur , taxes [ ' total_included ' ] )
return res
2010-09-29 09:57:42 +00:00
2011-09-25 14:09:30 +00:00
def onchange_product_id ( self , cr , uid , ids , pricelist , product_id , qty = 0 , partner_id = False , context = None ) :
context = context or { }
if not product_id :
return { }
if not pricelist :
raise osv . except_osv ( _ ( ' No Pricelist ! ' ) ,
_ ( ' You have to select a pricelist in the sale form ! \n ' \
' Please set one before choosing a product. ' ) )
price = self . pool . get ( ' product.pricelist ' ) . price_get ( cr , uid , [ pricelist ] ,
product_id , qty or 1.0 , partner_id ) [ pricelist ]
result = self . onchange_qty ( cr , uid , ids , product_id , 0.0 , qty , price , context = context )
result [ ' value ' ] [ ' price_unit ' ] = price
return result
def onchange_qty ( self , cr , uid , ids , product , discount , qty , price_unit , context = None ) :
result = { }
if not product :
return result
account_tax_obj = self . pool . get ( ' account.tax ' )
cur_obj = self . pool . get ( ' res.currency ' )
2010-09-29 09:57:42 +00:00
2011-09-25 14:09:30 +00:00
prod = self . pool . get ( ' product.product ' ) . browse ( cr , uid , product , context = context )
2010-09-27 14:21:50 +00:00
2011-09-25 14:09:30 +00:00
taxes = prod . taxes_id
price = price_unit * ( 1 - ( discount or 0.0 ) / 100.0 )
taxes = account_tax_obj . compute_all ( cr , uid , prod . taxes_id , price , qty , product = prod , partner = False )
2010-09-27 14:21:50 +00:00
2011-09-25 14:09:30 +00:00
result [ ' price_subtotal ' ] = taxes [ ' total ' ]
result [ ' price_subtotal_incl ' ] = taxes [ ' total_included ' ]
return { ' value ' : result }
2010-09-27 14:40:24 +00:00
2008-08-24 14:45:43 +00:00
_columns = {
2010-10-26 05:37:43 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' , required = True ) ,
2011-09-25 14:09:30 +00:00
' name ' : fields . char ( ' Line No ' , size = 32 , required = True ) ,
2011-09-25 15:50:50 +00:00
' notice ' : fields . char ( ' Discount Notice ' , size = 128 ) ,
2008-08-24 14:45:43 +00:00
' product_id ' : fields . many2one ( ' product.product ' , ' Product ' , domain = [ ( ' sale_ok ' , ' = ' , True ) ] , required = True , change_default = True ) ,
2011-09-25 14:09:30 +00:00
' price_unit ' : fields . float ( string = ' Unit Price ' , digits = ( 16 , 2 ) ) ,
' qty ' : fields . float ( ' Quantity ' , digits = ( 16 , 2 ) ) ,
' price_subtotal ' : fields . function ( _amount_line_all , multi = ' pos_order_line_amount ' , string = ' Subtotal w/o Tax ' , store = True ) ,
' price_subtotal_incl ' : fields . function ( _amount_line_all , multi = ' pos_order_line_amount ' , string = ' Subtotal ' , store = True ) ,
2008-08-24 14:45:43 +00:00
' discount ' : fields . float ( ' Discount ( % ) ' , digits = ( 16 , 2 ) ) ,
2010-01-18 08:38:26 +00:00
' order_id ' : fields . many2one ( ' pos.order ' , ' Order Ref ' , ondelete = ' cascade ' ) ,
2009-01-27 11:15:46 +00:00
' create_date ' : fields . datetime ( ' Creation Date ' , readonly = True ) ,
2010-08-13 12:20:05 +00:00
}
2008-08-24 14:45:43 +00:00
_defaults = {
' name ' : lambda obj , cr , uid , context : obj . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' pos.order.line ' ) ,
' qty ' : lambda * a : 1 ,
' discount ' : lambda * a : 0.0 ,
2010-01-18 08:38:26 +00:00
' company_id ' : lambda self , cr , uid , c : self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , c ) . company_id . id ,
2011-09-25 14:09:30 +00:00
}
2008-08-24 14:45:43 +00:00
2011-07-07 10:31:06 +00:00
def copy_data ( self , cr , uid , id , default = None , context = None ) :
if not default :
default = { }
default . update ( {
' name ' : self . pool . get ( ' ir.sequence ' ) . get ( cr , uid , ' pos.order.line ' )
} )
return super ( pos_order_line , self ) . copy_data ( cr , uid , id , default , context = context )
2008-08-24 14:45:43 +00:00
pos_order_line ( )
2011-07-18 16:17:46 +00:00
class pos_category ( osv . osv ) :
_name = ' pos.category '
2012-05-12 22:37:43 +00:00
_description = " Point of Sale Category "
2011-12-18 13:53:04 +00:00
_order = " sequence, name "
def _check_recursion ( self , cr , uid , ids , context = None ) :
level = 100
while len ( ids ) :
cr . execute ( ' select distinct parent_id from pos_category where id IN %s ' , ( tuple ( ids ) , ) )
ids = filter ( None , map ( lambda x : x [ 0 ] , cr . fetchall ( ) ) )
if not level :
return False
level - = 1
return True
_constraints = [
( _check_recursion , ' Error ! You cannot create recursive categories. ' , [ ' parent_id ' ] )
]
def name_get ( self , cr , uid , ids , context = None ) :
if not len ( ids ) :
return [ ]
reads = self . read ( cr , uid , ids , [ ' name ' , ' parent_id ' ] , context = context )
res = [ ]
for record in reads :
name = record [ ' name ' ]
if record [ ' parent_id ' ] :
name = record [ ' parent_id ' ] [ 1 ] + ' / ' + name
res . append ( ( record [ ' id ' ] , name ) )
return res
def _name_get_fnc ( self , cr , uid , ids , prop , unknow_none , context = None ) :
res = self . name_get ( cr , uid , ids , context = context )
return dict ( res )
2012-07-09 15:53:51 +00:00
def _get_small_image ( self , cr , uid , ids , prop , unknow_none , context = None ) :
result = { }
for obj in self . browse ( cr , uid , ids , context = context ) :
if not obj . category_image :
result [ obj . id ] = False
continue
image_stream = io . BytesIO ( obj . category_image . decode ( ' base64 ' ) )
img = Image . open ( image_stream )
img . thumbnail ( ( 120 , 100 ) , Image . ANTIALIAS )
img_stream = StringIO . StringIO ( )
img . save ( img_stream , " JPEG " )
result [ obj . id ] = img_stream . getvalue ( ) . encode ( ' base64 ' )
return result
2011-07-18 16:17:46 +00:00
_columns = {
2011-12-18 13:53:04 +00:00
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
' complete_name ' : fields . function ( _name_get_fnc , type = " char " , string = ' Name ' ) ,
2011-07-18 16:17:46 +00:00
' parent_id ' : fields . many2one ( ' pos.category ' , ' Parent Category ' , select = True ) ,
2011-12-18 13:53:04 +00:00
' child_id ' : fields . one2many ( ' pos.category ' , ' parent_id ' , string = ' Children Categories ' ) ,
' sequence ' : fields . integer ( ' Sequence ' , help = " Gives the sequence order when displaying a list of product categories. " ) ,
2012-07-09 15:53:51 +00:00
' category_image ' : fields . binary ( ' Image ' ) ,
' category_image_small ' : fields . function ( _get_small_image , string = ' Small Image ' , type = " binary " ,
2012-06-07 13:19:30 +00:00
store = {
2012-07-09 15:53:51 +00:00
' pos.category ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' category_image ' ] , 10 ) ,
} ) ,
2012-06-07 13:19:30 +00:00
}
2012-07-13 14:36:47 +00:00
def _get_default_image ( self , cr , uid , context = None ) :
image_path = openerp . modules . get_module_resource ( ' point_of_sale ' , ' images ' , ' default_category_photo.png ' )
return open ( image_path , ' rb ' ) . read ( ) . encode ( ' base64 ' )
_defaults = {
' category_image ' : _get_default_image ,
}
2011-07-18 16:17:46 +00:00
pos_category ( )
2012-02-09 14:23:55 +00:00
import io , StringIO
2010-01-18 08:38:26 +00:00
class product_product ( osv . osv ) :
_inherit = ' product.product '
2012-02-09 14:23:55 +00:00
def _get_small_image ( self , cr , uid , ids , prop , unknow_none , context = None ) :
result = { }
for obj in self . browse ( cr , uid , ids , context = context ) :
if not obj . product_image :
result [ obj . id ] = False
continue
image_stream = io . BytesIO ( obj . product_image . decode ( ' base64 ' ) )
img = Image . open ( image_stream )
img . thumbnail ( ( 120 , 100 ) , Image . ANTIALIAS )
img_stream = StringIO . StringIO ( )
img . save ( img_stream , " JPEG " )
result [ obj . id ] = img_stream . getvalue ( ) . encode ( ' base64 ' )
return result
2010-01-18 08:38:26 +00:00
_columns = {
2012-05-12 22:37:43 +00:00
' income_pdt ' : fields . boolean ( ' Point of Sale Cash In ' , help = " This is a product you can use to put cash into a statement for the point of sale backend. " ) ,
' expense_pdt ' : fields . boolean ( ' Point of Sale Cash Out ' , help = " This is a product you can use to take cash from a statement for the point of sale backend, exemple: money lost, transfer to bank, etc. " ) ,
' pos_categ_id ' : fields . many2one ( ' pos.category ' , ' Point of Sale Category ' ,
2012-02-09 14:23:55 +00:00
help = " If you want to sell this product through the point of sale, select the category it belongs to. " ) ,
' product_image_small ' : fields . function ( _get_small_image , string = ' Small Image ' , type = " binary " ,
store = {
' product.product ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' product_image ' ] , 10 ) ,
2012-05-29 12:15:56 +00:00
} ) ,
' to_weight ' : fields . boolean ( ' To Weight ' , help = " This category contains products that should be weighted, mainly used for the self-checkout interface " ) ,
2010-08-13 12:20:05 +00:00
}
2012-05-29 12:15:56 +00:00
_defaults = {
' to_weight ' : False ,
}
2010-01-18 08:38:26 +00:00
product_product ( )
2010-05-25 10:27:56 +00:00
2011-11-22 08:51:38 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: