"""单位换算只在计量段已绑定异单位证件时成立。""" from datetime import date, datetime from types import SimpleNamespace from sqlalchemy import create_engine from sqlalchemy.orm import Session from app.models.pl_models import ( PlPlan, PlPlanDelivery, PlPlanDeliveryProduct, PlPlanLoad, PlPlanLoadProduct, PlPlanProduct, ) from app.models.pl_quota_models import ( PlContractCertLink, PlContractCertProduct, PlPlanCertUsage, PlPurchaseCert, PlTransportCert, ) from app.services.pl_menu_badge_service import count_plan_cert_pending from app.services.pl_quota_conversion import plan_needs_unit_conversion from app.services.pl_quota_overview import list_plans def line(line_id, side, unit, contract_product_id='cp', customer='客户', toxic=True): return { 'id': line_id, 'planProductId': 'pp', 'side': side, 'unit': unit, 'contractProductId': contract_product_id, 'customerName': customer, 'isToxic': toxic, } def plan(**values): return SimpleNamespace( cert_configuration=values.get('configuration'), transport_status=values.get('transport_status', 'pending'), archive_status=values.get('archive_status', 'unarchived'), ) def test_same_label_and_code_do_not_need_conversion(): current = plan() assert plan_needs_unit_conversion(current, [line('L', 'load', '吨')], {'cp': ['dun']}, []) is False assert plan_needs_unit_conversion(current, [line('L', 'load', '吨', toxic=False)], {'cp': ['kg']}, []) is False assert plan_needs_unit_conversion( current, [line('L', 'load', '吨', customer='安庆市山峡化工有限公司')], {'cp': ['ping']}, [], ) is True assert plan_needs_unit_conversion(current, [line('L', 'load', '吨')], {'cp': ['kg']}, []) is False assert plan_needs_unit_conversion(current, [line('L', 'load', '升')], {'cp': ['毫升']}, []) is False def test_unbound_and_unselected_legacy_sides_are_display_only(): both = [line('L', 'load', '吨'), line('D', 'delivery', '吨')] arranged = plan(transport_status='arranged') assert plan_needs_unit_conversion(arranged, both, {'cp': ['kg']}, []) is False chosen = plan(transport_status='arranged', configuration={'sourceMapping': [ {'sourceStopType': 'load', 'sourceStopProductId': 'L', 'relatedStopProductIds': ['D']}, ]}) assert plan_needs_unit_conversion(chosen, both, {'cp': ['瓶']}, []) is True assert plan_needs_unit_conversion(chosen, both, {'cp': ['kg']}, []) is False def test_new_plan_counts_either_stop_when_a_bound_certificate_uses_another_unit(): current = plan() assert plan_needs_unit_conversion( current, [line('L', 'load', 'dun'), line('D', 'delivery', 'dun')], {'cp': ['kg']}, [], ) is False assert plan_needs_unit_conversion( current, [line('L', 'load', 'dun'), line('D', 'delivery', 'dun')], {'cp': ['ping']}, [], ) is True assert plan_needs_unit_conversion(current, [line('L', 'load', 'dun')], {}, []) is False def test_list_and_badge_count_only_plans_with_a_real_unit_mismatch(monkeypatch): engine = create_engine('sqlite://') models = ( PlPlan, PlPlanProduct, PlPlanLoad, PlPlanDelivery, PlPlanLoadProduct, PlPlanDeliveryProduct, PlContractCertLink, PlContractCertProduct, PlPurchaseCert, PlTransportCert, PlPlanCertUsage, ) for model in models: model.__table__.create(engine) with Session(engine) as db: user = SimpleNamespace(id='u', tenant_no='t', to_user_info=lambda: {'role': 'super_admin', 'user_id': 'u'}) db.add(PlPlan(id='plain', plan_no='PLAIN', create_date=date(2026, 11, 1), plan_date=date(2026, 11, 1), plan_type='direct', belongs_company='shanxia', tenant_no='t', create_time=datetime(2026, 11, 1))) db.add(PlPlan(id='mix', plan_no='MIX', create_date=date(2026, 11, 2), plan_date=date(2026, 11, 2), plan_type='direct', belongs_company='shanxia', tenant_no='t', create_time=datetime(2026, 11, 2))) db.add(PlPlanProduct(id='pp-plain', plan_id='plain', product_id='sku', product_no='SKU', product_name='硫酸', is_toxic=1, tenant_no='t')) db.add(PlPlanProduct(id='pp-mix', plan_id='mix', product_id='sku', product_no='SKU', product_name='硫酸', is_toxic=1, tenant_no='t')) db.add(PlPlanLoad(id='load-mix', plan_id='mix', customer_name='外部客户', tenant_no='t')) db.add(PlPlanLoadProduct( id='line-mix', load_id='load-mix', plan_id='mix', plan_product_id='pp-mix', product_id='sku', product_no='SKU', product_name='硫酸', unit='吨', contract_product_id='cp', tenant_no='t', )) db.add(PlPurchaseCert( id='buy', cert_no='BUY', product_name_on_cert='硫酸', total_qty=1, quantity_unit='ping', valid_use_text='多次有效', buyer_name='买方', seller_name='卖方', tenant_no='t', )) db.add(PlContractCertLink( id='link', contract_id='c', contract_no_snapshot='C-1', cert_type='purchase', cert_id='buy', tenant_no='t', )) db.add(PlContractCertProduct(id='scope', contract_cert_link_id='link', contract_product_id='cp', tenant_no='t')) db.commit() monkeypatch.setattr('app.services.pl_menu_badge_service.apply_pl_scope', lambda query, *args, **kwargs: query) monkeypatch.setattr('app.services.pl_quota_overview.apply_pl_scope', lambda query, *args, **kwargs: query) listed = {row['planNo']: row['needsUnitConversion'] for row in list_plans(db, user)['list']} assert listed == {'MIX': True, 'PLAIN': False} only = list_plans(db, user, conversion_only=True) assert only['total'] == 1 and only['list'][0]['planNo'] == 'MIX' assert count_plan_cert_pending(db, 't', user) == 1 engine.dispose()