feat(pl): 展示各装送段用证配置与独立占用明细并保留历史计量口径。
This commit is contained in:
1 parent
706260ff7a
commit
b764eb02a7
10 files changed
+497
-40
No files matched your search
@@ -156,34 +156,55 @@ def save_configuration(db, user, plan_id, config):
|
||||
def get_plan_quota(db, user, plan_id):
|
||||
with db.no_autoflush:
|
||||
plan, products, rows, stops = source_context(db, user, plan_id)
|
||||
from app.services.pl_quota_contract_service import _contract
|
||||
contract_numbers = {}
|
||||
from app.services.pl_quota_contract_service import _contract, get_contract_bindings
|
||||
contract_numbers, contract_bindings = {}, {}
|
||||
for cid in {r.contract_id for values in rows.values() for r in values.values() if r.contract_id}:
|
||||
try:
|
||||
contract_numbers[cid] = _contract(db, user, cid).contract_no
|
||||
bindings = get_contract_bindings(db, user, cid)
|
||||
contract_bindings[cid] = []
|
||||
for binding in bindings:
|
||||
if binding['linkStatus'] != 'active':
|
||||
continue
|
||||
cert = _get_row(db, user, binding['certType'], binding['certId'])
|
||||
contract_bindings[cid].append({
|
||||
'certId': cert.id, 'certType': binding['certType'],
|
||||
'certNo': cert.cert_no, 'quantityUnit': cert.quantity_unit,
|
||||
'productIds': [p['contractProductId'] for p in binding['products']
|
||||
if p['scopeStatus'] == 'active']})
|
||||
except HTTPException as exc:
|
||||
if exc.status_code not in (403, 404):
|
||||
raise
|
||||
contract_numbers[cid] = None
|
||||
options = []
|
||||
contract_bindings.pop(cid, None)
|
||||
options, stop_products = [], []
|
||||
for side, values in rows.items():
|
||||
for row in values.values():
|
||||
if products[row.plan_product_id].is_toxic == 1:
|
||||
stop = stops[side][getattr(row, 'load_id' if side == 'load' else 'delivery_id')]
|
||||
options.append({'sourceStopId': stop.id, 'stopId': stop.id,
|
||||
'stopOrder': getattr(stop, 'seq', None) or stop.order_num or 1,
|
||||
'productId': row.product_id, 'productNo': row.product_no,
|
||||
'sourceStopType': side, 'sourceStopProductId': row.id,
|
||||
'planProductId': row.plan_product_id, 'productName': row.product_name,
|
||||
'model': row.model, 'quantity': row.plan_qty, 'unit': row.unit,
|
||||
'contractId': row.contract_id, 'contractNo': contract_numbers.get(row.contract_id),
|
||||
'contractProductId': row.contract_product_id,
|
||||
'partyName': stop.customer_name})
|
||||
product = products[row.plan_product_id]
|
||||
stop = stops[side][getattr(row, 'load_id' if side == 'load' else 'delivery_id')]
|
||||
item = {'sourceStopId': stop.id, 'stopId': stop.id,
|
||||
'stopOrder': getattr(stop, 'seq', None) or stop.order_num or 1,
|
||||
'productId': row.product_id, 'productNo': row.product_no,
|
||||
'sourceStopType': side, 'sourceStopProductId': row.id,
|
||||
'planProductId': row.plan_product_id, 'productName': row.product_name,
|
||||
'model': row.model, 'quantity': row.plan_qty, 'unit': row.unit,
|
||||
'contractId': row.contract_id, 'contractNo': contract_numbers.get(row.contract_id),
|
||||
'contractProductId': row.contract_product_id,
|
||||
'partyName': stop.customer_name}
|
||||
stop_products.append({**item, 'isToxic': product.is_toxic == 1,
|
||||
'isExplosive': product.is_explosive == 1,
|
||||
'bindingsReadable': row.contract_id in contract_bindings,
|
||||
'certificates': [{k: v for k, v in cert.items() if k != 'productIds'}
|
||||
for cert in contract_bindings.get(row.contract_id, [])
|
||||
if row.contract_product_id in cert['productIds']]})
|
||||
if product.is_toxic == 1:
|
||||
options.append(item)
|
||||
usages = db.query(PlPlanCertUsage).filter_by(tenant_no=user.tenant_no, plan_id=plan_id, del_flag=0).order_by(PlPlanCertUsage.create_time.desc()).all()
|
||||
version = resolve_measurement_version(db, user, plan)
|
||||
result = {'planId': plan.id, 'planNo': plan.plan_no, 'licensePlate': plan.license_plate,
|
||||
'measurementVersion': version,
|
||||
'configuration': {**(plan.cert_configuration or {}), 'measurementVersion': version}, 'sourceOptions': options,
|
||||
'stopProducts': stop_products,
|
||||
'canSaveConfiguration': plan.transport_status != 'arranged' and plan.archive_status != 'archived',
|
||||
'usages': []}
|
||||
for usage in usages:
|
||||
|
||||
@@ -194,10 +194,11 @@ def test_server_version_cannot_be_overridden_by_client(case, history):
|
||||
|
||||
def test_options_include_stop_contract_and_party_without_foreign_contract_leak(case):
|
||||
from app.models.crm_models import CrmContract
|
||||
from app.models.pl_quota_models import PlContractCertLink, PlContractCertProduct
|
||||
from app.models.pl_quota_models import PlPlanCertUsage, PlPlanCertUsageItem
|
||||
from app.services.pl_quota_planning import get_plan_quota
|
||||
c = case
|
||||
for model in (CrmContract, PlPlanCertUsage, PlPlanCertUsageItem): model.__table__.create(c.db.bind)
|
||||
for model in (CrmContract, PlPlanCertUsage, PlPlanCertUsageItem, PlContractCertLink, PlContractCertProduct): model.__table__.create(c.db.bind)
|
||||
c.db.add(CrmContract(id='purchase', contract_no='PUR-1', contract_name='购买合同', customer_id='customer', contract_type='purchase', tenant_no='t'))
|
||||
c.db.add(CrmContract(id='sale', contract_no='SECRET', contract_name='其他租户', customer_id='customer', contract_type='sale', tenant_no='other'))
|
||||
c.db.get(c.m.PlPlanLoad, 'load').customer_name = '装货方'
|
||||
@@ -207,3 +208,41 @@ def test_options_include_stop_contract_and_party_without_foreign_contract_leak(c
|
||||
assert options['load']['partyName'] == '装货方'
|
||||
assert options['load']['stopId'] == 'load' and options['load']['stopOrder'] == 1
|
||||
assert options['delivery']['contractNo'] is None
|
||||
|
||||
|
||||
def test_readonly_stop_products_include_explosive_without_changing_sources(case):
|
||||
from app.models.crm_models import CrmContract
|
||||
from app.models.pl_quota_models import PlContractCertLink, PlContractCertProduct
|
||||
from app.models.pl_quota_models import PlPlanCertUsage, PlPlanCertUsageItem
|
||||
from app.services.pl_quota_planning import get_plan_quota
|
||||
c = case
|
||||
for model in (CrmContract, PlPlanCertUsage, PlPlanCertUsageItem, PlContractCertLink, PlContractCertProduct): model.__table__.create(c.db.bind)
|
||||
product = c.db.get(c.m.PlPlanProduct, 'pp')
|
||||
product.is_toxic = 0
|
||||
product.is_explosive = 1
|
||||
c.db.flush()
|
||||
result = get_plan_quota(c.db, c.user, 'plan')
|
||||
assert result['sourceOptions'] == []
|
||||
assert len(result['stopProducts']) == 2
|
||||
assert all(row['isExplosive'] and not row['isToxic'] for row in result['stopProducts'])
|
||||
assert {row['contractId'] for row in result['stopProducts']} == {'purchase', 'sale'}
|
||||
|
||||
|
||||
def test_stop_products_bindings_are_product_specific_and_hidden_contract_is_explicit(case):
|
||||
from app.models.crm_models import CrmContract
|
||||
from app.models.pl_quota_models import (PlPlanCertUsage, PlPlanCertUsageItem,
|
||||
PlContractCertLink, PlContractCertProduct, PlPurchaseCert)
|
||||
from app.services.pl_quota_planning import get_plan_quota
|
||||
c = case
|
||||
for model in (CrmContract, PlPlanCertUsage, PlPlanCertUsageItem, PlContractCertLink, PlContractCertProduct, PlPurchaseCert): model.__table__.create(c.db.bind)
|
||||
c.db.add(CrmContract(id='purchase', contract_no='PUR', contract_name='采购', customer_id='customer', contract_type='purchase', tenant_no='t'))
|
||||
c.db.add(PlPurchaseCert(id='cert', cert_no='BUY', product_name_on_cert='硫酸', valid_use_text='多次有效', buyer_name='买方', seller_name='卖方', total_qty=100, quantity_unit='吨', tenant_no='t'))
|
||||
c.db.add(PlContractCertLink(id='link',contract_id='purchase',contract_no_snapshot='PUR',cert_type='purchase',cert_id='cert',link_status='active',tenant_no='t'))
|
||||
c.db.add(PlContractCertProduct(id='scope',contract_cert_link_id='link',contract_product_id='cp',scope_status='active',tenant_no='t'))
|
||||
c.db.flush()
|
||||
rows = get_plan_quota(c.db,c.user,'plan')['stopProducts']
|
||||
assert rows[0]['certificates'][0]['certNo'] == 'BUY'
|
||||
assert rows[1]['bindingsReadable'] is False
|
||||
assert rows[1]['certificates'] == []
|
||||
c.db.get(PlContractCertProduct,'scope').scope_status='inactive'; c.db.flush()
|
||||
assert get_plan_quota(c.db,c.user,'plan')['stopProducts'][0]['certificates'] == []
|
||||
Reference in new issue
Block a user