def test_approval_and_forecasted_qty(self): """ When a PO is waiting for an approval, its quantities should be included in the draft quantity count """ self.env.company.po_double_validation = 'two_step' self.env.company.po_double_validation_amount = 0 basic_purchase_user = mail_new_test_user( self.env, login='******', groups='base.group_user,purchase.group_purchase_user', ) po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner with po_form.order_line.new() as line: line.product_id = self.product line.product_qty = 50 po_form.save() po_form = Form(self.env['purchase.order']) po_form.partner_id = self.partner with po_form.order_line.new() as line: line.product_id = self.product line.product_qty = 100 po = po_form.save() po.with_user(basic_purchase_user).button_confirm() docs = self.get_report_forecast(product_template_ids=self.product_template.ids)[1] self.assertEqual(docs['draft_purchase_qty'], 150)
def test_mail_composer_wtpl_recipients(self): """ Test various combinations of recipients: active_domain, active_id, active_ids, ... to ensure fallback behavior are working. """ # 1: active_domain composer_form = Form(self.env['mail.compose.message'].with_context( self._get_web_context(self.test_records, add_web=True, default_template_id=self.template.id, active_ids=[], default_use_active_domain=True, default_active_domain=[('id', 'in', self.test_records.ids)]) )) composer = composer_form.save() with self.mock_mail_gateway(mail_unlink_sent=True): composer.send_mail() # global outgoing self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record') self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record') for record in self.test_records: # template is sent directly using customer field self.assertSentEmail(self.partner_employee, record.customer_id) # 2: active_domain not taken into account if use_active_domain is False composer_form = Form(self.env['mail.compose.message'].with_context( self._get_web_context(self.test_records, add_web=True, default_template_id=self.template.id, default_use_active_domain=False, default_active_domain=[('id', 'in', -1)]) )) composer = composer_form.save() with self.mock_mail_gateway(mail_unlink_sent=True): composer.send_mail() # global outgoing self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record') self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record') # 3: fallback on active_id if not active_ids composer_form = Form(self.env['mail.compose.message'].with_context( self._get_web_context(self.test_records, add_web=True, default_template_id=self.template.id, active_ids=[]) )) composer = composer_form.save() with self.mock_mail_gateway(mail_unlink_sent=False): composer.send_mail() # global outgoing self.assertEqual(len(self._new_mails), 1, 'Should have created 1 mail.mail per record') self.assertEqual(len(self._mails), 1, 'Should have sent 1 email per record') # 3: void is void composer_form = Form(self.env['mail.compose.message'].with_context( default_model='mail.test.ticket', default_template_id=self.template.id )) composer = composer_form.save() with self.mock_mail_gateway(mail_unlink_sent=False), self.assertRaises(ValueError): composer.send_mail()
def test_o2m_remove(self): def commands(): return [c[0] for c in f._values['line_ids']] f = Form(self.env['test_testing_utilities.onchange_count']) self.assertEqual(f.count, 0) self.assertEqual(len(f.line_ids), 0) f.count = 5 self.assertEqual(f.count, 5) self.assertEqual(len(f.line_ids), 5) f.count = 2 self.assertEqual(f.count, 2) self.assertEqual(len(f.line_ids), 2) f.count = 4 r = f.save() previous = r.line_ids self.assertEqual(len(previous), 4) with Form(r) as f: f.count = 2 self.assertEqual(commands(), [0, 0, 2, 2, 2, 2], "Should contain 2 creations and 4 deletions") self.assertEqual(len(r.line_ids), 2) with Form(r) as f: f.line_ids.remove(0) self.assertEqual(commands(), [2, 1]) f.count = 1 self.assertEqual(commands(), [0, 2, 2], "should contain 1 '0' command and 2 deletions") self.assertEqual(len(r.line_ids), 1)
def test_2weeks_calendar(self): self.env.user.tz = 'Europe/Brussels' calendar = self.env['resource.calendar'].create({ 'name': 'auto next day', 'two_weeks_calendar': True, 'attendance_ids': [(5, 0, 0), (0, 0, { 'name': 'monday morning odd week', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning', 'dayofweek': '0', 'week_type': '0', }), (0, 0, { 'name': 'monday morning even week', 'hour_from': 10, 'hour_to': 12, 'day_period': 'morning', 'dayofweek': '0', 'week_type': '1', })] }) employee = self.employee_emp employee.resource_calendar_id = calendar with Form(self.env['hr.leave'].with_context( default_employee_id=employee.id)) as leave_form: leave_form.holiday_status_id = self.leave_type # even week, works 2 hours leave_form.request_date_from = date(2019, 9, 2) leave_form.request_date_to = date(2019, 9, 2) leave_form.request_unit_half = True leave_form.request_date_from_period = 'am' self.assertEqual(leave_form.number_of_days_display, 0.5) self.assertEqual(leave_form.number_of_hours_text, '2 Hours') self.assertEqual(leave_form.date_from, datetime(2019, 9, 2, 8, 0, 0)) self.assertEqual(leave_form.date_to, datetime(2019, 9, 2, 10, 0, 0)) with Form(self.env['hr.leave'].with_context( default_employee_id=employee.id)) as leave_form: leave_form.holiday_status_id = self.leave_type # odd week, works 4 hours leave_form.request_date_from = date(2019, 9, 9) leave_form.request_date_to = date(2019, 9, 9) leave_form.request_unit_half = True leave_form.request_date_from_period = 'am' self.assertEqual(leave_form.number_of_days_display, 0.5) self.assertEqual(leave_form.number_of_hours_text, '4 Hours') self.assertEqual(leave_form.date_from, datetime(2019, 9, 9, 6, 0, 0)) self.assertEqual(leave_form.date_to, datetime(2019, 9, 9, 10, 0, 0))
def test_journal_sequence(self): self.assertEqual(self.test_move.name, 'MISC/2016/01/0001') self.test_move.action_post() self.assertEqual(self.test_move.name, 'MISC/2016/01/0001') copy1 = self.create_move(date=self.test_move.date) self.assertEqual(copy1.name, '/') copy1.action_post() self.assertEqual(copy1.name, 'MISC/2016/01/0002') copy2 = self.create_move(date=self.test_move.date) new_journal = self.test_move.journal_id.copy() new_journal.code = "MISC2" copy2.journal_id = new_journal self.assertEqual(copy2.name, 'MISC2/2016/01/0001') with Form(copy2) as move_form: # It is editable in the form with mute_logger('flectra.tests.common.onchange'): move_form.name = 'MyMISC/2016/0001' self.assertIn( 'The sequence will restart at 1 at the start of every year', move_form._perform_onchange(['name' ])['warning']['message'], ) move_form.journal_id = self.test_move.journal_id self.assertEqual(move_form.name, '/') move_form.journal_id = new_journal self.assertEqual(move_form.name, 'MISC2/2016/01/0001') with mute_logger('flectra.tests.common.onchange'): move_form.name = 'MyMISC/2016/0001' self.assertIn( 'The sequence will restart at 1 at the start of every year', move_form._perform_onchange(['name' ])['warning']['message'], ) copy2.action_post() self.assertEqual(copy2.name, 'MyMISC/2016/0001') copy3 = self.create_move(date=copy2.date, journal=new_journal) self.assertEqual(copy3.name, '/') with self.assertRaises(AssertionError): with Form(copy2) as move_form: # It is not editable in the form move_form.name = 'MyMISC/2016/0002' copy3.action_post() self.assertEqual(copy3.name, 'MyMISC/2016/0002') copy3.name = 'MISC2/2016/00002' copy4 = self.create_move(date=copy2.date, journal=new_journal) copy4.action_post() self.assertEqual(copy4.name, 'MISC2/2016/00003') copy5 = self.create_move(date=copy2.date, journal=new_journal) copy5.date = '2021-02-02' copy5.action_post() self.assertEqual(copy5.name, 'MISC2/2021/00001') copy5.name = 'N\'importe quoi?' copy6 = self.create_move(date=copy5.date, journal=new_journal) copy6.action_post() self.assertEqual(copy6.name, 'N\'importe quoi?1')
def test_required_bool(self): f = Form(self.env['test_testing_utilities.req_bool']) f.f_bool = False r = f.save() self.assertEqual(r.f_bool, 0) f2 = Form(self.env['test_testing_utilities.req_bool']) r2 = f2.save() self.assertEqual(r2.f_bool, 0)
def test_crm_lead_partner_sync_email_phone_corner_cases(self): """ Test corner cases of email and phone sync (False versus '', formatting differences, wrong input, ...) """ test_email = '*****@*****.**' lead = self.lead_1.with_user(self.env.user) contact = self.env['res.partner'].create({ 'name': 'NoContact Partner', 'phone': '', 'email': '', 'mobile': '', }) lead_form = Form(lead) self.assertEqual(lead_form.email_from, test_email) self.assertFalse(lead_form.ribbon_message) # email: False versus empty string lead_form.partner_id = contact self.assertIn('the customer email', lead_form.ribbon_message) lead_form.email_from = '' self.assertFalse(lead_form.ribbon_message) lead_form.email_from = False self.assertFalse(lead_form.ribbon_message) # phone: False versus empty string lead_form.phone = '+1 202-555-0888' self.assertIn('the customer phone', lead_form.ribbon_message) lead_form.phone = '' self.assertFalse(lead_form.ribbon_message) lead_form.phone = False self.assertFalse(lead_form.ribbon_message) # email/phone: formatting should not trigger ribbon lead.write({ 'email_from': '"My Name" <%s>' % test_email, 'phone': '+1 202-555-0888', }) contact.write({ 'email': '"My Name" <%s>' % test_email, 'phone': '+1 202-555-0888', }) lead_form = Form(lead) self.assertFalse(lead_form.ribbon_message) lead_form.partner_id = contact self.assertFalse(lead_form.ribbon_message) lead_form.email_from = '"Another Name" <%s>' % test_email # same email normalized self.assertFalse(lead_form.ribbon_message, 'Formatting-only change should not trigger write') lead_form.phone = '2025550888' # same number but another format self.assertFalse(lead_form.ribbon_message, 'Formatting-only change should not trigger write') # wrong value are also propagated lead_form.phone = '666 789456789456789456' self.assertIn('the customer phone', lead_form.ribbon_message)
def test_generate_with_putaway(self): """ Checks the `location_dest_id` of generated move lines is correclty set in fonction of defined putaway rules. """ nbre_of_lines = 4 shelf_location = self.env['stock.location'].create({ 'name': 'shelf1', 'usage': 'internal', 'location_id': self.location_dest.id, }) # Checks a first time without putaway... move = self.get_new_move(nbre_of_lines) form_wizard = Form(self.env['stock.assign.serial'].with_context( default_move_id=move.id, )) form_wizard.next_serial_count = nbre_of_lines form_wizard.next_serial_number = '001' wiz = form_wizard.save() wiz.generate_serial_numbers() for move_line in move.move_line_nosuggest_ids: self.assertEqual(move_line.qty_done, 1) # The location dest must be the default one. self.assertEqual(move_line.location_dest_id.id, self.location_dest.id) # We need to activate multi-locations to use putaway rules. grp_multi_loc = self.env.ref('stock.group_stock_multi_locations') self.env.user.write({'groups_id': [(4, grp_multi_loc.id)]}) # Creates a putaway rule putaway_product = self.env['stock.putaway.rule'].create({ 'product_id': self.product_serial.id, 'location_in_id': self.location_dest.id, 'location_out_id': shelf_location.id, }) # Checks now with putaway... move = self.get_new_move(nbre_of_lines) form_wizard = Form(self.env['stock.assign.serial'].with_context( default_move_id=move.id, )) form_wizard.next_serial_count = nbre_of_lines form_wizard.next_serial_number = '001' wiz = form_wizard.save() wiz.generate_serial_numbers() for move_line in move.move_line_nosuggest_ids: self.assertEqual(move_line.qty_done, 1) # The location dest must be now the one from the putaway. self.assertEqual(move_line.location_dest_id.id, shelf_location.id)
def test_invoice_shipment(self): """ Tests the case into which we make the invoice first, and then receive the goods. """ # Create a PO and an invoice for it test_product = self.test_product_order purchase_order = self._create_purchase(test_product, '2017-12-01') invoice = self._create_invoice_for_po(purchase_order, '2017-12-23') move_form = Form(invoice) with move_form.invoice_line_ids.edit(0) as line_form: line_form.quantity = 1 invoice = move_form.save() # Validate the invoice and refund the goods invoice.action_post() self._process_pickings(purchase_order.picking_ids, date='2017-12-24') picking = self.env['stock.picking'].search([('purchase_id', '=', purchase_order.id)]) self.check_reconciliation(invoice, picking) # Return the goods and refund the invoice stock_return_picking_form = Form( self.env['stock.return.picking'].with_context( active_ids=picking.ids, active_id=picking.ids[0], active_model='stock.picking')) stock_return_picking = stock_return_picking_form.save() stock_return_picking.product_return_moves.quantity = 1.0 stock_return_picking_action = stock_return_picking.create_returns() return_pick = self.env['stock.picking'].browse( stock_return_picking_action['res_id']) return_pick.action_assign() return_pick.move_lines.quantity_done = 1 return_pick._action_done() self._change_pickings_date(return_pick, '2018-01-13') # Refund the invoice refund_invoice_wiz = self.env['account.move.reversal'].with_context( active_model="account.move", active_ids=[invoice.id]).create({ 'reason': 'test_invoice_shipment_refund', 'refund_method': 'cancel', 'date': '2018-03-15', }) refund_invoice = self.env['account.move'].browse( refund_invoice_wiz.reverse_moves()['res_id']) # Check the result self.assertEqual(invoice.payment_state, 'reversed', "Invoice should be in 'reversed' state") self.assertEqual(refund_invoice.payment_state, 'paid', "Refund should be in 'paid' state") self.check_reconciliation(refund_invoice, return_pick)
def test_03_onchange_expiration_date(self): """ Updates the `expiration_date` of the lot production and checks other date fields are updated as well. """ # Keeps track of the current datetime and set a delta for the compares. today_date = datetime.today() time_gap = timedelta(seconds=10) # Creates a new lot number and saves it... lot_form = Form(self.LotObj) lot_form.name = 'Apple Box #1' lot_form.product_id = self.apple_product lot_form.company_id = self.env.company apple_lot = lot_form.save() # ...then checks date fields have the expected values. self.assertAlmostEqual( today_date + timedelta(days=self.apple_product.expiration_time), apple_lot.expiration_date, delta=time_gap) self.assertAlmostEqual(today_date + timedelta(days=self.apple_product.use_time), apple_lot.use_date, delta=time_gap) self.assertAlmostEqual(today_date + timedelta(days=self.apple_product.removal_time), apple_lot.removal_date, delta=time_gap) self.assertAlmostEqual(today_date + timedelta(days=self.apple_product.alert_time), apple_lot.alert_date, delta=time_gap) difference = timedelta(days=20) new_date = apple_lot.expiration_date + difference old_use_date = apple_lot.use_date old_removal_date = apple_lot.removal_date old_alert_date = apple_lot.alert_date # Modifies the lot `expiration_date`... lot_form = Form(apple_lot) lot_form.expiration_date = new_date apple_lot = lot_form.save() # ...then checks all other date fields were correclty updated. self.assertAlmostEqual(apple_lot.use_date, old_use_date + difference, delta=time_gap) self.assertAlmostEqual(apple_lot.removal_date, old_removal_date + difference, delta=time_gap) self.assertAlmostEqual(apple_lot.alert_date, old_alert_date + difference, delta=time_gap)
def test_04_expiration_date_on_receipt(self): """ Test we can set an expiration date on receipt and all expiration date will be correctly set. """ partner = self.env['res.partner'].create({ 'name': 'Apple\'s Joe', 'company_id': self.env.ref('base.main_company').id, }) expiration_date = datetime.today() + timedelta(days=30) time_gap = timedelta(seconds=10) # Receives a tracked production using expiration date. picking_form = Form(self.env['stock.picking']) picking_form.partner_id = partner picking_form.picking_type_id = self.env.ref('stock.picking_type_in') with picking_form.move_ids_without_package.new() as move: move.product_id = self.apple_product move.product_uom_qty = 4 receipt = picking_form.save() receipt.action_confirm() # Defines a date during the receipt. move_form = Form(receipt.move_ids_without_package, view="stock.view_stock_move_operations") with move_form.move_line_ids.new() as line: line.lot_name = 'Apple Box #2' line.expiration_date = expiration_date line.qty_done = 4 move = move_form.save() receipt._action_done() # Get back the lot created when the picking was done... apple_lot = self.env['stock.production.lot'].search( [('product_id', '=', self.apple_product.id)], limit=1, ) # ... and checks all date fields are correctly set. self.assertAlmostEqual(apple_lot.expiration_date, expiration_date, delta=time_gap) self.assertAlmostEqual(apple_lot.use_date, expiration_date - timedelta(days=5), delta=time_gap) self.assertAlmostEqual(apple_lot.removal_date, expiration_date - timedelta(days=2), delta=time_gap) self.assertAlmostEqual(apple_lot.alert_date, expiration_date - timedelta(days=6), delta=time_gap)
def test_move_task(self): with self.sudo('employee-a'): with self.allow_companies([self.company_a.id, self.company_b.id]): with Form(self.task_1) as task_form: task_form.project_id = self.project_company_b task = task_form.save() self.assertEqual(task.company_id, self.company_b, "The company of the task should be the one from its project.") with Form(self.task_1) as task_form: task_form.project_id = self.project_company_a task = task_form.save() self.assertEqual(task.company_id, self.company_a, "Moving a task should change its company.")
def test_report_forecast_1_sale_order_replenishment(self): """ Create and confirm two sale orders: one for the next week and one for tomorrow. Then check in the report it's the most urgent who is linked to the qty. on stock. """ today = datetime.today() # Put some quantity in stock. quant_vals = { 'product_id': self.product.id, 'product_uom_id': self.product.uom_id.id, 'location_id': self.stock_location.id, 'quantity': 5, 'reserved_quantity': 0, } self.env['stock.quant'].create(quant_vals) # Create a first SO for the next week. so_form = Form(self.env['sale.order']) so_form.partner_id = self.partner # so_form.validity_date = today + timedelta(days=7) with so_form.order_line.new() as so_line: so_line.product_id = self.product so_line.product_uom_qty = 5 so_1 = so_form.save() so_1.action_confirm() so_1.picking_ids.scheduled_date = today + timedelta(days=7) # Create a second SO for tomorrow. so_form = Form(self.env['sale.order']) so_form.partner_id = self.partner # so_form.validity_date = today + timedelta(days=1) with so_form.order_line.new() as so_line: so_line.product_id = self.product so_line.product_uom_qty = 5 so_2 = so_form.save() so_2.action_confirm() so_2.picking_ids.scheduled_date = today + timedelta(days=1) report_values, docs, lines = self.get_report_forecast( product_template_ids=self.product_template.ids) self.assertEqual(len(lines), 2) line_1 = lines[0] line_2 = lines[1] self.assertEqual(line_1['quantity'], 5) self.assertTrue(line_1['replenishment_filled']) self.assertEqual(line_1['document_out'].id, so_2.id) self.assertEqual(line_2['quantity'], 5) self.assertEqual(line_2['replenishment_filled'], False) self.assertEqual(line_2['document_out'].id, so_1.id)
def test_mail_composer_wtpl_delete(self): self.template.auto_delete = True composer_form = Form(self.env['mail.compose.message'].with_context( self._get_web_context(self.test_records, add_web=True, default_template_id=self.template.id) )) composer = composer_form.save() with self.mock_mail_gateway(mail_unlink_sent=True): composer.send_mail() # global outgoing self.assertEqual(len(self._new_mails), 2, 'Should have created 1 mail.mail per record') self.assertEqual(len(self._mails), 2, 'Should have sent 1 email per record') self.assertEqual(self._new_mails.exists(), self.env['mail.mail'], 'Should have deleted mail.mail records') for record in self.test_records: # message copy is kept message = record.message_ids[0] # template is sent directly using customer field self.assertSentEmail(self.partner_employee, record.customer_id) # message content self.assertEqual(message.subject, 'TemplateSubject %s' % record.name) self.assertEqual(message.body, '<p>TemplateBody %s</p>' % record.name) self.assertEqual(message.author_id, self.user_employee.partner_id) # post-related fields are void self.assertEqual(message.subtype_id, self.env['mail.message.subtype']) self.assertEqual(message.partner_ids, self.env['res.partner'])
def test_remove(self): """ onchanges can remove o2m records which haven't been loaded yet due to lazy loading of o2ms. The removal information should still be retained, otherwise due to the stateful update system we end up retaining records we don't even know exist. """ # create structure with sub-sub-children r = self.env['o2m_changes_parent'].create({ 'name': "A", 'line_ids': [ (0, 0, { 'name': 'line 1', 'v': 42, 'line_ids': [(0, 0, {'v': 1, 'vv': 1})], }) ] }) with Form(r) as f: f.name = 'B' self.assertEqual(len(r.line_ids), 1) self.assertEqual(len(r.line_ids.line_ids), 1) self.assertEqual(r.line_ids.line_ids.v, 0) self.assertEqual(r.line_ids.line_ids.vv, 0)
def test_set_multiple_lot_name_01(self): """ Sets five SN in one time in stock move view form, then checks move has five new move lines with the right `lot_name`. """ nbre_of_lines = 10 picking_type = self.env['stock.picking.type'].search([ ('use_create_lots', '=', True), ('warehouse_id', '=', self.warehouse.id) ]) move = self.get_new_move(nbre_of_lines) move.picking_type_id = picking_type # We must begin with a move with 10 move lines. self.assertEqual(len(move.move_line_ids), nbre_of_lines) value_list = [ 'abc-235', 'abc-237', 'abc-238', 'abc-282', 'abc-301', ] values = '\n'.join(value_list) move_form = Form(move, view='stock.view_stock_move_nosuggest_operations') with move_form.move_line_nosuggest_ids.new() as line: line.lot_name = values move = move_form.save() # After we set multiple SN, we must have now 15 move lines. self.assertEqual(len(move.move_line_ids), nbre_of_lines + len(value_list)) # Then we look each SN name is correct. for move_line in move.move_line_nosuggest_ids: self.assertEqual(move_line.lot_name, value_list.pop(0)) for move_line in (move.move_line_ids - move.move_line_nosuggest_ids): self.assertEqual(move_line.lot_name, False)
def test_generate_01_sn(self): """ Creates a move with 5 move lines, then asks for generates 5 Serial Numbers. Checks move has 5 new move lines with each a SN, and the 5 original move lines are still unchanged. """ nbre_of_lines = 5 move = self.get_new_move(nbre_of_lines) form_wizard = Form(self.env['stock.assign.serial'].with_context( default_move_id=move.id, default_next_serial_number='001', default_next_serial_count=nbre_of_lines, )) wiz = form_wizard.save() self.assertEqual(len(move.move_line_ids), nbre_of_lines) wiz.generate_serial_numbers() # Checks new move lines have the right SN generated_numbers = ['001', '002', '003', '004', '005'] self.assertEqual(len(move.move_line_ids), nbre_of_lines + len(generated_numbers)) for move_line in move.move_line_nosuggest_ids: # For a product tracked by SN, the `qty_done` is set on 1 when # `lot_name` is set. self.assertEqual(move_line.qty_done, 1) self.assertEqual(move_line.lot_name, generated_numbers.pop(0)) # Checks pre-generated move lines didn't change for move_line in (move.move_line_ids - move.move_line_nosuggest_ids): self.assertEqual(move_line.qty_done, 0) self.assertEqual(move_line.lot_name, False)
def test_edit_removal_date_in_inventory_mode(self): """ Try to edit removal_date with the inventory mode. """ user_group_stock_manager = self.env.ref('stock.group_stock_manager') self.demo_user = mail_new_test_user( self.env, name='Demo user', login='******', email='*****@*****.**', groups='stock.group_stock_manager', ) lot_form = Form(self.LotObj) lot_form.name = 'LOT001' lot_form.product_id = self.apple_product lot_form.company_id = self.env.company apple_lot = lot_form.save() quant = self.StockQuantObj.with_context(inventory_mode=True).create({ 'product_id': self.apple_product.id, 'location_id': self.stock_location, 'quantity': 10, 'lot_id': apple_lot.id, }) # Try to write on quant with inventory mode new_date = datetime.today() + timedelta(days=15) quant.with_user(self.demo_user).with_context( inventory_mode=True).write({'removal_date': new_date}) self.assertEqual(quant.removal_date, new_date)
def test_m2o(self): Sub = self.env['test_testing_utilities.m2o'] a = Sub.create({'name': 'a'}) b = Sub.create({'name': 'b'}) c = Sub.create({'name': 'c'}) r = self.env['test_testing_utilities.d'].create({ 'f': c.id, 'f2': "OK", }) with Form(r) as f: # no default/onchange should have run so loading an incoherent # record should still be incoherent self.assertEqual(f.f, c) self.assertEqual(f.f2, 'OK') f.f2 = "b" self.assertEqual(f.f, b) f.f2 = "Whoops" self.assertEqual(f.f, Sub) f.f2 = "a" self.assertEqual(f.f, a) self.assertEqual(r.f2, "a") self.assertEqual(r.f, a)
def test_supplier_lead_time(self): """ Basic stock configuration and a supplier with a minimum qty and a lead time """ self.env['stock.warehouse.orderpoint'].search([]).unlink() orderpoint_form = Form(self.env['stock.warehouse.orderpoint']) orderpoint_form.product_id = self.product_1 orderpoint_form.product_min_qty = 10 orderpoint_form.product_max_qty = 50 orderpoint = orderpoint_form.save() self.env['product.supplierinfo'].search([ ('product_tmpl_id', '=', self.product_1.product_tmpl_id.id) ]).unlink() self.env['product.supplierinfo'].create({ 'name': self.partner_1.id, 'min_qty': 1, 'price': 1, 'delay': 7, 'product_tmpl_id': self.product_1.product_tmpl_id.id, }) self.env['procurement.group'].run_scheduler() purchase_order = self.env['purchase.order'].search([ ('partner_id', '=', self.partner_1.id) ]) today = fields.Datetime.start_of(fields.Datetime.now(), 'day') self.assertEqual(purchase_order.date_order, today) self.assertEqual( fields.Datetime.start_of(purchase_order.date_planned, 'day'), today + timedelta(days=7))
def test_recurrence_simple(self): with freeze_time("2020-02-01"): with Form(self.env['project.task']) as form: form.name = 'test recurring task' form.project_id = self.project_recurring form.recurring_task = True form.repeat_interval = 5 form.repeat_unit = 'month' form.repeat_type = 'after' form.repeat_number = 10 form.repeat_on_month = 'date' form.repeat_day = '31' task = form.save() self.assertTrue(bool(task.recurrence_id), 'should create a recurrence') task.write(dict(repeat_interval=2, repeat_number=11)) self.assertEqual(task.recurrence_id.repeat_interval, 2, 'recurrence should be updated') self.assertEqual(task.recurrence_id.repeat_number, 11, 'recurrence should be updated') self.assertEqual(task.recurrence_id.recurrence_left, 11) self.assertEqual(task.recurrence_id.next_recurrence_date, date(2020, 2, 29)) task.recurring_task = False self.assertFalse(bool(task.recurrence_id), 'the recurrence should be deleted')
def test_product_price_decimal_accuracy(self): self.env['ir.model.data'].xmlid_to_object( 'product.decimal_price').digits = 3 self.env.company.currency_id.rounding = 0.01 po = self.env['purchase.order'].with_context( tracking_disable=True).create({ 'partner_id': self.partner_a.id, 'order_line': [(0, 0, { 'name': self.product_a.name, 'product_id': self.product_a.id, 'product_qty': 12, 'product_uom': self.product_a.uom_id.id, 'price_unit': 0.001, 'taxes_id': False, })] }) po.button_confirm() po.order_line.qty_received = 12 move_form = Form(self.env['account.move'].with_context( default_move_type='in_invoice')) move_form.purchase_vendor_bill_id = self.env[ 'purchase.bill.union'].browse(-po.id) move = move_form.save() self.assertEqual(move.amount_total, 0.01)
def new_partner_bank_form(self): form = Form( self.env['res.partner.bank'], view="l10n_ch.isr_partner_bank_form", ) form.partner_id = self.partner return form
def test_attendance_previous_day(self): self.env.user.tz = 'Europe/Brussels' calendar = self.env['resource.calendar'].create({ 'name': 'auto next day', 'attendance_ids': [(5, 0, 0), (0, 0, { 'name': 'monday morning', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning', 'dayofweek': '0', })] }) employee = self.employee_emp employee.resource_calendar_id = calendar with Form(self.env['hr.leave'].with_context(default_employee_id=employee.id)) as leave_form: leave_form.holiday_status_id = self.leave_type leave_form.request_date_from = date(2019, 9, 3) leave_form.request_date_to = date(2019, 9, 3) leave_form.request_unit_half = True leave_form.request_date_from_period = 'am' self.assertEqual(leave_form.number_of_days_display, 0) self.assertEqual(leave_form.number_of_hours_text, '0 Hours') self.assertEqual(leave_form.date_from, datetime(2019, 9, 3, 6, 0, 0)) self.assertEqual(leave_form.date_to, datetime(2019, 9, 3, 10, 0, 0))
def _create_invoice(self, data=None, invoice_type='out_invoice'): data = data or {} with Form(self.env['account.move'].with_context( default_move_type=invoice_type)) as invoice_form: invoice_form.partner_id = data.get('partner', self.partner) if 'in_' not in invoice_type: invoice_form.journal_id = data.get('journal', self.journal) if data.get('document_type'): invoice_form.l10n_latam_document_type_id = data.get( 'document_type') if data.get('document_number'): invoice_form.l10n_latam_document_number = data.get( 'document_number') if data.get('incoterm'): invoice_form.invoice_incoterm_id = data.get('incoterm') if data.get('currency'): invoice_form.currency_id = data.get('currency') for line in data.get('lines', [{}]): with invoice_form.invoice_line_ids.new() as invoice_line_form: if line.get('display_type'): invoice_line_form.display_type = line.get( 'display_type') invoice_line_form.name = line.get( 'name', 'not invoice line') else: invoice_line_form.product_id = line.get( 'product', self.product_iva_21) invoice_line_form.quantity = line.get('quantity', 1) invoice_line_form.price_unit = line.get( 'price_unit', 100) invoice_form.invoice_date = invoice_form.date invoice = invoice_form.save() return invoice
def test_fifo_perpetual_01_mc_01(self): self.product_A.categ_id.property_cost_method = "fifo" rate = self.currency_data["rates"].sorted()[0].rate move_form = Form(self.env["account.move"].with_context( default_move_type="out_invoice")) move_form.partner_id = self.partner_a move_form.currency_id = self.currency_data["currency"] with move_form.invoice_line_ids.new() as line_form: line_form.product_id = self.product_A line_form.tax_ids.clear() invoice = move_form.save() self.assertAlmostEqual(self.product_A.lst_price * rate, invoice.amount_total) self.assertAlmostEqual(self.product_A.lst_price * rate, invoice.amount_residual) self.assertEqual(len(invoice.mapped("line_ids")), 2) self.assertEqual(len(invoice.mapped("line_ids.currency_id")), 1) invoice._post() self.assertAlmostEqual(self.product_A.lst_price * rate, invoice.amount_total) self.assertAlmostEqual(self.product_A.lst_price * rate, invoice.amount_residual) self.assertEqual(len(invoice.mapped("line_ids")), 4) self.assertEqual( len(invoice.mapped("line_ids").filtered("is_anglo_saxon_line")), 2) self.assertEqual(len(invoice.mapped("line_ids.currency_id")), 2)
def test_attendance_on_morning(self): calendar = self.env['resource.calendar'].create({ 'name': 'Morning only', 'attendance_ids': [(5, 0, 0), (0, 0, { 'name': 'Monday All day', 'hour_from': 8, 'hour_to': 16, 'day_period': 'morning', 'dayofweek': '0', })], }) employee = self.employee_emp employee.resource_calendar_id = calendar with Form(self.env['hr.leave'].with_context(default_employee_id=employee.id)) as leave_form: leave_form.holiday_status_id = self.leave_type leave_form.request_date_from = date(2019, 9, 2) leave_form.request_date_to = date(2019, 9, 2) leave_form.request_unit_half = True # Ask for morning leave_form.request_date_from_period = 'am' self.assertEqual(leave_form.number_of_days_display, 1) self.assertEqual(leave_form.number_of_hours_text, '8 Hours') # Ask for afternoon leave_form.request_date_from_period = 'pm' self.assertEqual(leave_form.number_of_days_display, 1) self.assertEqual(leave_form.number_of_hours_text, '8 Hours')
def _create_taxes(cls): """ Create taxes tax7: 7%, excluded in product price tax10: 10%, included in product price """ tax7 = cls.env['account.tax'].create({'name': 'Tax 7%', 'amount': 7}) tax10 = cls.env['account.tax'].create({ 'name': 'Tax 10%', 'amount': 10, 'price_include': True, 'include_base_amount': False }) (tax7 | tax10).mapped('invoice_repartition_line_ids').write( {'account_id': cls.tax_received_account.id}) (tax7 | tax10).mapped('refund_repartition_line_ids').write( {'account_id': cls.tax_received_account.id}) tax_group_7_10 = tax7.copy() with Form(tax_group_7_10) as tax: tax.name = 'Tax 7+10%' tax.amount_type = 'group' tax.children_tax_ids.add(tax7) tax.children_tax_ids.add(tax10) return {'tax7': tax7, 'tax10': tax10, 'tax_group_7_10': tax_group_7_10}
def test_form_name_onchange(self): """ Test Lead._find_matching_partner() """ lead = self.env['crm.lead'].browse(self.lead_1.ids) lead_dup = lead.copy({'name': 'Duplicate'}) customer = self.env['res.partner'].create({ "name": "Amy Wong", "email": '"Amy, PhD Student, Wong" Tiny <*****@*****.**>' }) wizard = Form(self.env['crm.lead2opportunity.partner'].with_context({ 'active_model': 'crm.lead', 'active_id': lead.id, 'active_ids': lead.ids, })) self.assertEqual(wizard.name, 'merge') self.assertEqual(wizard.action, 'exist') self.assertEqual(wizard.partner_id, customer) self.assertEqual(wizard.duplicated_lead_ids[:], lead + lead_dup) wizard.name = 'convert' wizard.action = 'create' self.assertEqual(wizard.action, 'create', 'Should keep user input') self.assertEqual(wizard.name, 'convert', 'Should keep user input')
def test_o2m_editable_list(self): """ Tests the o2m proxy when the list view is editable rather than delegating to a separate form view """ f = Form(self.env['test_testing_utilities.parent'], view='test_testing_utilities.o2m_parent_ed') custom_tree = self.env.ref('test_testing_utilities.editable_external').id subs_field = f._view['fields']['subs'] tree_view = subs_field['views']['tree'] self.assertEqual(tree_view['type'], 'tree') self.assertEqual( tree_view['view_id'], custom_tree, 'check that the tree view is the one referenced by tree_view_ref' ) self.assertIs(subs_field['views']['edition'], tree_view, "check that the edition view is the tree view") self.assertEqual( subs_field['views']['edition']['view_id'], custom_tree ) with f.subs.new() as s: s.value = 1 with f.subs.new() as s: s.value = 3 with f.subs.new() as s: s.value = 7 r = f.save() self.assertEqual(r.v, 12) self.assertEqual( [get(s) for s in r.subs], [('1', 1, 1), ('3', 3, 3), ('7', 7, 7)] )