GoodERP
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

145 rindas
8.6KB

  1. """2026-10-05:13 → 18 指定修复的回归用例,使用独立事务。"""
  2. from odoo.tests import tagged
  3. from odoo.tests.common import TransactionCase
  4. @tagged('post_install', '-at_install', 'port_13_18')
  5. class TestPortSell(TransactionCase):
  6. def test_partial_and_serial_discounts(self):
  7. goods = self.env.ref('goods.mouse')
  8. goods.force_batch_one = False
  9. for kind in ('sell', 'return'):
  10. order = self.env['sell.order'].new({'type': kind})
  11. for quantity, done, expected in [(10, 0, 100), (10, 6, 40), (10, 9, 10), (10, 10, 0), (0, 0, 0)]:
  12. line = self.env['sell.order.line'].new({
  13. 'goods_id': goods.id, 'quantity': quantity, 'quantity_out': done,
  14. 'price': 100, 'price_taxed': 113, 'tax_rate': 13,
  15. 'discount_amount': 100,
  16. })
  17. vals = order.get_delivery_line(line)
  18. self.assertAlmostEqual(vals['discount_amount'], expected)
  19. self.assertEqual(vals['goods_qty'], quantity - done)
  20. if quantity:
  21. self.assertEqual(order.get_delivery_line(line, single=True)['discount_amount'], 10)
  22. # 三个实际批次累计折扣与原单一致,保留 18 含税总额算法。
  23. discounts = []
  24. for done, qty in [(0, 6), (6, 3), (9, 1)]:
  25. line = self.env['sell.order.line'].new({
  26. 'goods_id': goods.id, 'quantity': 10, 'quantity_out': done,
  27. 'price': 100, 'price_taxed': 113, 'tax_rate': 13, 'discount_amount': 100,
  28. })
  29. vals = order.get_delivery_line(line)
  30. # 模拟保存后的草稿行再改数量,按单价折扣分摊。
  31. origin = self.env['wh.move.line'].create(dict(vals, sell_line_id=False))
  32. edited = self.env['wh.move.line'].new(dict(vals, goods_qty=qty), origin=origin)
  33. edited.onchange_discount_rate()
  34. discounts.append(edited.discount_amount)
  35. self.assertAlmostEqual(edited.subtotal, 113 * qty - 10 * qty)
  36. self.assertAlmostEqual(edited.amount + edited.tax_amount, edited.subtotal)
  37. self.assertAlmostEqual(sum(discounts), 100)
  38. def test_fee_supplier_payment_terms_and_due_date(self):
  39. term_order = self.env['pay.method'].create({'name': 'PORT主单30天', 'add_days': 30})
  40. term_fee = self.env['pay.method'].create({'name': 'PORT费用7天', 'add_days': 7})
  41. partner = self.env.ref('core.lenovo')
  42. supplier = partner.copy({'name': 'PORT费用供应商', 'pay_method': term_fee.id})
  43. order = self.env['sell.order'].new({'partner_id': partner.id, 'pay_method': term_order.id})
  44. doc = self.env['sell.delivery'].new({'partner_id': partner.id, 'order_id': order})
  45. category = self.env.ref('money.core_category_purchase')
  46. from datetime import date, timedelta
  47. day = date(2026, 10, 5)
  48. for target, term in [(partner, term_order), (supplier, term_fee)]:
  49. vals = doc._get_invoice_vals(target, category, day, 106, 6)
  50. self.assertEqual(vals['pay_method'], term.id)
  51. vals.update(move_id=False, invoice_date=day)
  52. invoice = self.env['money.invoice'].create(vals)
  53. if invoice.state == 'draft':
  54. invoice.money_invoice_done()
  55. self.assertEqual(invoice.date_due, day + timedelta(days=term.add_days))
  56. supplier.pay_method = False
  57. self.assertFalse(doc._get_invoice_vals(supplier, category, day, 100, 0)['pay_method'])
  58. order.pay_method = False
  59. partner.pay_method = term_fee
  60. self.assertEqual(doc._get_invoice_vals(partner, category, day, 100, 0)['pay_method'], term_fee.id)
  61. def _check_report(self, model):
  62. goods = self.env.ref('goods.mouse').copy({'name': 'PORT报表', 'code': 'PORT-REPORT', 'force_batch_one': False})
  63. partner = self.env.ref('core.jd')
  64. warehouse = self.env.ref('warehouse.hd_stock')
  65. move = self.env['wh.move'].create({'origin': 'sell.delivery.sell', 'partner_id': partner.id,
  66. 'warehouse_id': warehouse.id, 'warehouse_dest_id': self.env.ref('warehouse.warehouse_customer').id})
  67. self.env['wh.move.line'].create({'move_id': move.id, 'type': 'out', 'goods_id': goods.id,
  68. 'goods_qty': 4, 'price': 100, 'price_taxed': 113, 'tax_rate': 13, 'discount_amount': 40,
  69. 'cost_unit': 50, 'state': 'done', 'date': '2026-10-05'})
  70. self.env.flush_all()
  71. values = {'goods_id': goods.id, 'partner_id': partner.id, 'warehouse_id': warehouse.id,
  72. 'goods_categ_id': goods.category_id.id, 'c_category_id': partner.c_category_id.id,
  73. 'user_id': move.user_id.id, 'date_start': '2026-10-01', 'date_end': '2026-10-31'}
  74. for keys in [('goods_id',), ('goods_id', 'warehouse_id'), tuple(values)]:
  75. report = self.env[model].with_context(**{key: values[key] for key in keys})
  76. sql = (report.select_sql() + report.from_sql() + report.where_sql() + report.group_sql()).format(**values)
  77. self.env.cr.execute(sql)
  78. rows = self.env.cr.dictfetchall()
  79. self.assertEqual(len(rows), 1)
  80. if model == 'report.stock.transceive':
  81. self.assertEqual(rows[0]['goods_qty'], 4)
  82. self.assertAlmostEqual(rows[0]['cost'], 200)
  83. else:
  84. self.assertEqual(rows[0]['qty'], 4)
  85. self.assertAlmostEqual(rows[0]['subtotal'], 412)
  86. self.assertAlmostEqual(rows[0]['amount'] + rows[0]['tax_amount'], 412)
  87. def test_report_goods_combined_filters(self):
  88. self._check_report('sell.summary.goods')
  89. def test_report_partner_combined_filters(self):
  90. self._check_report('sell.summary.partner')
  91. def test_report_staff_combined_filters(self):
  92. self._check_report('sell.summary.staff')
  93. def test_report_stock_combined_filters(self):
  94. self._check_report('report.stock.transceive')
  95. def test_three_batch_confirmation_chain(self):
  96. self.env.user.groups_id |= self.env.ref('sell.group_sell')
  97. goods = self.env.ref('goods.keyboard').copy({'name': 'PORT分批sell', 'code': 'PORT-BATCH-sell',
  98. 'using_batch': False, 'force_batch_one': False})
  99. stock = self.env.ref('warehouse.hd_stock')
  100. customer = self.env.ref('core.jd')
  101. location = self.env['location'].create({'name': 'PORT分批库位', 'warehouse_id': stock.id})
  102. 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,
  103. 'warehouse_dest_id': stock.id, 'line_in_ids': [(0, 0, {'goods_id': goods.id,
  104. 'goods_qty': 10, 'price': 50, 'price_taxed': 50, 'type': 'in', 'location_id': location.id})]})
  105. incoming.approve_order()
  106. order = self.env['sell.order'].with_context(warehouse_dest_type='stock', warehouse_type='stock').create({
  107. 'partner_id': customer.id,
  108. 'bank_account_id': False, 'warehouse_id': stock.id,
  109. 'line_ids': [(0, 0, {'goods_id': goods.id, 'uom_id': goods.uom_id.id, 'quantity': 10,
  110. 'price': 100, 'price_taxed': 113, 'tax_rate': 13, 'discount_rate': 0, 'discount_amount': 100})],
  111. })
  112. order.sell_order_done()
  113. discounts = []
  114. for qty in (6, 3, 1):
  115. pending = self.env['sell.delivery'].search([('order_id', '=', order.id), ('state', '=', 'draft')])
  116. if not pending:
  117. order.sell_generate_delivery()
  118. pending = self.env['sell.delivery'].search([('order_id', '=', order.id), ('state', '=', 'draft')])
  119. pending.ensure_one()
  120. line = pending.line_out_ids
  121. line.ensure_one()
  122. draft = self.env['wh.move.line'].new({
  123. 'goods_id': goods.id, 'goods_qty': qty, 'price': line.price, 'price_taxed': line.price_taxed,
  124. 'tax_rate': line.tax_rate, 'discount_rate': line.discount_rate, 'discount_amount': line.discount_amount,
  125. }, origin=line)
  126. draft.onchange_discount_rate()
  127. line.write({'goods_qty': qty, 'discount_amount': draft.discount_amount})
  128. self.assertAlmostEqual(line.subtotal, 103 * qty)
  129. pending.sell_delivery_done()
  130. self.assertEqual(pending.state, 'done')
  131. discounts.append(line.discount_amount)
  132. self.assertEqual(order.line_ids.quantity_out, 10)
  133. self.assertAlmostEqual(sum(discounts), 100)
  134. order.sell_generate_delivery()
  135. self.assertFalse(self.env['sell.delivery'].search([('order_id', '=', order.id), ('state', '=', 'draft')]))
上海开阖软件有限公司 沪ICP备12045867号-1