"""Gitea issue #1: searchable reuse, approved prices, and work stages.""" import re import secrets from decimal import Decimal from conftest import post from test_workflow import action, approve, form, new, order def submit_item(app, clients, supplier, code, spec, price): oid = new(app, clients['maker']) values = form(order(app, oid)['version'], price=price, intent='submit') values['supplier_name'] = supplier values.setlist('item_code', [code]) values.setlist('item_spec', [spec]) assert post(clients['maker'], '/orders/%s/edit' % oid, values).status_code == 302 return oid def test_supplier_material_search_and_approved_price_reuse(app, clients): from models import Material, Supplier with app.Session() as db: db.add_all([ Supplier(code='SU-01', name='苏州甲公司', short_name='甲司', active=True), Supplier(code='SU-02', name='苏州乙公司', short_name='乙司', active=True), Material(code='AX-55', spec='航空轴承', unit='件', price=Decimal('4.0000'), active=True), ]) db.commit() supplier_page = clients['maker'].get('/suppliers?kw=甲司').get_data(as_text=True) assert 'SU-01' in supplier_page and 'SU-02' not in supplier_page material_page = clients['maker'].get('/materials?kw=航空').get_data(as_text=True) assert 'AX-55' in material_page assert 'supplierSearch' in clients['maker'].get('/orders/new').get_data(as_text=True) oid_a = submit_item(app, clients, '苏州甲公司', 'AX-55', '航空轴承', '12.3456') with app.Session() as db: assert db.query(Material).filter_by(code='AX-55').one().price == Decimal('4.0000') approve(app, clients, oid_a) with app.Session() as db: assert db.query(Material).filter_by(code='AX-55').one().price == Decimal('12.3456') oid_b = submit_item(app, clients, '苏州乙公司', 'AX-55', '航空轴承', '18.7654') approve(app, clients, oid_b) with app.Session() as db: assert db.query(Material).filter_by(code='AX-55').one().price == Decimal('18.7654') prices = clients['maker'].get('/api/material-prices', query_string={'supplier_name': '苏州甲公司'}).json assert prices['AX-55'] == '12.3456' assert clients['other'].get('/api/material-prices', query_string={'supplier_name': '苏州甲公司'}).json == {} assert clients['approver'].get('/api/material-prices', query_string={'supplier_name': '苏州甲公司'}).status_code == 403 edit_page = clients['maker'].get('/orders/%s/edit' % new(app, clients['maker'])).get_data(as_text=True) assert 'matsearch' in edit_page and 'search_select.js' in edit_page # An already completed order remains searchable by its material and reusable. with app.Session() as db: row = db.get(app.Order, oid_a) row.invoice_status, row.delivery_status, row.payment_status = 'received', 'delivered', 'paid' row.fulfillment_revision = row.payment_revision = row.revision db.commit() assert 'AX-55' not in clients['maker'].get('/orders').get_data(as_text=True) result = clients['maker'].get('/orders', query_string={'material_kw': '航空轴承'}).get_data(as_text=True) assert 'AX-55' in result and '匹配物料' in result and '复制下单' in result assert clients['other'].get('/orders', query_string={'material_kw': '航空轴承'}).get_data(as_text=True).count('AX-55') == 0 copied = action(app, clients['maker'], oid_a, 'copy', request_key=secrets.token_hex(16)) assert copied.status_code == 302 copy_id = int(re.search(r'/orders/(\d+)', copied.location)[1]) with app.Session() as db: clone = db.get(app.Order, copy_id) assert clone.status == 'draft' and clone.items[0].delivery_date == '' assert clone.items[0].price == Decimal('12.3456') assert '请填写新交期' in clients['maker'].get(copied.location).get_data(as_text=True) def test_new_material_is_added_on_approval_and_draft_does_not_change_catalog(app, clients): from models import Material oid = submit_item(app, clients, '新供应商', 'NEW-314', '新规格', '3.2109') with app.Session() as db: assert db.query(Material).filter_by(code='NEW-314').count() == 0 approve(app, clients, oid) with app.Session() as db: material = db.query(Material).filter_by(code='NEW-314').one() assert material.price == Decimal('3.2109') and material.spec == '新规格' def test_admin_can_backfill_old_approved_prices_without_changing_orders(app, clients): from models import Material oid = submit_item(app, clients, '历史供应商', 'OLD-9', '历史物料', '7.4321') approve(app, clients, oid) pdf = clients['maker'].get('/orders/%s/pdf' % oid).data with app.Session() as db: db.query(Material).filter_by(code='OLD-9').one().price = Decimal('0') db.commit() assert post(clients['maker'], '/materials/prices/from-approved-orders').status_code == 403 assert post(clients['admin'], '/materials/prices/from-approved-orders').status_code == 302 with app.Session() as db: assert db.query(Material).filter_by(code='OLD-9').one().price == Decimal('7.4321') assert clients['maker'].get('/orders/%s/pdf' % oid).data == pdf def test_work_stage_filters_leave_unclassified_orders_visible(app, clients): from models import Order, User with app.Session() as db: maker = db.query(User).filter_by(username='maker').one() samples = [ ('A', 'pending', 'unpaid', 'pending', 1), ('B', 'partial', 'paid', 'received', 1), ('C', 'delivered', 'unpaid', 'received', 1), ('D', 'delivered', 'partial', 'received', 1), ('E', 'delivered', 'paid', 'received', 1), ('F', 'delivered', 'paid', 'pending', 1), ('G', 'unknown', 'unknown', 'unknown', 1), ('H', 'delivered', 'paid', 'received', 0), ] for suffix, delivery, payment, invoice, payment_revision in samples: db.add(Order(order_no='STAGE-' + suffix, created_by=maker.id, created_by_name='maker', supplier_name='阶段测试', status='approved', revision=1, delivery_status=delivery, payment_status=payment, invoice_status=invoice, fulfillment_revision=1, payment_revision=payment_revision)) db.commit() expected = { 'work_undelivered': {'A', 'B'}, 'work_invoice_due': {'C', 'D'}, 'work_completed': {'E'}, 'work_other': {'F', 'G', 'H'}, } for key, suffixes in expected.items(): html = clients['maker'].get('/orders', query_string={'tracking': key}).get_data(as_text=True) found = set(re.findall(r'STAGE-([A-H])', html)) assert found == suffixes, (key, found) assert 'STAGE-A' not in clients['other'].get('/orders', query_string={'tracking': 'work_undelivered'}).get_data(as_text=True)