Implement issue 1 search, order reuse and tracking
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
"""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'<b>STAGE-([A-H])</b>', 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)
|
||||
Reference in New Issue
Block a user