Purchase form

This commit is contained in:
2026-07-25 10:39:50 +02:00
parent 64390eaecb
commit 264ff534cf
3 changed files with 102 additions and 25 deletions

View File

@@ -1606,9 +1606,6 @@ class Log(ResourceAccessMixin, ModelSQL, ModelView):
return json.dumps(value, sort_keys=True, ensure_ascii=False)
if value in (None, ''):
return ''
if isinstance(value, str) and re.match(r'^-?\d+(\.\d+)?$', value):
value = value.rstrip('0').rstrip('.')
return value or '0'
return str(value)
@staticmethod
@@ -1619,14 +1616,27 @@ class Log(ResourceAccessMixin, ModelSQL, ModelView):
return label[:-1]
return label
def _nested_record_label(self, field, field_label, record_id):
record_label = self._singular_label(field_label)
if not self.resource:
return '%s %s' % (record_label, record_id)
records = list(getattr(self.resource, field.name, None) or [])
line_records = [
record for record in records
if getattr(record, 'type', 'line') == 'line']
ordered_records = line_records or records
for index, record in enumerate(ordered_records, 1):
if str(getattr(record, 'id', '')) == str(record_id):
return '%s %s' % (record_label, index)
return '%s %s' % (record_label, record_id)
def _format_nested_change_summary(
self, field_label, target_model, old_value, new_value):
self, field, field_label, target_model, old_value, new_value):
pool = Pool()
Field = pool.get('ir.model.field')
lines = []
if not isinstance(old_value, dict) or not isinstance(new_value, dict):
return lines
record_label = self._singular_label(field_label)
def record_sort_key(value):
try:
return int(value)
@@ -1645,14 +1655,63 @@ class Log(ResourceAccessMixin, ModelSQL, ModelView):
if child_old == child_new:
continue
child_label = Field.get_name(target_model, child_field)
lines.append('%s %s %s %s => %s' % (
record_label,
record_id,
lines.append('%s %s %s => %s' % (
self._nested_record_label(
field, field_label, record_id),
child_label,
self._format_change_value(child_old),
self._format_change_value(child_new)))
return lines
@staticmethod
def _iter_change_commands(value):
if not isinstance(value, list):
return
for item in value:
if isinstance(item, list) and item and isinstance(item[0], str):
command = item[0]
if len(item) >= 3:
yield command, item[1], item[2]
elif len(item) >= 2:
yield command, item[1], None
if value and all(isinstance(item, list) for item in value):
return
index = 0
while index < len(value):
command = value[index]
if not isinstance(command, str):
index += 1
continue
if command == 'write':
if index + 2 >= len(value):
break
yield command, value[index + 1], value[index + 2]
index += 3
continue
if index + 1 >= len(value):
break
yield command, value[index + 1], None
index += 2
def _format_command_change_summary(
self, field, field_label, target_model, new_value):
pool = Pool()
Field = pool.get('ir.model.field')
lines = []
for command, record_ids, values in self._iter_change_commands(
new_value) or []:
if command != 'write' or not isinstance(values, dict):
continue
for record_id in record_ids:
for child_field, child_value in sorted(values.items()):
child_label = Field.get_name(target_model, child_field)
lines.append('%s %s => %s' % (
self._nested_record_label(
field, field_label, record_id),
child_label,
self._format_change_value(child_value)))
return lines
def get_change_summary(self, name):
if self.event != 'write':
return ''
@@ -1673,14 +1732,21 @@ class Log(ResourceAccessMixin, ModelSQL, ModelView):
field_label = Field.get_name(model, field_name)
else:
field_label = field_name
field = getattr(self.resource.__class__, field_name, None)
field = (
getattr(self.resource.__class__, field_name, None)
if self.resource else None)
if field and hasattr(field, 'get_target'):
target_model = field.get_target().__name__
nested_lines = self._format_nested_change_summary(
field_label, target_model, old_value, new_value)
field, field_label, target_model, old_value, new_value)
if nested_lines:
lines.extend(nested_lines)
continue
command_lines = self._format_command_change_summary(
field, field_label, target_model, new_value)
if command_lines:
lines.extend(command_lines)
continue
lines.append('%s: %s -> %s' % (
field_label,
self._format_change_value(old_value),

View File

@@ -3,11 +3,12 @@
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/form/group[@id='hd'][2]" position="replace"/>
<xpath expr="/form/group[@id='buttons']" position="replace"/>
<xpath expr="/form/field[@name='party_lang']" position="before">
<field name="allow_modification_after_validation" invisible="1"/>
</xpath>
<xpath expr="/form/group[@id='hd'][1]" position="replace">
<group id="purchase_header_summary" colspan="6" col="10"
<group id="purchase_header_summary" colspan="5" col="10"
panel="summary" xalign="0" yalign="0"
col_widths="min-content,2fr,min-content,130px,min-content,1.2fr,min-content,130px,min-content,1fr">
<label name="party"/>
@@ -21,6 +22,18 @@ this repository contains the full copyright notices and license terms. -->
<label name="currency"/>
<field name="currency"/>
</group>
<group id="purchase_header_buttons" col="-1" colspan="1"
xalign="1" yalign="0">
<button name="cancel" icon="tryton-cancel"/>
<button name="draft"/>
<button name="modify_header" icon="tryton-launch"/>
<button name="quote" icon="tryton-forward"/>
<button name="handle_invoice_exception" icon="tryton-forward"/>
<button name="handle_shipment_exception" icon="tryton-forward"/>
<button name="confirm" icon="tryton-ok"/>
<button name="process" invisible="1"/>
<button name="manual_invoice" icon="tryton-forward"/>
</group>
<group id="purchase_header_visuals" colspan="6" col="4"
string="Purchase summary" icon="tryton-dashboard"

View File

@@ -56,9 +56,9 @@ this repository contains the full copyright notices and license terms. -->
<field name="unit"/>
</group>
<group id="coffee_packing" string="Packing &amp; Tolerance"
colspan="1" col="4" panel="card" icon="tryton-archive"
colspan="1" col="6" panel="card" icon="tryton-archive"
xalign="0" yalign="0"
col_widths="min-content,1fr,min-content,1fr">
col_widths="min-content,1fr,min-content,1fr,min-content,1fr">
<label name="coffee_packing_count"/>
<field name="coffee_packing_count" width="120" xexpand="0" xfill="0"/>
<label name="coffee_packing_unit"/>
@@ -68,20 +68,18 @@ this repository contains the full copyright notices and license terms. -->
<field name="inherit_tol"/>
<label name="inherit_cer"/>
<field name="inherit_cer"/>
<newline/>
<label name="certif"/>
<field name="certif" colspan="3"/>
<field name="certif"/>
<newline/>
<label name="tol_min"/>
<field name="tol_min"/>
<label name="tol_max"/>
<field name="tol_max"/>
<newline/>
<label name="tolerance_used"/>
<label name="tolerance_used" string="Tol. used:"/>
<field name="tolerance_used" widget="tolerance_gauge"
min_field="tolerance_min" max_field="tolerance_max"
width="180" xexpand="0" xfill="0" xalign="0" colspan="3"/>
<newline/>
width="180" xexpand="0" xfill="0" xalign="0"/>
<label name="tol_min_v"/>
<field name="tol_min_v"/>
<label name="tol_max_v"/>
@@ -107,13 +105,15 @@ this repository contains the full copyright notices and license terms. -->
<field name="delivery_date_edit" xexpand="0" xfill="0" xalign="0"/>
</group>
<group id="pricing_amounts" string="Pricing &amp; Amounts"
colspan="1" col="4" panel="card" icon="tryton-public"
colspan="1" col="6" panel="card" icon="tryton-public"
xalign="0" yalign="0"
col_widths="min-content,1fr,min-content,1fr">
col_widths="min-content,1fr,min-content,1fr,min-content,min-content">
<label name="price_type"/>
<field name="price_type"/>
<label name="unit_price"/>
<field name="unit_price" width="150" xexpand="0" xfill="0"/>
<label name="enable_linked_currency"/>
<field name="enable_linked_currency" xexpand="0" xfill="0"/>
<newline/>
<label name="premium"/>
<field name="premium" width="120" xexpand="0" xfill="0"/>
@@ -121,10 +121,8 @@ this repository contains the full copyright notices and license terms. -->
<field name="amount" width="160" xexpand="0" xfill="0"/>
<newline/>
<label name="progress"/>
<field name="progress" widget="progressbar" colspan="3"/>
<field name="progress" widget="progressbar" colspan="5"/>
<newline/>
<label name="enable_linked_currency"/>
<field name="enable_linked_currency" xexpand="0" xfill="0"/>
<label name="linked_currency"/>
<field name="linked_currency"/>
<newline/>
@@ -146,9 +144,9 @@ this repository contains the full copyright notices and license terms. -->
colspan="12" col="1" panel="card" icon="tryton-list"
xalign="0" yalign="0"
col_widths="1fr">
<button name="apply_default_fees" icon="tryton-launch"/>
<field name="fees" colspan="1" mode="tree,form"
<field name="fees" colspan="1" mode="tree,form" height="180"
view_ids="purchase_trade.fee_view_tree_sequence,purchase_trade.fee_view_form"/>
<button name="apply_default_fees" icon="tryton-launch"/>
</group>
<group id="attributes_description" string="Description"
colspan="12" col="1" panel="card" icon="tryton-note"