补齐证书齐备、证件折算、移动用证和合同绑定,并带上报销批量发放、付款备注以及个人开发流程升级,便于继续讨论已安排计划的调整规则。 Co-authored-by: Cursor <cursoragent@cursor.com>
78 lines
3.6 KiB
Python
78 lines
3.6 KiB
Python
"""证件视角的合同范围查询,复用 CRM 全角色数据权限。"""
|
|
from app.crud.crm.data_scope_helpers import apply_crm_owner_scope
|
|
from app.models.crm_models import CrmContract, CrmContractProduct
|
|
from app.models.pl_quota_models import PlContractCertLink
|
|
from app.services.pl_quota_cert_service import _get_row
|
|
from app.services.pl_quota_contract_service import _contract, get_contract_bindings
|
|
|
|
|
|
def _day(value):
|
|
return value.isoformat()[:10] if value else None
|
|
|
|
|
|
def _product_names(db, user, contract_ids):
|
|
grouped = {}
|
|
if not contract_ids:
|
|
return grouped
|
|
rows = db.query(CrmContractProduct.contract_id, CrmContractProduct.product_name).filter(
|
|
CrmContractProduct.tenant_no == user.tenant_no, CrmContractProduct.del_flag == 0,
|
|
CrmContractProduct.contract_id.in_(contract_ids),
|
|
).order_by(CrmContractProduct.create_time.desc()).all()
|
|
for contract_id, name in rows:
|
|
names = grouped.setdefault(contract_id, [])
|
|
if name and name not in names:
|
|
names.append(name)
|
|
return grouped
|
|
|
|
|
|
def _card(row, names):
|
|
shown = names[:3]
|
|
summary = '、'.join(shown)
|
|
if len(names) > len(shown):
|
|
summary = f'{summary} 等{len(names)}个' if summary else f'{len(names)}个产品'
|
|
return {
|
|
'id': row.id, 'contractNo': row.contract_no, 'contractName': row.contract_name,
|
|
'contractType': row.contract_type, 'customerId': row.customer_id or '',
|
|
'customerName': row.customer_name or '',
|
|
'status': row.status, 'signDate': _day(row.sign_date), 'productSummary': summary,
|
|
}
|
|
|
|
|
|
def _cards(db, user, rows):
|
|
names = _product_names(db, user, [row.id for row in rows])
|
|
return [_card(row, names.get(row.id, [])) for row in rows]
|
|
|
|
|
|
def contract_options(db, user, keyword=None):
|
|
query = db.query(CrmContract).filter(
|
|
CrmContract.tenant_no == user.tenant_no, CrmContract.del_flag == 0,
|
|
CrmContract.status.in_(('approved', 'executing')),
|
|
CrmContract.contract_type.in_(('sale', 'purchase', 'framework_sale', 'framework_purchase')),
|
|
)
|
|
query = apply_crm_owner_scope(query, CrmContract, user.to_user_info(), db, user.tenant_no)
|
|
if keyword:
|
|
query = query.filter((CrmContract.contract_no.contains(keyword)) | (CrmContract.contract_name.contains(keyword)))
|
|
rows = query.order_by(CrmContract.create_time.desc()).limit(100).all()
|
|
return _cards(db, user, rows)
|
|
|
|
|
|
def contract_products(db, user, contract_id):
|
|
_contract(db, user, contract_id)
|
|
rows = db.query(CrmContractProduct).filter_by(tenant_no=user.tenant_no, contract_id=contract_id, del_flag=0)
|
|
return [{'id': r.id, 'productId': r.product_id, 'productName': r.product_name,
|
|
'productNo': r.product_no or '', 'categoryName': r.category_name or '',
|
|
'brandName': r.brand_name or '', 'model': r.model or '', 'unit': r.unit,
|
|
'quantity': r.quantity, 'packageSpec': r.package_spec or '',
|
|
'deliveryMethod': r.delivery_method or ''}
|
|
for r in rows.order_by(CrmContractProduct.create_time.desc()).all()]
|
|
|
|
|
|
def certificate_contracts(db, user, cert_type, cert_id):
|
|
_get_row(db, user, cert_type, cert_id)
|
|
linked = db.query(PlContractCertLink.contract_id).filter_by(
|
|
tenant_no=user.tenant_no, cert_type=cert_type, cert_id=cert_id, del_flag=0)
|
|
query = db.query(CrmContract).filter(CrmContract.tenant_no == user.tenant_no,
|
|
CrmContract.del_flag == 0, CrmContract.id.in_(linked))
|
|
query = apply_crm_owner_scope(query, CrmContract, user.to_user_info(), db, user.tenant_no)
|
|
return _cards(db, user, query.order_by(CrmContract.create_time.desc()).all())
|