From cd5e1cd6483455aeb76754736181afd078125d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B0=D0=BB=D0=B5=D1=80?= <101361201+DarkSteelD@users.noreply.github.com> Date: Wed, 8 Jan 2025 19:19:40 +0300 Subject: [PATCH] feat addded fully task 3 --- .gitignore | 1 + inventory/__pycache__/models.cpython-310.pyc | Bin 7147 -> 6357 bytes ...roduct_alter_inventory_product_and_more.py | 33 ++++++++++++++++++ logs.log | 25 +++++++++++++ pricing/models.py | 22 +++++++++++- settings/__pycache__/base.cpython-310.pyc | Bin 1553 -> 1866 bytes 6 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 inventory/migrations/0003_alter_stockoperation_product_alter_inventory_product_and_more.py diff --git a/.gitignore b/.gitignore index ebd7ddf..bb04232 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.pyc __pycache__/* inventory/migrations/__pycache__/0001_initial.cpython-310.pyc +*.log \ No newline at end of file diff --git a/inventory/__pycache__/models.cpython-310.pyc b/inventory/__pycache__/models.cpython-310.pyc index a87835cac4db81ee7ffb9b0b17f835dd30010887..b9b8b024547fedc9d59ad440949bdb1857b95391 100644 GIT binary patch delta 2018 zcma)7O>7%g5cYFo@7lZTpS2x3v6I+I8i+y?5i3m)0!ou6l$6#aEouysal9MH#6Rit z`j7|_0u>zSq1C7tBq|U>h#M$WDu)UoDskON<>C{^2E>UAw=lCdO@g!)mUi^sH#5&O z-+cS_kLh2Z_0<%`>%iYjpS@T7B7V!4VCJpS!5z(^b(Gx|AuBM)f6&8_JaYAQe#5u~B_#pZI#MhK&~YW1KnnhHqH(kBK&DnN8KqivJeR8*JeRvTB7x93 zwG%;qQ=ZccrAod$U((B3R$8w$czG+w^M>A(&sPn-sPmRfsnn{*I{GN2&U-MK$4;7V z+6ri*_|$0*qQl1mOlGpv!V3sJ{=w%F1q9(IrP*0+l*?Q~4;SH~FvvXcw=kyC0ZrFx zIbYr2L*$fTN?i0d-HmGLT0_U}$Kq-CaLe88|_o|9+PQ~*u8M}hdk~5BGJGyMt zc)qA#s1@=jC+p$I8iFx7dbXdktWkFwTbsK5;L;fQ96s&AiOlE1(K&eQ{)|FfkFlxMZ1&Z4|{zJQG#=~O=6 z4TaKpc&j6Lr1U>MPWuTmwzHv@=3&COmmH)xQduK_#=K+xXx`i3HNQ3QoA=DSJP1zz z%aWx+OH)H|(SNm%n6sV88}PtC9681~1zRKUAxy&1djUz(6_Jq!1Qqxtb zX?mF_X)PA=oB2X1Wo+4#JBxvD?j_X~#-?C9^dbww51};POMixjq!x=9fih2oSDsAe zCO~*tIz}Zt2&cwJDceov44DiW(rHsHx24}w!zFU0AQYLk=X?QU3VTLmiE90&tM^}~ zfA2~n(^52p#lIDu4*TgWQb<$K^tF7WY+(IgN9#|n{{xtb^)DQ&9}mc?nWgiy=W>@< zGUsx$uUx|Qa$6qsAOGpglJyEXl5i)sX5Yvaj4@!K`#UW7VfXDpOQK7ZXm@kmfEzuj z^vUAv3n7BJbzTa7>*=#EB#VI`K_VV!D$K;6pUlQKTi>djR^mFn%3I@>pz2nyP1kFd ry66kR>B_{b<&*e8;OK6)R^4zv-V>IcYAE1UW2&NhRY?`qV3+z230;@{ delta 2694 zcma)7-ES0C6yLiaGqbZZv$NA}cctxaKcKeChkQ%WMk!Ffgr<~WCzxf~nYIht-FkN> zraVxJXf)a&UWkb%B8iEb_)skk6{W=Z2QX`b59^chiO7S|#3u}%GhOZ0bQ?O^lY4*X z+;e~D!6+{MPN5s$o z(khSwP@NG4Bw9hjfYciefHYJP)rcMSbj9B%o7hd?Q|zo9o*;(b@J)Gj&h(x38wB{{ zj(2w)a)&QC<=26~s~7)6f)$&PdqRXA#9_!&M3*WW!BC9wluwrp)reg5=!&7i^>t;w zj}{C&W8Ht`@q0Y>8ule=l1dkxdFN|qx^&)|W@XYeVXuOeJJ(=8@60(jK{xN*aOS{n z*7>&duKgscua_?10q3?e-QwJ-VSDNRCa|?z@xX`ZWd+lLEHL|p zKX2!9wt@~mf!l66-#N3T^QCtdd|pLfKw+-*CelE%t{#XYc*$E5iFGxTtA#LNw)a@ip> zWu(W8I)ADsP00$FwA(LKOw_tVM z*xy2I*Fw$kTE8_uwnF!90h_JxtJFv!O2F;8El{H$w(Owz7xvHqwTFsYFQDi{ft^|w za+T&^m`X=bkzl_@dTJ-V7i>~9yS0Ag`axauzp1`e*8-{jxvme$uZ?bxwxh4rcnNQq zLuor_!ApHDT3ng`IVRL6d#m_^16}Lu-`}$*H89w>C)Km>2&|7T^zd?VxleTvFJHs* z^+UA-IR-Xk?2r1dfbgdcSKHkl?Z<<)hW%UYM67l5QgXG4V1lXZFTti`iP}VTFucGX z#2QJ23Gtora^NMmecXcK(5E;X=@w?k+q#$emsb{^gMPDfW;X%5BEDhC6D68YQ&drl OYqBP4Ax+RC4cb5Bjf!*t diff --git a/inventory/migrations/0003_alter_stockoperation_product_alter_inventory_product_and_more.py b/inventory/migrations/0003_alter_stockoperation_product_alter_inventory_product_and_more.py new file mode 100644 index 0000000..a8ce40c --- /dev/null +++ b/inventory/migrations/0003_alter_stockoperation_product_alter_inventory_product_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 5.1.4 on 2025-01-08 16:17 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('inventory', '0002_contractor_position_truck_employee_supplycontract'), + ('product_directory', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='stockoperation', + name='product', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='product_directory.product', verbose_name='Товар'), + ), + migrations.AlterField( + model_name='inventory', + name='product', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='product_directory.product', verbose_name='Товар'), + ), + migrations.AlterField( + model_name='pricelist', + name='product', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='product_directory.product', verbose_name='Товар'), + ), + migrations.DeleteModel( + name='Product', + ), + ] diff --git a/logs.log b/logs.log index 92ab0b8..1fcc9e7 100644 --- a/logs.log +++ b/logs.log @@ -133,3 +133,28 @@ Watching for file changes with StatReloader "GET /admin/jsi18n/ HTTP/1.1" 200 3342 "GET /admin/warehouse/stockoperation/statistics/ HTTP/1.1" 200 28103 "GET /admin/warehouse/stockoperation/ HTTP/1.1" 200 15416 +Watching for file changes with StatReloader +Not Found: / +"GET / HTTP/1.1" 404 2782 +"GET /api/pricing/ HTTP/1.1" 200 11324 +"GET /static/rest_framework/css/bootstrap.min.css HTTP/1.1" 304 0 +"GET /static/rest_framework/css/prettify.css HTTP/1.1" 304 0 +"GET /static/rest_framework/css/bootstrap-tweaks.css HTTP/1.1" 304 0 +"GET /static/rest_framework/js/csrf.js HTTP/1.1" 304 0 +"GET /static/rest_framework/js/jquery-3.7.1.min.js HTTP/1.1" 304 0 +"GET /static/rest_framework/css/default.css HTTP/1.1" 304 0 +"GET /static/rest_framework/js/bootstrap.min.js HTTP/1.1" 304 0 +"GET /static/rest_framework/js/ajax-form.js HTTP/1.1" 304 0 +"GET /static/rest_framework/js/prettify-min.js HTTP/1.1" 304 0 +"GET /static/rest_framework/js/default.js HTTP/1.1" 304 0 +"GET /static/rest_framework/js/load-ajax-form.js HTTP/1.1" 304 0 +"GET /static/rest_framework/img/grid.png HTTP/1.1" 304 0 +"GET /api/pricing/swagger/ HTTP/1.1" 200 2245 +"GET /static/drf-yasg/style.css HTTP/1.1" 304 0 +"GET /static/drf-yasg/swagger-ui-dist/swagger-ui.css HTTP/1.1" 304 0 +"GET /static/drf-yasg/swagger-ui-dist/swagger-ui-standalone-preset.js HTTP/1.1" 304 0 +"GET /static/drf-yasg/immutable.min.js HTTP/1.1" 304 0 +"GET /static/drf-yasg/swagger-ui-dist/swagger-ui-bundle.js HTTP/1.1" 304 0 +"GET /static/drf-yasg/insQ.min.js HTTP/1.1" 304 0 +"GET /static/drf-yasg/swagger-ui-init.js HTTP/1.1" 304 0 +"GET /api/pricing/swagger/?format=openapi HTTP/1.1" 200 44272 diff --git a/pricing/models.py b/pricing/models.py index bca45d2..246d9ae 100644 --- a/pricing/models.py +++ b/pricing/models.py @@ -1,4 +1,7 @@ from django.db import models +from io import BytesIO +from reportlab.lib.pagesizes import letter +from reportlab.pdfgen import canvas # Справочник товаров class Product(models.Model): @@ -38,7 +41,6 @@ class PriceList(models.Model): constraint_price_change = models.DecimalField(max_digits=5, decimal_places=2, default=90, verbose_name="Лимит на изменение цены (%)") def save(self, *args, **kwargs): - # Логика проверки на изменение цены if self.pk: old_price = PriceList.objects.get(pk=self.pk).final_price price_change_percent = abs((self.final_price - old_price) / old_price) * 100 @@ -81,6 +83,19 @@ class PriceTag(models.Model): price_list = models.ForeignKey(PriceList, on_delete=models.CASCADE, verbose_name="Прайс-лист") tag_image = models.ImageField(upload_to='price_tags/', verbose_name="Изображение ценника", blank=True, null=True) price_effective_date = models.DateField(verbose_name="Дата вступления в силу ценника") + + def generate_pdf(self): + """Генерация ценника в формате PDF.""" + buffer = BytesIO() + c = canvas.Canvas(buffer, pagesize=letter) + c.drawString(100, 750, f"Продукт: {self.product.name}") + c.drawString(100, 730, f"Тип цены: {self.price_list.price_type.name}") + c.drawString(100, 710, f"Входная цена: {self.price_list.entry_price} руб.") + c.drawString(100, 690, f"Итоговая цена: {self.price_list.final_price} руб.") + c.showPage() + c.save() + buffer.seek(0) + return buffer def __str__(self): return f"Ценник для {self.product.name} - {self.price_effective_date}" @@ -104,5 +119,10 @@ class PriceListWithDiscount(models.Model): discount = models.ForeignKey(Discount, on_delete=models.CASCADE, verbose_name="Скидка") final_price_after_discount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="Итоговая цена после скидки") + def save(self, *args, **kwargs): + # Расчёт итоговой цены с учётом скидки + self.final_price_after_discount = self.price_list.final_price - (self.price_list.final_price * self.discount.discount_percentage / 100) + super().save(*args, **kwargs) + def __str__(self): return f"{self.price_list.product.name} - {self.final_price_after_discount} руб. (с учетом скидки)" diff --git a/settings/__pycache__/base.cpython-310.pyc b/settings/__pycache__/base.cpython-310.pyc index db58c1b2014eb0c28d9bdf9c6bf0855956254548..041679a8fac4b0ef5f677d7791f157e80fb5a261 100644 GIT binary patch delta 401 zcmY*T%}&BV5T@;x76hsoBP#w~B#j9-6Q2MiF>vrgdZ4M@wUpFuvs+L})c6Rb*ZKe& z59(uh@B#J>ym<6rVsr>x+{y0DH{Z82-=y$XD$!ywpMlf6zwtixNvSG5Pxh}5@hYz1 zHN1{Da5YtY30FJ`uz@#II?lhaNcJm>_ mY9L^>t#MY&mpvh)0%|M~-lSbn(VRPCi2NJ)=bo{WeH}`6yNwDj+v2jvOUWtLH2^8%;e0x p^jj>YMLETOn*5V*v997=$xtK>)LJAxc^X>;qsip=Y^F>cJOC_^7`Xrd