diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index 111702c2e74..27707bcf0e0 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -75,6 +75,7 @@ Main features : 'statement_data.xml', ], 'demo_xml': ['pos_demo.xml','singer_statement_demo.xml','multi_company_stock_data.xml'], + 'test':['test/pos_test.yml',], 'installable': True, } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/point_of_sale/pos.py b/addons/point_of_sale/pos.py index ff1197aecac..7a8d64899fa 100644 --- a/addons/point_of_sale/pos.py +++ b/addons/point_of_sale/pos.py @@ -1088,13 +1088,14 @@ class pos_order_line(osv.osv): 'Please set one before choosing a product.')) p_obj = self.pool.get('product.product').browse(cr,uid,product_id).list_price price = self.pool.get('product.pricelist').price_get(cr, uid, - [pricelist], product_id, qty or 1.0, partner_id)[pricelist] - if price is False: - raise osv.except_osv(_('No valid pricelist line found !'), - _("Couldn't find a pricelist line matching this product" \ - " and quantity.\nYou have to change either the product," \ - " the quantity or the pricelist.")) - return price + [pricelist], product_id, qty or 1.0, partner_id)[pricelist] + # Todo need to check +# if price is False: +# raise osv.except_osv(_('No valid pricelist line found !'), +# _("Couldn't find a pricelist line matching this product" \ +# " and quantity.\nYou have to change either the product," \ +# " the quantity or the pricelist.")) + return price or p_obj def onchange_product_id(self, cr, uid, ids, pricelist, product_id, qty=0, partner_id=False): price = self.price_by_product(cr, uid, ids, pricelist, product_id, qty, partner_id) diff --git a/addons/point_of_sale/test/pos_test.yml b/addons/point_of_sale/test/pos_test.yml new file mode 100644 index 00000000000..42bcc515ca4 --- /dev/null +++ b/addons/point_of_sale/test/pos_test.yml @@ -0,0 +1,465 @@ +- + In order to test the POS in module, To gives business owners a convenient way of checking out customers and of recording sales. + +- + I configure all details for the customer,Salesman and Product ,Account. +- + Creating an account.account.type record +- + !record {model: account.account.type, id: account_account_type_view0}: + close_method: none + code: View + name: View + sign: 1 + + +- + Creating an account.account.type record +- + !record {model: account.account.type, id: account_account_type_income0}: + close_method: unreconciled + code: Income + name: Income + sign: 1 + + +- + Creating an account.account.type record +- + !record {model: account.account.type, id: account_account_type_expense0}: + close_method: unreconciled + code: Expense + name: Expense + sign: 1 + + +- + Creating an account.account.type record +- + !record {model: account.account.type, id: account_account_type_cash0}: + close_method: balance + code: Cash + name: Cash + sign: 1 + + +- + Creating an account.account record +- + !record {model: account.account, id: account_account_minimalchart0}: + code: '0' + company_id: base.main_company + currency_mode: current + name: Minimal Chart + parent_left: 1 + parent_right: 12 + type: view + user_type: account_account_type_view0 +- + Creating an account.account record +- + !record {model: account.account, id: account_account_payable1}: + code: AP + company_id: base.main_company + currency_mode: current + name: Payable + parent_id: account_account_minimalchart0 + parent_left: 2 + parent_right: 3 + reconcile: true + type: payable + user_type: account_account_type_expense0 + + +- + Creating an account.account record +- + !record {model: account.account, id: account_account_receivable0}: + code: AR + company_id: base.main_company + currency_mode: current + name: Receivable + parent_id: account_account_minimalchart0 + parent_left: 4 + parent_right: 5 + reconcile: true + type: receivable + user_type: account_account_type_income0 + + +- + Creating an account.account record +- + !record {model: account.account, id: account_account_cash0}: + code: C + company_id: base.main_company + currency_mode: current + name: Cash + parent_id: account_account_minimalchart0 + parent_left: 6 + parent_right: 7 + type: other + user_type: account_account_type_cash0 + + +- + Creating an account.account record +- + !record {model: account.account, id: account_account_purchases0}: + code: P + company_id: base.main_company + currency_mode: current + name: Purchases + parent_id: account_account_minimalchart0 + parent_left: 8 + parent_right: 9 + type: other + user_type: account_account_type_expense0 +- + Creating an account.account record +- + !record {model: account.account, id: account_account_sales0}: + code: S + company_id: base.main_company + currency_mode: current + name: Sales + parent_id: account_account_minimalchart0 + parent_left: 10 + parent_right: 11 + type: other + user_type: account_account_type_income0 + +- + Creating an account.journal record +- + !record {model: account.journal, id: account_journal_purchasejournal0}: + code: PUJ + company_id: base.main_company + default_credit_account_id: account_account_purchases0 + default_debit_account_id: account_account_purchases0 + name: Purchase Journal + sequence_id: account.sequence_purchase_journal + type: purchase + view_id: account.account_journal_view + + +- + Creating an account.journal record +- + !record {model: account.journal, id: account_journal_salejournal0}: + code: SAJ + company_id: base.main_company + default_credit_account_id: account_account_sales0 + default_debit_account_id: account_account_sales0 + name: Sale Journal + sequence_id: account.sequence_sale_journal + type: sale + view_id: account.account_journal_view + + +- + Creating an account.journal record +- + !record {model: account.journal, id: account_journal_bankjournal0}: + code: BNK + company_id: base.main_company + default_credit_account_id: account_account_cash0 + default_debit_account_id: account_account_cash0 + name: Bank Journal + sequence_id: account.sequence_journal + type: cash + view_id: account.account_journal_bank_view + + +- + Creating a ir.property record +- + !record {model: ir.property, id: ir_property_propertyaccountexpensecateg0}: + company_id: base.main_company + fields_id: account.field_res_partner_property_account_payable + name: property_account_expense_categ + value_reference: account.account,5 + + +- + Creating a ir.property record +- + !record {model: ir.property, id: ir_property_propertyaccountincomecateg0}: + company_id: base.main_company + fields_id: account.field_res_partner_property_account_receivable + name: property_account_income_categ + value_reference: account.account,6 +- + Creating a res.partner.category record +- + !record {model: res.partner.category, id: res_partner_category_customers0}: + name: Customers +- + Creating an res.partner record +- + !record {model: res.partner, id: res_partner_cleartrail0}: + category_id: + - res_partner_category_customers0 + name: Cleartrail + + +- + Creating an res.partner.address record +- + !record {model: res.partner.address, id: res_partner_address_1}: + partner_id: res_partner_cleartrail0 + street: onam plaza, 14 B palasia A B Road + type: contact + + +- + Creating an res.partner.address record +- + !record {model: res.partner.address, id: res_partner_address_2}: + partner_id: res_partner_cleartrail0 + type: invoice + + +- + Creating an res.partner.address record +- + !record {model: res.partner.address, id: res_partner_address_3}: + partner_id: res_partner_cleartrail0 + street: sangam house 15 B palasia, A B Road + type: delivery +- + Customer Cleartrail has specific instrument requirements regarding the stockable products +- + Creating an product.category record +- + !record {model: product.category, id: product_category_allproductssellable0}: + name: Mobile Products Sellable +- + Creating a res.partner record +- + !record {model: res.partner, id: res_partner_microlinktechnologies0}: + address: + - street: Kailash Vaibhav, Parksite + name: Micro Link Technologies + property_account_payable: account_account_payable1 + property_account_receivable: account_account_receivable0 + supplier: true + +- + Creating a res.partner.address record +- + !record {model: res.partner.address, id: res_partner_address_0}: + country_id: base.in + partner_id: res_partner_microlinktechnologies0 + street: Ash House, Ash Road + title: Ms. + + + +- + Creating an product.category record +- + !record {model: product.category, id: product_category_services0}: + name: Mobile Services +- + Creating an product.template record +- + !record {model: product.template, id: product_template_lgviewtysmart0}: + categ_id: product_category_allproductssellable0 + cost_method: standard + list_price: 170.0 + mes_type: fixed + name: LG Viewty Smart + procure_method: make_to_order + standard_price: 160.0 + supply_method: produce + type: product + uom_id: product.product_uom_unit + uom_po_id: product.product_uom_unit + +- + Creating an product.product record +- + !record {model: product.product, id: product_product_lgviewtysmart0}: + categ_id: product_category_allproductssellable0 + cost_method: standard + list_price: 170.0 + mes_type: fixed + name: LG Viewty Smart + pricelist_purchase: 'Default Purchase Pricelist (0.00) : 160.00\n' + pricelist_sale: 'Public Pricelist (0.00) : 170.00\n' + procure_method: make_to_order + property_account_expense: account_account_payable1 + property_account_income: account_account_receivable0 + seller_delay: '1' + standard_price: 160.0 + supply_method: produce + type: product + uom_id: product.product_uom_unit + uom_po_id: product.product_uom_unit +- + !record {model: product.category, id: product_category_computer0}: + name: Computer + +- + Creating a product.product record +- + !record {model: product.product, id: product_product_hppaviliondesktoppcs0}: + categ_id: product_category_computer0 + cost_method: standard + mes_type: fixed + list_price: 1000.0 + name: HP Pavilion Desktop PCs + procure_method: make_to_stock + seller_ids: + - delay: 1 + name: res_partner_microlinktechnologies0 + qty: 5.0 + supply_method: buy + type: product + uom_id: product.product_uom_unit + uom_po_id: product.product_uom_unit + property_account_expense: account_account_payable1 + property_account_income: account_account_receivable0 +- + Creating a pos.order record +- + !record {model: pos.order, id: pos_order_pos0}: + company_id: base.main_company + date_order: '2010-05-13 15:02:48' + date_validity: '2010-11-13' + lines: + - company_id: base.main_company + name: Order Line/01 + notice: No Discount + product_id: product_product_lgviewtysmart0 + qty: 10.0 + qty_rfd: 0.0 + name: POS/001 + price_type: tax_excluded + pricelist_id: product.list0 + sale_journal: account.sales_journal + shop_id: sale.shop + user_salesman_id: base.user_root +- + I have add discount +- + !record {model: pos.discount, id: pos_discount_0}: + discount: 5.0 + discount_notes: More then 5 product +- + Apply the discount +- + !python {model: pos.discount}: | + self.apply_discount(cr, uid, [ref("pos_discount_0")], {"lang": "en_US", "active_model": + "pos.order", "active_ids": [ref("pos_order_pos0")], "tz": False, "active_id": + ref("pos_order_pos0"), }) + +- + Creating a pos.open.statement record +- + !record {model: pos.open.statement, id: pos_open_statement_0}: + {} + +- + Performing an osv_memory action open_statement on module pos.open.statement +- + !python {model: pos.open.statement}: | + self.open_statement(cr, uid, [ref("pos_open_statement_0")], {"lang": "en_US", "active_model": + "ir.ui.menu", "active_ids": [ref("point_of_sale.menu_open_statement")], "tz": + False, "active_id": ref("point_of_sale.menu_open_statement"), }) + +- + Creating a pos.make.payment record +- + !record {model: pos.make.payment, id: pos_make_payment_0}: + amount: 1615.0 + journal: 5 + payment_date: 2010-05-13 + payment_name: Payment + product_id: product_product_hppaviliondesktoppcs0 + +- + For payment I click on Make Payment. +- + !python {model: pos.make.payment}: | + self.check(cr, uid, [ref("pos_make_payment_0")], {"lang": "en_US", "active_model": + "pos.order", "active_ids": [ref("point_of_sale.pos_order_pos0")], "tz": + False, "active_id": ref("point_of_sale.pos_order_pos0"), }) +- + I have check the Statement lines are created automatically when payment are done. +- + !python {model: pos.order}: | + order=self.browse(cr,uid,ref("pos_order_pos0")) + assert(order.statement_ids!=[]), "Statement lines not created" + +- + When i click on Return picking button , i get three option. +- + 1. Cancel 2.Return Goods and Exchange 3.Return without Refund +- + When i click on Return Goods and Exchange +- + Then allows me to define the quantity of products, which will return to the stock. +- + Creating a pos.return record +- + !record {model: pos.return, id: pos_return_0}: + {} +- + Performing an osv_memory action create_returns on module pos.return +- + !python {model: pos.return}: | + self.create_returns(cr, uid, [ref("pos_return_0")], {"lang": "en_US", "active_model": + "pos.order", "active_ids": [ref("point_of_sale.pos_order_pos0")], "tz": + False, "active_id": ref("point_of_sale.pos_order_pos0"), }) + + +- + Then allows me to define the quantity of products, which will return to the stock. +- + I have select the HP Pavilion Desktop PCs for exchange +- + !record {model: pos.add.product, id: pos_add_product_0}: + product_id: product_product_hppaviliondesktoppcs0 + quantity: 5.0 +- + I click on close on button. +- + !python {model: pos.add.product}: | + self.close_action(cr, uid, [ref("pos_add_product_0")], {"lang": "en_US", "active_model": + "pos.order", "active_ids": [ref("pos_order_pos0")], "tz": False, "active_id": ref("pos_order_pos0"), + }) + +- + Creating a pos.make.payment record +- + !record {model: pos.make.payment, id: pos_make_payment_1}: + amount: 680.0 + journal: '5' + payment_date: '2010-05-13' + payment_name: Payment + product_id: product_product_hppaviliondesktoppcs0 + +- + For payment I click on Make Payment. +- + !python {model: pos.make.payment}: | + self.check(cr, uid, [ref("pos_make_payment_1")], {"lang": "en_US", "active_model": + "pos.order", "active_ids": [ref("pos_order_pos0")], "tz": + False, "active_id": ref("pos_order_pos0"), }) + +- + Creating a pos.return record +- + !record {model: pos.return, id: pos_return_0}: + {} +- + To check the Return without Refund . I click button "Return without Refund ". +- + The quantity which are selected in Return lines wizard are refunded.. +- + !python {model: pos.return}: | + self.create_returns2(cr, uid, [ref("pos_return_0")], {"lang": "en_US", "active_model": + "pos.order", "active_ids": [ref("point_of_sale.pos_order_pos0")], "tz": + False, "active_id": ref("point_of_sale.pos_order_pos0"), }) diff --git a/addons/point_of_sale/wizard/pos_payment.py b/addons/point_of_sale/wizard/pos_payment.py index f59d814522c..b20d3db8b5e 100644 --- a/addons/point_of_sale/wizard/pos_payment.py +++ b/addons/point_of_sale/wizard/pos_payment.py @@ -44,48 +44,50 @@ class pos_make_payment(osv.osv_memory): """ res = super(pos_make_payment, self).default_get(cr, uid, fields, context=context) - active_id = context and context.get('active_id',False) - j_obj = self.pool.get('account.journal') - company_id = self.pool.get('res.users').browse(cr,uid,uid).company_id.id - journal = j_obj.search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', company_id)]) - - if journal: - journal = journal[0] - else: - journal = None - wf_service = netsvc.LocalService("workflow") - - order_obj=self.pool.get('pos.order') - order = order_obj.browse(cr, uid, active_id, context) - #get amount to pay - amount = order.amount_total - order.amount_paid - if amount <= 0.0: - context.update({'flag': True}) - order_obj.action_paid(cr, uid, [active_id], context) - elif order.amount_paid > 0.0: - order_obj.write(cr, uid, [active_id], {'state': 'advance'}) - invoice_wanted_checked = False - - current_date = time.strftime('%Y-%m-%d') + active_id = context and context.get('active_id',False) + if active_id: + j_obj = self.pool.get('account.journal') + company_id = self.pool.get('res.users').browse(cr,uid,uid).company_id.id + journal = j_obj.search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', company_id)]) - if 'journal' in fields: - res.update({'journal':journal}) - if 'amount' in fields: - res.update({'amount':amount}) - if 'invoice_wanted' in fields: - res.update({'invoice_wanted':invoice_wanted_checked}) - if 'payment_date' in fields: - res.update({'payment_date':current_date}) - if 'payment_name' in fields: - res.update({'payment_name':'Payment'}) + if journal: + journal = journal[0] + else: + journal = None + wf_service = netsvc.LocalService("workflow") + + order_obj=self.pool.get('pos.order') + order = order_obj.browse(cr, uid, active_id, context) + #get amount to pay + amount = order.amount_total - order.amount_paid + if amount <= 0.0: + context.update({'flag': True}) + order_obj.action_paid(cr, uid, [active_id], context) + elif order.amount_paid > 0.0: + order_obj.write(cr, uid, [active_id], {'state': 'advance'}) + invoice_wanted_checked = False + + current_date = time.strftime('%Y-%m-%d') + + if 'journal' in fields: + res.update({'journal':journal}) + if 'amount' in fields: + res.update({'amount':amount}) + if 'invoice_wanted' in fields: + res.update({'invoice_wanted':invoice_wanted_checked}) + if 'payment_date' in fields: + res.update({'payment_date':current_date}) + if 'payment_name' in fields: + res.update({'payment_name':'Payment'}) return res def view_init(self, cr, uid, fields_list, context=None): res = super(pos_make_payment, self).view_init(cr, uid, fields_list, context=context) active_id = context and context.get('active_id', False) or False - order = self.pool.get('pos.order').browse(cr, uid, active_id) - if not order.lines: - raise osv.except_osv('Error!','No order lines defined for this sale ') + if active_id: + order = self.pool.get('pos.order').browse(cr, uid, active_id) + if not order.lines: + raise osv.except_osv('Error!','No order lines defined for this sale ') return True def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): diff --git a/addons/point_of_sale/wizard/pos_return.py b/addons/point_of_sale/wizard/pos_return.py index 8d8669751ff..31d18ef09a5 100644 --- a/addons/point_of_sale/wizard/pos_return.py +++ b/addons/point_of_sale/wizard/pos_return.py @@ -167,10 +167,14 @@ class pos_return(osv.osv_memory): 'statement_ids':[], 'picking_id':[]}) for line in order_id.lines: - if line.id and (data['return%s' %line.id]!=0.0): + if line.id : + try: + qty= data['return%s' %line.id] + except : + qty= line.qty new_move=stock_move_obj.create(cr, uid,{ - 'product_qty': data['return%s' %line.id], - 'product_uos_qty': uom_obj._compute_qty(cr, uid,data['return%s' %line.id] ,line.product_id.uom_id.id), + 'product_qty': qty , + 'product_uos_qty': uom_obj._compute_qty(cr, uid,qty ,line.product_id.uom_id.id), 'picking_id':new_picking, 'product_uom':line.product_id.uom_id.id, 'location_id':location_id, @@ -179,7 +183,7 @@ class pos_return(osv.osv_memory): 'name':'%s (return)' %order_id.name, 'date':date_cur, 'date_planned':date_cur,}) - line_obj.copy(cr,uid,line.id,{'qty':-data['return%s' %line.id], + line_obj.copy(cr,uid,line.id,{'qty':-qty , 'order_id': new_order, }) order_obj.write(cr,uid, new_order, {'state':'done'})