|
- """2026-10-05:13 → 18 指定修复的回归用例,使用独立事务。"""
- from odoo.tests import tagged
- from odoo.tests.common import TransactionCase
-
-
- @tagged('post_install', '-at_install', 'port_13_18')
- class TestPortSell(TransactionCase):
- def test_partial_and_serial_discounts(self):
- goods = self.env.ref('goods.mouse')
- goods.force_batch_one = False
- for kind in ('sell', 'return'):
- order = self.env['sell.order'].new({'type': kind})
- for quantity, done, expected in [(10, 0, 100), (10, 6, 40), (10, 9, 10), (10, 10, 0), (0, 0, 0)]:
- line = self.env['sell.order.line'].new({
- 'goods_id': goods.id, 'quantity': quantity, 'quantity_out': done,
- 'price': 100, 'price_taxed': 113, 'tax_rate': 13,
- 'discount_amount': 100,
- })
- vals = order.get_delivery_line(line)
- self.assertAlmostEqual(vals['discount_amount'], expected)
- self.assertEqual(vals['goods_qty'], quantity - done)
- if quantity:
- self.assertEqual(order.get_delivery_line(line, single=True)['discount_amount'], 10)
- # 三个实际批次累计折扣与原单一致,保留 18 含税总额算法。
- discounts = []
- for done, qty in [(0, 6), (6, 3), (9, 1)]:
- line = self.env['sell.order.line'].new({
- 'goods_id': goods.id, 'quantity': 10, 'quantity_out': done,
- 'price': 100, 'price_taxed': 113, 'tax_rate': 13, 'discount_amount': 100,
- })
- vals = order.get_delivery_line(line)
- # 模拟保存后的草稿行再改数量,按单价折扣分摊。
- origin = self.env['wh.move.line'].create(dict(vals, sell_line_id=False))
- edited = self.env['wh.move.line'].new(dict(vals, goods_qty=qty), origin=origin)
- edited.onchange_discount_rate()
- discounts.append(edited.discount_amount)
- self.assertAlmostEqual(edited.subtotal, 113 * qty - 10 * qty)
- self.assertAlmostEqual(edited.amount + edited.tax_amount, edited.subtotal)
- self.assertAlmostEqual(sum(discounts), 100)
-
- def test_fee_supplier_payment_terms_and_due_date(self):
- term_order = self.env['pay.method'].create({'name': 'PORT主单30天', 'add_days': 30})
- term_fee = self.env['pay.method'].create({'name': 'PORT费用7天', 'add_days': 7})
- partner = self.env.ref('core.lenovo')
- supplier = partner.copy({'name': 'PORT费用供应商', 'pay_method': term_fee.id})
- order = self.env['sell.order'].new({'partner_id': partner.id, 'pay_method': term_order.id})
- doc = self.env['sell.delivery'].new({'partner_id': partner.id, 'order_id': order})
- category = self.env.ref('money.core_category_purchase')
- from datetime import date, timedelta
- day = date(2026, 10, 5)
- for target, term in [(partner, term_order), (supplier, term_fee)]:
- vals = doc._get_invoice_vals(target, category, day, 106, 6)
- self.assertEqual(vals['pay_method'], term.id)
- vals.update(move_id=False, invoice_date=day)
- invoice = self.env['money.invoice'].create(vals)
- if invoice.state == 'draft':
- invoice.money_invoice_done()
- self.assertEqual(invoice.date_due, day + timedelta(days=term.add_days))
- supplier.pay_method = False
- self.assertFalse(doc._get_invoice_vals(supplier, category, day, 100, 0)['pay_method'])
- order.pay_method = False
- partner.pay_method = term_fee
- self.assertEqual(doc._get_invoice_vals(partner, category, day, 100, 0)['pay_method'], term_fee.id)
-
- def _check_report(self, model):
- goods = self.env.ref('goods.mouse').copy({'name': 'PORT报表', 'code': 'PORT-REPORT', 'force_batch_one': False})
- partner = self.env.ref('core.jd')
- warehouse = self.env.ref('warehouse.hd_stock')
- move = self.env['wh.move'].create({'origin': 'sell.delivery.sell', 'partner_id': partner.id,
- 'warehouse_id': warehouse.id, 'warehouse_dest_id': self.env.ref('warehouse.warehouse_customer').id})
- self.env['wh.move.line'].create({'move_id': move.id, 'type': 'out', 'goods_id': goods.id,
- 'goods_qty': 4, 'price': 100, 'price_taxed': 113, 'tax_rate': 13, 'discount_amount': 40,
- 'cost_unit': 50, 'state': 'done', 'date': '2026-10-05'})
- self.env.flush_all()
- values = {'goods_id': goods.id, 'partner_id': partner.id, 'warehouse_id': warehouse.id,
- 'goods_categ_id': goods.category_id.id, 'c_category_id': partner.c_category_id.id,
- 'user_id': move.user_id.id, 'date_start': '2026-10-01', 'date_end': '2026-10-31'}
- for keys in [('goods_id',), ('goods_id', 'warehouse_id'), tuple(values)]:
- report = self.env[model].with_context(**{key: values[key] for key in keys})
- sql = (report.select_sql() + report.from_sql() + report.where_sql() + report.group_sql()).format(**values)
- self.env.cr.execute(sql)
- rows = self.env.cr.dictfetchall()
- self.assertEqual(len(rows), 1)
- if model == 'report.stock.transceive':
- self.assertEqual(rows[0]['goods_qty'], 4)
- self.assertAlmostEqual(rows[0]['cost'], 200)
- else:
- self.assertEqual(rows[0]['qty'], 4)
- self.assertAlmostEqual(rows[0]['subtotal'], 412)
- self.assertAlmostEqual(rows[0]['amount'] + rows[0]['tax_amount'], 412)
-
- def test_report_goods_combined_filters(self):
- self._check_report('sell.summary.goods')
-
- def test_report_partner_combined_filters(self):
- self._check_report('sell.summary.partner')
-
- def test_report_staff_combined_filters(self):
- self._check_report('sell.summary.staff')
-
- def test_report_stock_combined_filters(self):
- self._check_report('report.stock.transceive')
-
- def test_three_batch_confirmation_chain(self):
- self.env.user.groups_id |= self.env.ref('sell.group_sell')
- goods = self.env.ref('goods.keyboard').copy({'name': 'PORT分批sell', 'code': 'PORT-BATCH-sell',
- 'using_batch': False, 'force_batch_one': False})
- stock = self.env.ref('warehouse.hd_stock')
- customer = self.env.ref('core.jd')
- location = self.env['location'].create({'name': 'PORT分批库位', 'warehouse_id': stock.id})
- incoming = self.env['wh.in'].create({'type': 'others', 'finance_category_id': self.env.ref('core.cat_donate').id, 'warehouse_id': self.env.ref('warehouse.warehouse_supplier').id,
- 'warehouse_dest_id': stock.id, 'line_in_ids': [(0, 0, {'goods_id': goods.id,
- 'goods_qty': 10, 'price': 50, 'price_taxed': 50, 'type': 'in', 'location_id': location.id})]})
- incoming.approve_order()
- order = self.env['sell.order'].with_context(warehouse_dest_type='stock', warehouse_type='stock').create({
- 'partner_id': customer.id,
- 'bank_account_id': False, 'warehouse_id': stock.id,
- 'line_ids': [(0, 0, {'goods_id': goods.id, 'uom_id': goods.uom_id.id, 'quantity': 10,
- 'price': 100, 'price_taxed': 113, 'tax_rate': 13, 'discount_rate': 0, 'discount_amount': 100})],
- })
- order.sell_order_done()
- discounts = []
- for qty in (6, 3, 1):
- pending = self.env['sell.delivery'].search([('order_id', '=', order.id), ('state', '=', 'draft')])
- if not pending:
- order.sell_generate_delivery()
- pending = self.env['sell.delivery'].search([('order_id', '=', order.id), ('state', '=', 'draft')])
- pending.ensure_one()
- line = pending.line_out_ids
- line.ensure_one()
- draft = self.env['wh.move.line'].new({
- 'goods_id': goods.id, 'goods_qty': qty, 'price': line.price, 'price_taxed': line.price_taxed,
- 'tax_rate': line.tax_rate, 'discount_rate': line.discount_rate, 'discount_amount': line.discount_amount,
- }, origin=line)
- draft.onchange_discount_rate()
- line.write({'goods_qty': qty, 'discount_amount': draft.discount_amount})
- self.assertAlmostEqual(line.subtotal, 103 * qty)
- pending.sell_delivery_done()
- self.assertEqual(pending.state, 'done')
- discounts.append(line.discount_amount)
- self.assertEqual(order.line_ids.quantity_out, 10)
- self.assertAlmostEqual(sum(discounts), 100)
- order.sell_generate_delivery()
- self.assertFalse(self.env['sell.delivery'].search([('order_id', '=', order.id), ('state', '=', 'draft')]))
|