Go to matching action
This commit is contained in:
@@ -248,11 +248,12 @@ def register():
|
||||
sale.AnalyticDimensionAssignment,
|
||||
sale.PriceComposition,
|
||||
module='sale', type_='model')
|
||||
Pool.register(
|
||||
lot.LotShipping,
|
||||
lot.LotMatching,
|
||||
#lot.LotMatchingUnit,
|
||||
lot.LotWeighing,
|
||||
Pool.register(
|
||||
lot.LotShipping,
|
||||
lot.LotMatching,
|
||||
lot.LotGoMatching,
|
||||
#lot.LotMatchingUnit,
|
||||
lot.LotWeighing,
|
||||
lot.CreateContracts,
|
||||
lot.LotUnmatch,
|
||||
lot.LotUnship,
|
||||
|
||||
@@ -2612,9 +2612,9 @@ class LotContext(ModelView):
|
||||
def default_ps(cls):
|
||||
return 'all'
|
||||
|
||||
@classmethod
|
||||
def default_group(cls):
|
||||
return 'by_physic'
|
||||
@classmethod
|
||||
def default_group(cls):
|
||||
return 'all'
|
||||
|
||||
@classmethod
|
||||
def default_wh(cls):
|
||||
@@ -2801,9 +2801,62 @@ class LotMatching(Wizard):
|
||||
|
||||
matching = StateTransition()
|
||||
|
||||
def transition_start(self):
|
||||
return 'match'
|
||||
|
||||
def transition_start(self):
|
||||
return 'match'
|
||||
|
||||
@staticmethod
|
||||
def _record_id(record):
|
||||
return record.id if record else None
|
||||
|
||||
@classmethod
|
||||
def _matching_lot_value(cls, lqt, side):
|
||||
lot = lqt.lot_p if side == 'purchase' else lqt.lot_s
|
||||
line = getattr(lot, 'line', None)
|
||||
sale_line = getattr(lot, 'sale_line', None)
|
||||
purchase = getattr(line, 'purchase', None)
|
||||
sale = getattr(sale_line, 'sale', None)
|
||||
party = (
|
||||
getattr(purchase, 'party', None) if side == 'purchase'
|
||||
else getattr(sale, 'party', None))
|
||||
quantity = Decimal(str(lqt.lot_quantity or 0))
|
||||
if side == 'sale':
|
||||
quantity = abs(quantity)
|
||||
return {
|
||||
'lot_id': cls._record_id(lot),
|
||||
'lot_r_id': cls._record_id(lqt),
|
||||
'lot_purchase': cls._record_id(purchase),
|
||||
'lot_sale': cls._record_id(sale),
|
||||
'lot_shipment_in': cls._record_id(lqt.lot_shipment_in),
|
||||
'lot_shipment_internal': cls._record_id(
|
||||
lqt.lot_shipment_internal),
|
||||
'lot_shipment_out': cls._record_id(lqt.lot_shipment_out),
|
||||
'lot_type': getattr(lot, 'lot_type', None),
|
||||
'lot_product': cls._record_id(getattr(lot, 'lot_product', None)),
|
||||
'lot_quantity': quantity,
|
||||
'lot_matched_qt': 0,
|
||||
'lot_cp': cls._record_id(party),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _selected_matching_defaults(cls, active_ids):
|
||||
LotQt = Pool().get('lot.qt')
|
||||
lot_p = []
|
||||
lot_s = []
|
||||
for active_id in active_ids or []:
|
||||
if active_id <= 10000000:
|
||||
continue
|
||||
lqt = LotQt(active_id - 10000000)
|
||||
if lqt.lot_p and lqt.lot_s:
|
||||
continue
|
||||
if lqt.lot_p:
|
||||
lot_p.append(cls._matching_lot_value(lqt, 'purchase'))
|
||||
elif lqt.lot_s:
|
||||
lot_s.append(cls._matching_lot_value(lqt, 'sale'))
|
||||
return {
|
||||
'lot_p': lot_p,
|
||||
'lot_s': lot_s,
|
||||
}
|
||||
|
||||
def transition_matching(self):
|
||||
Warning = Pool().get('res.user.warning')
|
||||
LotQt = Pool().get('lot.qt')
|
||||
@@ -2831,10 +2884,30 @@ class LotMatching(Wizard):
|
||||
|
||||
return 'end'
|
||||
|
||||
def end(self):
|
||||
return 'reload'
|
||||
|
||||
class LotMatchingStart(ModelView):
|
||||
def end(self):
|
||||
return 'reload'
|
||||
|
||||
|
||||
class LotGoMatching(LotMatching):
|
||||
"Go to matching"
|
||||
__name__ = "lot.go_matching"
|
||||
|
||||
match = StateView(
|
||||
'lot.matching.start',
|
||||
'purchase_trade.go_matching_view_form', [
|
||||
Button("Cancel", 'end', 'tryton-cancel'),
|
||||
Button("Match", 'matching', 'tryton-ok', default=True),
|
||||
])
|
||||
|
||||
def default_match(self, fields):
|
||||
context = Transaction().context
|
||||
values = self._selected_matching_defaults(
|
||||
context.get('active_ids') or [])
|
||||
values['qt_type'] = 'all'
|
||||
return values
|
||||
|
||||
|
||||
class LotMatchingStart(ModelView):
|
||||
"Matching"
|
||||
__name__ = "lot.matching.start"
|
||||
lot_p = fields.One2Many('lot.matching.lot','lms',"Purchase")
|
||||
|
||||
@@ -164,16 +164,21 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="type">tree</field>
|
||||
<field name="name">lot_invoicing_inv_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="matching_view_form">
|
||||
<field name="model">lot.matching.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">lot_matching_start_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="matching_lot_view_tree">
|
||||
<field name="model">lot.matching.lot</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">lot_matching_lot_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="matching_view_form">
|
||||
<field name="model">lot.matching.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">lot_matching_start_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="go_matching_view_form">
|
||||
<field name="model">lot.matching.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">lot_go_matching_start_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="matching_lot_view_tree">
|
||||
<field name="model">lot.matching.lot</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">lot_matching_lot_tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="matching_lot_view_tree2">
|
||||
<field name="model">lot.matching.lot</field>
|
||||
<field name="type">tree</field>
|
||||
@@ -184,16 +189,26 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="wiz_name">lot.matching</field>
|
||||
<field name="model">lot.report</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_matching_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">lot.report,-1</field>
|
||||
<field name="action" ref="act_matching"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="weighing_view_form">
|
||||
<field name="model">lot.weighing.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">lot_weighing_start_form</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_matching_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">lot.report,-1</field>
|
||||
<field name="action" ref="act_matching"/>
|
||||
</record>
|
||||
<record model="ir.action.wizard" id="act_go_matching">
|
||||
<field name="name">Go to matching</field>
|
||||
<field name="wiz_name">lot.go_matching</field>
|
||||
<field name="model">lot.report</field>
|
||||
</record>
|
||||
<record model="ir.action.keyword" id="act_go_matching_keyword">
|
||||
<field name="keyword">form_action</field>
|
||||
<field name="model">lot.report,-1</field>
|
||||
<field name="action" ref="act_go_matching"/>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="weighing_view_form">
|
||||
<field name="model">lot.weighing.start</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">lot_weighing_start_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="weighing_lot_view_tree">
|
||||
<field name="model">lot.weighing.lot</field>
|
||||
<field name="type">tree</field>
|
||||
|
||||
@@ -2722,6 +2722,69 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
||||
with self.assertRaises(UserError):
|
||||
lot_module.LotQt.match_lots([purchase_lot], [])
|
||||
|
||||
def test_go_matching_defaults_selected_open_lot_qts(self):
|
||||
'go to matching only preloads selected unmatched open lot.qt rows'
|
||||
purchase = Mock(id=10, party=Mock(id=20))
|
||||
sale = Mock(id=30, party=Mock(id=40))
|
||||
product = Mock(id=50)
|
||||
purchase_lot = Mock(
|
||||
id=101, line=Mock(purchase=purchase), sale_line=None,
|
||||
lot_type='virtual', lot_product=product)
|
||||
sale_lot = Mock(
|
||||
id=102, line=None, sale_line=Mock(sale=sale),
|
||||
lot_type='virtual', lot_product=product)
|
||||
matched_sale_lot = Mock(
|
||||
id=103, line=None, sale_line=Mock(sale=sale),
|
||||
lot_type='virtual', lot_product=product)
|
||||
lot_qts = {
|
||||
1: Mock(
|
||||
id=1, lot_p=purchase_lot, lot_s=None,
|
||||
lot_quantity=Decimal('100'),
|
||||
lot_shipment_in=None, lot_shipment_internal=None,
|
||||
lot_shipment_out=None),
|
||||
2: Mock(
|
||||
id=2, lot_p=None, lot_s=sale_lot,
|
||||
lot_quantity=Decimal('80'),
|
||||
lot_shipment_in=None, lot_shipment_internal=None,
|
||||
lot_shipment_out=None),
|
||||
3: Mock(
|
||||
id=3, lot_p=purchase_lot, lot_s=matched_sale_lot,
|
||||
lot_quantity=Decimal('20'),
|
||||
lot_shipment_in=None, lot_shipment_internal=None,
|
||||
lot_shipment_out=None),
|
||||
}
|
||||
|
||||
class LotQtMock:
|
||||
def __call__(self, _id):
|
||||
return lot_qts[_id]
|
||||
|
||||
pool = Mock()
|
||||
pool.get.side_effect = (
|
||||
lambda name: LotQtMock() if name == 'lot.qt' else Mock())
|
||||
transaction = Mock()
|
||||
transaction.context = {
|
||||
'active_ids': [10000001, 10000002, 10000003],
|
||||
}
|
||||
|
||||
with patch.object(lot_module, 'Pool', return_value=pool):
|
||||
with patch.object(
|
||||
lot_module, 'Transaction', return_value=transaction):
|
||||
result = lot_module.LotGoMatching().default_match([])
|
||||
|
||||
self.assertEqual(result['qt_type'], 'all')
|
||||
self.assertEqual(len(result['lot_p']), 1)
|
||||
self.assertEqual(len(result['lot_s']), 1)
|
||||
self.assertEqual(result['lot_p'][0]['lot_r_id'], 1)
|
||||
self.assertEqual(result['lot_p'][0]['lot_quantity'], Decimal('100'))
|
||||
self.assertEqual(result['lot_p'][0]['lot_cp'], 20)
|
||||
self.assertEqual(result['lot_s'][0]['lot_r_id'], 2)
|
||||
self.assertEqual(result['lot_s'][0]['lot_quantity'], Decimal('80'))
|
||||
self.assertEqual(result['lot_s'][0]['lot_cp'], 40)
|
||||
|
||||
def test_lot_context_group_defaults_to_all(self):
|
||||
'lots management opens without grouping by physical lot'
|
||||
self.assertEqual(lot_module.LotContext.default_group(), 'all')
|
||||
|
||||
def test_contract_detail_defaults_sale_locations_from_dropship_purchase(self):
|
||||
'create contracts copies supplier-to-customer locations from purchase to sale'
|
||||
supplier = Mock(id=1, type='supplier')
|
||||
|
||||
12
modules/purchase_trade/view/lot_go_matching_start_form.xml
Normal file
12
modules/purchase_trade/view/lot_go_matching_start_form.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<form col="8">
|
||||
<notebook colspan="8">
|
||||
<page string="Matching" col="8" id="matching">
|
||||
<field name="lot_p" colspan="8" mode="tree" view_ids="purchase_trade.matching_lot_view_tree"/>
|
||||
<label name="tot_p"/>
|
||||
<field name="tot_p"/>
|
||||
<field name="lot_s" colspan="8" mode="tree" view_ids="purchase_trade.matching_lot_view_tree2"/>
|
||||
<label name="tot_s"/>
|
||||
<field name="tot_s"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
Reference in New Issue
Block a user