Skip to content

Commit

Permalink
[Issue #174] changed product to product type. draft the product costs…
Browse files Browse the repository at this point in the history
… draft the product
  • Loading branch information
scaphilo committed Sep 10, 2018
1 parent 0789053 commit c975630
Show file tree
Hide file tree
Showing 15 changed files with 200 additions and 143 deletions.
4 changes: 2 additions & 2 deletions koalixcrm/crm/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from koalixcrm.crm.documents.contract import Contract, OptionContract
from koalixcrm.crm.product.tax import Tax, OptionTax
from koalixcrm.crm.product.unit import Unit, OptionUnit
from koalixcrm.crm.product.product import Product, OptionProduct
from koalixcrm.crm.product.product_type import ProductType, OptionProductType
from koalixcrm.crm.product.currency import Currency, OptionCurrency
from koalixcrm.crm.contact.customer import Customer, OptionCustomer
from koalixcrm.crm.contact.supplier import Supplier, OptionSupplier
Expand Down Expand Up @@ -49,7 +49,7 @@
admin.site.register(Unit, OptionUnit)
admin.site.register(Currency, OptionCurrency)
admin.site.register(Tax, OptionTax)
admin.site.register(Product, OptionProduct)
admin.site.register(ProductType, OptionProductType)

admin.site.register(Task, OptionTask)
admin.site.register(TaskLinkType, OptionTaskLinkType)
Expand Down
4 changes: 2 additions & 2 deletions koalixcrm/crm/documents/sales_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from koalixcrm.crm.contact.postal_address import PostalAddress
from koalixcrm.crm.documents.sales_document_position import SalesDocumentPosition, SalesDocumentInlinePosition
from koalixcrm.djangoUserExtension.models import TextParagraphInDocumentTemplate, UserExtension
from koalixcrm.crm.product.product import Product
from koalixcrm.crm.product.product_type import ProductType
from koalixcrm.crm.exceptions import TemplateSetMissingInContract
import koalixcrm.crm.documents.calculations
from koalixcrm.crm.documents.pdf_export import PDFExport
Expand Down Expand Up @@ -350,7 +350,7 @@ def after_saving_model_and_related_inlines(self, request, obj):
try:
koalixcrm.crm.documents.calculations.Calculations.calculate_document_price(obj, date.today())
self.message_user(request, "Successfully calculated Prices")
except Product.NoPriceFound as e:
except ProductType.NoPriceFound as e:
self.message_user(request, "Unsuccessful in updating the Prices " + e.__str__(), level=messages.ERROR)
return obj

Expand Down
4 changes: 2 additions & 2 deletions koalixcrm/crm/documents/sales_document_position.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ class Meta:
@staticmethod
def add_positions(position_class, object_to_create_pdf):
from koalixcrm.crm.product.unit import Unit
from koalixcrm.crm.product.product import Product
from koalixcrm.crm.product.product_type import ProductType
objects = list(position_class.objects.filter(sales_document=object_to_create_pdf.id))
for position in list(position_class.objects.filter(sales_document=object_to_create_pdf.id)):
objects += list(Position.objects.filter(id=position.id))
objects += list(Product.objects.filter(id=position.product.id))
objects += list(ProductType.objects.filter(id=position.product.id))
objects += list(Unit.objects.filter(id=position.unit.id))
return objects

Expand Down
4 changes: 2 additions & 2 deletions koalixcrm/crm/factories/factory_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import factory
import datetime
from koalixcrm.crm.models import Product
from koalixcrm.crm.models import ProductType
from koalixcrm.crm.factories.factory_unit import StandardUnitFactory
from koalixcrm.crm.factories.factory_user import StaffUserFactory
from koalixcrm.accounting.factories.factory_product_category import StandardProductCategoryFactory
Expand All @@ -11,7 +11,7 @@

class StandardProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = Product
model = ProductType
django_get_or_create = ('product_number',)

title = "This is a test Product"
Expand Down
2 changes: 1 addition & 1 deletion koalixcrm/crm/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

from koalixcrm.crm.product.currency import *
from koalixcrm.crm.product.price import *
from koalixcrm.crm.product.product import *
from koalixcrm.crm.product.product_type import *
from koalixcrm.crm.product.customer_group_transform import *
from koalixcrm.crm.product.unit_transform import *
from koalixcrm.crm.product.tax import *
Expand Down
4 changes: 2 additions & 2 deletions koalixcrm/crm/product/price.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@


class Price(models.Model):
product = models.ForeignKey("Product",
verbose_name=_("Product"))
product_type = models.ForeignKey("Product Type",
verbose_name=_("Product Type"))
unit = models.ForeignKey(Unit,
blank=False,
verbose_name=_("Unit"))
Expand Down
120 changes: 5 additions & 115 deletions koalixcrm/crm/product/product.py
Original file line number Diff line number Diff line change
@@ -1,122 +1,12 @@
# -*- coding: utf-8 -*-
from django.contrib import admin
from django.db import models
from django.utils.translation import ugettext as _

from koalixcrm.crm.product.price import Price
from koalixcrm.crm.product.price import ProductPrice
from koalixcrm.crm.product.unit_transform import ProductUnitTransform
from koalixcrm.crm.product.customer_group_transform import ProductCustomerGroupTransform
from koalixcrm.crm.product.currency_transform import ProductCurrencyTransform


class Product(models.Model):
description = models.TextField(verbose_name=_("Description"),
null=True,
blank=True)
title = models.CharField(verbose_name=_("Title"),
max_length=200)
product_number = models.IntegerField(verbose_name=_("Product Number"))
default_unit = models.ForeignKey("Unit", verbose_name=_("Unit"))
date_of_creation = models.DateTimeField(verbose_name=_("Created at"),
auto_now_add=True)
last_modification = models.DateTimeField(verbose_name=_("Last modified"),
auto_now=True)
last_modified_by = models.ForeignKey('auth.User',
limit_choices_to={'is_staff': True},
verbose_name=_("Last modified by"),
null=True,
blank="True")
tax = models.ForeignKey("Tax",
blank=False)
accounting_product_categorie = models.ForeignKey('accounting.ProductCategorie',
verbose_name=_("Accounting Product Categorie"),
null=True,
blank="True")

def get_price(self, date, unit, customer, currency):
"""The function searches for a valid price and returns the price of the product as a decimal value.
Args:
koalixcrm.crm.contact.customer customer
koalixcrm.crm.product.unit unit
koalixcrm.crm.product.currency currency
datetime.date date
Returns:
when a match is found: dict customer_group_factors name=customer_group, value=factor
when no match is found: customer_group_factors is None
Raises:
In case the algorithm does not find a valid product price, the function raises a
NoPriceFound Exception"""
prices = Price.objects.filter(product=self.id)
valid_prices = list()
for price in list(prices):
currency_factor = price.get_currency_transform_factor(price)
unit_factor = price.get_unit_transform_factor(price)
group_factors = price.get_customer_group_transform_factor(customer)
date_in_range = price.is_date_in_range(date)
if currency_factor != 0 and \
group_factors != 0 and \
date_in_range and \
unit_factor != 0:

transformed_price = price.price*group_factors*unit_factor*unit_factor
valid_prices.append(transformed_price)
if len(valid_prices) > 0:
lowest_price = valid_prices[0]
for price in valid_prices:
if price < lowest_price:
lowest_price = price
return lowest_price
else:
raise Product.NoPriceFound(customer, unit, date, currency, self)

def get_tax_rate(self):
return self.tax.get_tax_rate()

def __str__(self):
return str(self.product_number) + ' ' + self.title.__str__()

class Meta:
app_label = "crm"
verbose_name = _('Product')
verbose_name_plural = _('Products')

class NoPriceFound(Exception):
def __init__(self, customer, unit, date, currency, product):
self.customer = customer
self.unit = unit
self.date = date
self.product = product
self.currency = currency
return

def __str__(self):
return _("There is no Price for this product") + ": " + self.product.__str__() + _(
"that matches the date") + ": " + self.date.__str__() + " ," + _(
"customer") + ": " + self.customer.__str__() + " ," + _(
"currency") + ": " + self.currency.__str__() + _(" and unit") + ":" + self.unit.__str__()

identifier = models.CharField(verbose_name=_("Product Number"),
max_lenghth=200,
null=True,
blank=True)
product_type = models.ForeignKey("ProductType", verbose_name=_("Product Type"))

class OptionProduct(admin.ModelAdmin):
list_display = ('product_number',
'title',
'default_unit',
'tax',
'accounting_product_categorie')
list_display_links = ('product_number',)
fieldsets = (
(_('Basics'), {
'fields': ('product_number',
'title',
'description',
'default_unit',
'tax',
'accounting_product_categorie')
}),)
inlines = [ProductPrice,
ProductUnitTransform,
ProductCurrencyTransform,
ProductCustomerGroupTransform]
33 changes: 33 additions & 0 deletions koalixcrm/crm/product/product_costs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-

from django.db import models
from django.contrib import admin
from django.utils.translation import ugettext as _
from koalixcrm.crm.product.currency import Currency
from koalixcrm.crm.product.unit import Unit
from koalixcrm.crm.contact.customer_group import CustomerGroup
from koalixcrm.crm.product.unit_transform import UnitTransform
from koalixcrm.crm.product.customer_group_transform import CustomerGroupTransform
from koalixcrm.crm.product.currency_transform import CurrencyTransform


class Cost(models.Model):
product = models.ForeignKey("Product",
verbose_name=_("Product"))
unit = models.ForeignKey(Unit,
blank=False,
verbose_name=_("Unit"))
currency = models.ForeignKey(Currency,
verbose_name='Currency',
blank=False,
null=False)
customer_group = models.ForeignKey(CustomerGroup,
verbose_name=_("Customer Group"),
blank=True,
null=True)
cost = models.DecimalField(max_digits=17,
decimal_places=2,
verbose_name=_("Cost Per Unit"))
date = models.DateField(verbose_name=_("Cost date"),
blank=True,
null=True)
134 changes: 134 additions & 0 deletions koalixcrm/crm/product/product_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*-
from django.contrib import admin
from django.db import models
from django.utils.translation import ugettext as _

from koalixcrm.crm.product.price import Price
from koalixcrm.crm.product.price import ProductPrice
from koalixcrm.crm.product.unit_transform import ProductUnitTransform
from koalixcrm.crm.product.customer_group_transform import ProductCustomerGroupTransform
from koalixcrm.crm.product.currency_transform import ProductCurrencyTransform


class ProductType(models.Model):
description = models.TextField(verbose_name=_("Description"),
null=True,
blank=True)
title = models.CharField(verbose_name=_("Title"),
max_length=200)
product_identifier = models.CharField(verbose_name=_("Product Number"),
max_lenghth=200,
null=True,
blank=True)
default_unit = models.ForeignKey("Unit", verbose_name=_("Unit"))
tax = models.ForeignKey("Tax",
blank=False,
null=False)
product_category = models.ForeignKey("ProductCategory",
blank=False,
null=False)
product_status = models.ForeignKey("ProductStatus",
blank=False,
null=False)
last_status_change = models.DateField(verbose_name=_("Last Status Change"),
blank=True,
null=False)
last_modification = models.DateTimeField(verbose_name=_("Last modified"),
auto_now=True)
last_modified_by = models.ForeignKey('auth.User',
limit_choices_to={'is_staff': True},
verbose_name=_("Last modified by"),
null=True,
blank=True)
date_of_creation = models.DateTimeField(verbose_name=_("Created at"),
auto_now_add=True)
accounting_product_categorie = models.ForeignKey('accounting.ProductCategorie',
verbose_name=_("Accounting Product Categorie"),
null=True,
blank="True")

def get_price(self, date, unit, customer, currency):
"""The function searches for a valid price and returns the price of the product as a decimal value.
Args:
koalixcrm.crm.contact.customer customer
koalixcrm.crm.product.unit unit
koalixcrm.crm.product.currency currency
datetime.date date
Returns:
when a match is found: dict customer_group_factors name=customer_group, value=factor
when no match is found: customer_group_factors is None
Raises:
In case the algorithm does not find a valid product price, the function raises a
NoPriceFound Exception"""
prices = Price.objects.filter(product_type=self.id)
valid_prices = list()
for price in list(prices):
currency_factor = price.get_currency_transform_factor(price)
unit_factor = price.get_unit_transform_factor(price)
group_factors = price.get_customer_group_transform_factor(customer)
date_in_range = price.is_date_in_range(date)
if currency_factor != 0 and \
group_factors != 0 and \
date_in_range and \
unit_factor != 0:

transformed_price = price.price*group_factors*unit_factor*unit_factor
valid_prices.append(transformed_price)
if len(valid_prices) > 0:
lowest_price = valid_prices[0]
for price in valid_prices:
if price < lowest_price:
lowest_price = price
return lowest_price
else:
raise ProductType.NoPriceFound(customer, unit, date, currency, self)

def get_tax_rate(self):
return self.tax.get_tax_rate()

def __str__(self):
return str(self.product_identifier) + ' ' + self.title.__str__()

class Meta:
app_label = "crm"
verbose_name = _('Product Type')
verbose_name_plural = _('Product Types')

class NoPriceFound(Exception):
def __init__(self, customer, unit, date, currency, product):
self.customer = customer
self.unit = unit
self.date = date
self.product = product
self.currency = currency
return

def __str__(self):
return _("There is no Price for this product type") + ": " + self.product.__str__() + _(
"that matches the date") + ": " + self.date.__str__() + " ," + _(
"customer") + ": " + self.customer.__str__() + " ," + _(
"currency") + ": " + self.currency.__str__() + _(" and unit") + ":" + self.unit.__str__()


class OptionProductType(admin.ModelAdmin):
list_display = ('product_type_number',
'title',
'default_unit',
'tax',
'accounting_product_categorie')
list_display_links = ('product_number',)
fieldsets = (
(_('Basics'), {
'title',
'description',
'default_unit',
'tax',
'accounting_product_categorie'
}),)
inlines = [ProductPrice,
ProductUnitTransform,
ProductCurrencyTransform,
ProductCustomerGroupTransform]
Loading

0 comments on commit c975630

Please sign in to comment.