Some checks failed
Build and Publish Docker Image / build-and-push (push) Has been cancelled
135 lines
5.3 KiB
Python
135 lines
5.3 KiB
Python
"""Regression checks for discounted MoySklad positions in 1C exports."""
|
|
|
|
import sys
|
|
import types
|
|
import unittest
|
|
from decimal import Decimal
|
|
from unittest.mock import patch
|
|
|
|
from lxml import etree
|
|
|
|
|
|
with patch.dict(
|
|
sys.modules,
|
|
{"config": types.SimpleNamespace(
|
|
settings=types.SimpleNamespace(include_accounting_accounts=False)
|
|
)},
|
|
):
|
|
from modules.xml_generator import XML1CGenerator
|
|
|
|
|
|
class DiscountExportTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.generator = XML1CGenerator()
|
|
|
|
@staticmethod
|
|
def order_data(positions, sum_kopecks):
|
|
return {
|
|
"order": {
|
|
"id": "example",
|
|
"name": "example",
|
|
"moment": "2026-09-15 09:00:00",
|
|
"sum": sum_kopecks,
|
|
},
|
|
"organization": {},
|
|
"counterparty": {},
|
|
"positions": positions,
|
|
}
|
|
|
|
@staticmethod
|
|
def values(xml):
|
|
root = etree.fromstring(xml.encode("utf-8"))
|
|
document = root.xpath('//*[local-name()="Документ.РеализацияТоваровУслуг"]')[0]
|
|
header = document.xpath('./*[local-name()="Сумма"]/text()')[0]
|
|
rows = document.xpath(
|
|
'./*[local-name()="Товары" or local-name()="Услуги"]'
|
|
'/*[local-name()="Строка"]'
|
|
)
|
|
return header, [
|
|
{
|
|
name: (row.xpath('./*[local-name()=$name]/text()', name=name) or [None])[0]
|
|
for name in (
|
|
"Цена", "Сумма", "СуммаНДС", "ВидСкидки", "ПроцентСкидки",
|
|
"СуммаСкидки", "СуммаСУчетомСкидки",
|
|
)
|
|
}
|
|
for row in rows
|
|
]
|
|
|
|
def test_discount_applies_to_goods_and_services_in_both_export_modes(self):
|
|
data = self.order_data([
|
|
{
|
|
"quantity": 2, "price": 10000, "discount": 10, "vat": 20,
|
|
"assortment": {"name": "Product", "meta": {"type": "product"}},
|
|
},
|
|
{
|
|
"quantity": 1, "price": 10000, "discount": 10, "vat": 20,
|
|
"assortment": {"name": "Service", "meta": {"type": "service"}},
|
|
},
|
|
], 27000)
|
|
|
|
for xml in (
|
|
self.generator.generate_realization(data),
|
|
self.generator.generate_batch_realization([data]),
|
|
):
|
|
with self.subTest(export=xml[:50]):
|
|
header, rows = self.values(xml)
|
|
self.assertEqual(header, "270")
|
|
self.assertEqual(
|
|
[(r["Цена"], r["Сумма"], r["СуммаНДС"]) for r in rows],
|
|
[("100.00", "200.00", "30.00"),
|
|
("90.00", "90.00", "15.00")],
|
|
)
|
|
self.assertEqual(rows[0]["ВидСкидки"], "НаТовар")
|
|
self.assertEqual(rows[0]["ПроцентСкидки"], "10.00")
|
|
self.assertEqual(rows[0]["СуммаСкидки"], "20.00")
|
|
self.assertEqual(rows[0]["СуммаСУчетомСкидки"], "180.00")
|
|
self.assertEqual(
|
|
Decimal(rows[0]["СуммаСУчетомСкидки"]) + Decimal(rows[1]["Сумма"]),
|
|
Decimal(header),
|
|
)
|
|
|
|
def test_fractional_discount_preserves_kopecks(self):
|
|
data = self.order_data([{
|
|
"quantity": 2, "price": 10001, "discount": 12.5, "vat": 20,
|
|
"assortment": {"name": "Product", "meta": {"type": "product"}},
|
|
}], 17502)
|
|
|
|
header, rows = self.values(self.generator.generate_realization(data))
|
|
self.assertEqual(header, "175.02")
|
|
self.assertEqual(rows[0]["Цена"], "100.01")
|
|
self.assertEqual(rows[0]["Сумма"], "200.02")
|
|
self.assertEqual(rows[0]["ПроцентСкидки"], "12.50")
|
|
self.assertEqual(rows[0]["СуммаСкидки"], "25.00")
|
|
self.assertEqual(rows[0]["СуммаСУчетомСкидки"], "175.02")
|
|
self.assertEqual(rows[0]["СуммаНДС"], "29.17")
|
|
|
|
def test_position_without_discount_keeps_original_price(self):
|
|
data = self.order_data([{
|
|
"quantity": 1, "price": 10001, "vat": 20,
|
|
"assortment": {"name": "Product", "meta": {"type": "product"}},
|
|
}], 10001)
|
|
|
|
header, rows = self.values(self.generator.generate_realization(data))
|
|
self.assertEqual(header, "100.01")
|
|
self.assertEqual(rows[0]["Цена"], "100.01")
|
|
self.assertEqual(rows[0]["Сумма"], "100.01")
|
|
self.assertIsNone(rows[0]["ПроцентСкидки"])
|
|
|
|
def test_service_discount_uses_net_amount_with_two_decimal_price(self):
|
|
data = self.order_data([{
|
|
"quantity": 2, "price": 10001, "discount": 12.5, "vat": 20,
|
|
"assortment": {"name": "Service", "meta": {"type": "service"}},
|
|
}], 17502)
|
|
|
|
header, rows = self.values(self.generator.generate_realization(data))
|
|
self.assertEqual(header, "175.02")
|
|
self.assertEqual(rows[0]["Цена"], "87.51")
|
|
self.assertEqual(rows[0]["Сумма"], "175.02")
|
|
self.assertEqual(rows[0]["СуммаНДС"], "29.17")
|
|
self.assertIsNone(rows[0]["ПроцентСкидки"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|