mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-04 07:05:41 +00:00 
			
		
		
		
	cut back on modifications
This commit is contained in:
		
							
								
								
									
										25
									
								
								InvenTree/order/migrations/0065_auto_20220305_2209.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								InvenTree/order/migrations/0065_auto_20220305_2209.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
# Generated by Django 3.2.12 on 2022-03-05 22:09
 | 
			
		||||
 | 
			
		||||
from django.db import migrations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('order', '0064_auto_20220304_0004'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='salesorder',
 | 
			
		||||
            name='checksum',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='salesorder',
 | 
			
		||||
            name='sell_price',
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.RemoveField(
 | 
			
		||||
            model_name='salesorder',
 | 
			
		||||
            name='sell_price_currency',
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -5,7 +5,7 @@ Order model definitions
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import hashlib
 | 
			
		||||
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
from decimal import Decimal
 | 
			
		||||
 | 
			
		||||
@@ -614,75 +614,6 @@ class SalesOrder(Order):
 | 
			
		||||
 | 
			
		||||
        return query.exists()
 | 
			
		||||
 | 
			
		||||
    checksum = models.CharField(max_length=128, blank=True, verbose_name=_('order checksum'), help_text=_('Stored order checksum'))
 | 
			
		||||
 | 
			
		||||
    sell_price = InvenTreeModelMoneyField(
 | 
			
		||||
        max_digits=19,
 | 
			
		||||
        decimal_places=4,
 | 
			
		||||
        blank=True, null=True,
 | 
			
		||||
        verbose_name=_('Sell Price'),
 | 
			
		||||
        help_text=_('Price for this sale order'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def get_hash(self):
 | 
			
		||||
        """ Return a checksum hash for this sale order. """
 | 
			
		||||
 | 
			
		||||
        hash = hashlib.md5(str(self.id).encode())
 | 
			
		||||
 | 
			
		||||
        # hash own values
 | 
			
		||||
        hash.update(str(self.customer.id).encode())
 | 
			
		||||
        hash.update(str(self.customer_reference).encode())
 | 
			
		||||
        hash.update(str(self.target_date).encode())
 | 
			
		||||
        hash.update(str(self.reference).encode())
 | 
			
		||||
        hash.update(str(self.link).encode())
 | 
			
		||||
        hash.update(str(self.notes).encode())
 | 
			
		||||
        hash.update(str(self.sell_price).encode())
 | 
			
		||||
        hash.update(str(self.sell_price_currency).encode())
 | 
			
		||||
 | 
			
		||||
        # List *all* items
 | 
			
		||||
        items = self.lines.all()
 | 
			
		||||
        for item in items:
 | 
			
		||||
            hash.update(str(item.get_item_hash()).encode())
 | 
			
		||||
 | 
			
		||||
        return str(hash.digest())
 | 
			
		||||
 | 
			
		||||
    def is_valid(self):
 | 
			
		||||
        """ Check if the sale order is 'valid' - if the calculated checksum matches the stored value
 | 
			
		||||
        """
 | 
			
		||||
        return self.get_hash() == self.checksum or not self.sell_price
 | 
			
		||||
 | 
			
		||||
    @transaction.atomic
 | 
			
		||||
    def validate(self, user):
 | 
			
		||||
        """ Validate the sale order
 | 
			
		||||
        - Calculates and stores the hash for the sale order
 | 
			
		||||
        """
 | 
			
		||||
        self.checksum = self.get_hash()
 | 
			
		||||
        self.save()
 | 
			
		||||
 | 
			
		||||
    def get_total_price(self):
 | 
			
		||||
        """
 | 
			
		||||
        Calculates the total price of all order lines
 | 
			
		||||
        """
 | 
			
		||||
        target_currency = self.sell_price_currency if self.sell_price else currency_code_default()
 | 
			
		||||
        total = Money(0, target_currency)
 | 
			
		||||
 | 
			
		||||
        # order items
 | 
			
		||||
        total += sum([a.quantity * convert_money(a.sale_price, target_currency) for a in self.lines.all() if a.sale_price])
 | 
			
		||||
 | 
			
		||||
        # additional lines
 | 
			
		||||
        total += sum([a.quantity * convert_money(a.sale_price, target_currency) for a in self.additional_lines.all() if a.sale_price])
 | 
			
		||||
 | 
			
		||||
        # set decimal-places
 | 
			
		||||
        total.decimal_places = 4
 | 
			
		||||
        return total
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_price_total(self):
 | 
			
		||||
        """
 | 
			
		||||
        Returns true if the set sale price and the calculated total price are equal
 | 
			
		||||
        """
 | 
			
		||||
        return self.get_total_price() == self.sell_price
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def is_pending(self):
 | 
			
		||||
        return self.status == SalesOrderStatus.PENDING
 | 
			
		||||
 
 | 
			
		||||
@@ -515,21 +515,6 @@ class SalesOrderSerializer(ReferenceIndexingSerializerMixin, InvenTreeModelSeria
 | 
			
		||||
 | 
			
		||||
    reference = serializers.CharField(required=True)
 | 
			
		||||
 | 
			
		||||
    sell_price = InvenTreeMoneySerializer(
 | 
			
		||||
        max_digits=19,
 | 
			
		||||
        decimal_places=4,
 | 
			
		||||
        allow_null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sell_price_string = serializers.CharField(source='sell_price', read_only=True)
 | 
			
		||||
 | 
			
		||||
    sell_price_currency = serializers.ChoiceField(
 | 
			
		||||
        choices=currency_code_mappings(),
 | 
			
		||||
        help_text=_('Sell price currency'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    total_price_string = serializers.CharField(source='get_total_price', read_only=True)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = order.models.SalesOrder
 | 
			
		||||
 | 
			
		||||
@@ -550,11 +535,6 @@ class SalesOrderSerializer(ReferenceIndexingSerializerMixin, InvenTreeModelSeria
 | 
			
		||||
            'status_text',
 | 
			
		||||
            'shipment_date',
 | 
			
		||||
            'target_date',
 | 
			
		||||
            'sell_price',
 | 
			
		||||
            'sell_price_string',
 | 
			
		||||
            'sell_price_currency',
 | 
			
		||||
            'total_price_string',
 | 
			
		||||
            'is_valid',
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        read_only_fields = [
 | 
			
		||||
@@ -692,16 +672,6 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
 | 
			
		||||
        help_text=_('Sale price currency'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sale_price_converted = InvenTreeMoneySerializer(
 | 
			
		||||
        max_digits=19,
 | 
			
		||||
        decimal_places=4,
 | 
			
		||||
        allow_null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sale_price_converted_string = serializers.CharField(source='sale_price_converted', read_only=True)
 | 
			
		||||
 | 
			
		||||
    sale_price_converted_currency = serializers.CharField(read_only=True)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = order.models.SalesOrderLineItem
 | 
			
		||||
 | 
			
		||||
@@ -724,67 +694,6 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
 | 
			
		||||
            'target_date',
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    line_item = serializers.PrimaryKeyRelatedField(
 | 
			
		||||
        queryset=order.models.SalesOrderLineItem.objects.all(),
 | 
			
		||||
        many=False,
 | 
			
		||||
        allow_null=False,
 | 
			
		||||
        required=True,
 | 
			
		||||
        label=_('Stock Item'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def validate_line_item(self, line_item):
 | 
			
		||||
 | 
			
		||||
        order = self.context['order']
 | 
			
		||||
 | 
			
		||||
        # Ensure that the line item points to the correct order
 | 
			
		||||
        if line_item.order != order:
 | 
			
		||||
            raise ValidationError(_("Line item is not associated with this order"))
 | 
			
		||||
 | 
			
		||||
        return line_item
 | 
			
		||||
 | 
			
		||||
    stock_item = serializers.PrimaryKeyRelatedField(
 | 
			
		||||
        queryset=stock.models.StockItem.objects.all(),
 | 
			
		||||
        many=False,
 | 
			
		||||
        allow_null=False,
 | 
			
		||||
        required=True,
 | 
			
		||||
        label=_('Stock Item'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    quantity = serializers.DecimalField(
 | 
			
		||||
        max_digits=15,
 | 
			
		||||
        decimal_places=5,
 | 
			
		||||
        min_value=0,
 | 
			
		||||
        required=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def validate_quantity(self, quantity):
 | 
			
		||||
 | 
			
		||||
        if quantity <= 0:
 | 
			
		||||
            raise ValidationError(_("Quantity must be positive"))
 | 
			
		||||
 | 
			
		||||
        return quantity
 | 
			
		||||
 | 
			
		||||
    def validate(self, data):
 | 
			
		||||
 | 
			
		||||
        data = super().validate(data)
 | 
			
		||||
 | 
			
		||||
        stock_item = data['stock_item']
 | 
			
		||||
        quantity = data['quantity']
 | 
			
		||||
 | 
			
		||||
        if stock_item.serialized and quantity != 1:
 | 
			
		||||
            raise ValidationError({
 | 
			
		||||
                'quantity': _("Quantity must be 1 for serialized stock item"),
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        q = normalize(stock_item.unallocated_quantity())
 | 
			
		||||
 | 
			
		||||
        if quantity > q:
 | 
			
		||||
            raise ValidationError({
 | 
			
		||||
                'quantity': _(f"Available quantity ({q}) exceeded")
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
        return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SalesOrderShipmentSerializer(InvenTreeModelSerializer):
 | 
			
		||||
    """
 | 
			
		||||
@@ -1206,8 +1115,6 @@ class SOAdditionalLineItemSerializer(InvenTreeModelSerializer):
 | 
			
		||||
    quantity = serializers.FloatField()
 | 
			
		||||
 | 
			
		||||
    sale_price = InvenTreeMoneySerializer(
 | 
			
		||||
        max_digits=19,
 | 
			
		||||
        decimal_places=4,
 | 
			
		||||
        allow_null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
@@ -1218,15 +1125,6 @@ class SOAdditionalLineItemSerializer(InvenTreeModelSerializer):
 | 
			
		||||
        help_text=_('Sale price currency'),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sale_price_converted = InvenTreeMoneySerializer(
 | 
			
		||||
        max_digits=19,
 | 
			
		||||
        decimal_places=4,
 | 
			
		||||
        allow_null=True
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    sale_price_converted_string = serializers.CharField(source='sale_price_converted', read_only=True)
 | 
			
		||||
 | 
			
		||||
    sale_price_converted_currency = serializers.CharField(read_only=True)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = order.models.SalesOrderAdditionalLineItem
 | 
			
		||||
@@ -1242,9 +1140,6 @@ class SOAdditionalLineItemSerializer(InvenTreeModelSerializer):
 | 
			
		||||
            'sale_price',
 | 
			
		||||
            'sale_price_currency',
 | 
			
		||||
            'sale_price_string',
 | 
			
		||||
            'sale_price_converted',
 | 
			
		||||
            'sale_price_converted_currency',
 | 
			
		||||
            'sale_price_converted_string',
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -183,16 +183,6 @@ src="{% static 'img/blank_image.png' %}"
 | 
			
		||||
        <td>{{ order.responsible }}</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% if order.sell_price %}
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td><span class='fas fa-users'></span></td>
 | 
			
		||||
        <td>{% trans "Sell Price" %}</td>
 | 
			
		||||
        <td id='sales-order-sell-price'>
 | 
			
		||||
            {% trans "Loading..." %}
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
</table>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
@@ -212,8 +202,6 @@ $("#edit-order").click(function() {
 | 
			
		||||
            {% endif %}
 | 
			
		||||
            customer_reference: {},
 | 
			
		||||
            description: {},
 | 
			
		||||
            sell_price: {},
 | 
			
		||||
            sell_price_currency: {},
 | 
			
		||||
            target_date: {
 | 
			
		||||
                icon: 'fa-calendar-alt',
 | 
			
		||||
            },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
{% extends "modal_form.html" %}
 | 
			
		||||
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
{% load inventree_extras %}
 | 
			
		||||
 | 
			
		||||
{% block pre_form_content %}
 | 
			
		||||
{% blocktrans %}Confirm that the order is valid for:<br><i>{{ order }}</i> with a price of {{price}} (calculated price is {{price_calc}}, difference <span class="text-{{ diff_symbol }}">{{ price_diff }}</span>){% endblocktrans %}
 | 
			
		||||
 | 
			
		||||
{% endblock %} 
 | 
			
		||||
@@ -142,6 +142,7 @@ class RuleSet(models.Model):
 | 
			
		||||
            'order_salesorderallocation',
 | 
			
		||||
            'order_salesorderattachment',
 | 
			
		||||
            'order_salesorderlineitem',
 | 
			
		||||
            'order_salesorderadditionallineitem',
 | 
			
		||||
            'order_salesordershipment',
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user