From a9289cb28d8987755e3bb3735d7a3a5a46493a87 Mon Sep 17 00:00:00 2001 From: Welton Moura Date: Tue, 22 Jul 2025 15:39:37 -0300 Subject: [PATCH] feat: criado tabela no db (UnitOfMeasure, ProductComponent, StockMovementType, StockMovement) add UnitOfMeasure na tabela produtos --- .../__pycache__/models.cpython-312.pyc | Bin 3672 -> 6359 bytes .../0005_stockmovementtype_stockmovement.py | 42 ++++++++++++ ...movementtype_stockmovement.cpython-312.pyc | Bin 0 -> 3344 bytes gestaoRaul/comandas/models.py | 37 ++++++++++- gestaoRaul/db.sqlite3 | Bin 364544 -> 425984 bytes .../__pycache__/models.cpython-312.pyc | Bin 1934 -> 4366 bytes ...ctcomponent_product_components_and_more.py | 44 +++++++++++++ ...roduct_components_and_more.cpython-312.pyc | Bin 0 -> 3038 bytes gestaoRaul/products/models.py | 62 ++++++++++++++++++ 9 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 gestaoRaul/comandas/migrations/0005_stockmovementtype_stockmovement.py create mode 100644 gestaoRaul/comandas/migrations/__pycache__/0005_stockmovementtype_stockmovement.cpython-312.pyc create mode 100644 gestaoRaul/products/migrations/0004_unitofmeasure_productcomponent_product_components_and_more.py create mode 100644 gestaoRaul/products/migrations/__pycache__/0004_unitofmeasure_productcomponent_product_components_and_more.cpython-312.pyc diff --git a/gestaoRaul/comandas/__pycache__/models.cpython-312.pyc b/gestaoRaul/comandas/__pycache__/models.cpython-312.pyc index 6b5b583535164e978ede1c3b2b6f9cb75177cffc..3c572ee514e6a6be879b6ce1759fa9af18d2fd37 100644 GIT binary patch delta 2520 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 F{{b}EKfV9} literal 0 HcmV?d00001 diff --git a/gestaoRaul/comandas/models.py b/gestaoRaul/comandas/models.py index 6e6bf59..56235be 100644 --- a/gestaoRaul/comandas/models.py +++ b/gestaoRaul/comandas/models.py @@ -43,4 +43,39 @@ class ProductComanda(models.Model): for p in products: if p.name == produto['nome'] and p.active == True: products_ordenados.append(p) - return products_ordenados[:15] \ No newline at end of file + return products_ordenados[:15] + + +class StockMovementType(models.Model): + id = models.AutoField(primary_key=True) + name = models.CharField(max_length=100, unique=True, help_text="Ex: 'Entrada por Compra', 'Saída por Venda', 'Ajuste de Estoque'") + observation = models.TextField(null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.name + +class StockMovement(models.Model): + id = models.AutoField(primary_key=True) + product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='stock_movements') + user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, help_text="Usuário que realizou a movimentação.") + related_comanda = models.ForeignKey( + Comanda, + on_delete=models.SET_NULL, + null=True, + blank=True, + help_text="Comanda relacionada à movimentação (opcional)." + ) + movement_type = models.ForeignKey(StockMovementType, on_delete=models.PROTECT, help_text="Tipo de movimentação (entrada, saída, ajuste).") + quantity = models.IntegerField(help_text="Quantidade movimentada. Use valores negativos para saídas.") + observation = models.TextField(null=True, blank=True) + movement_date = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return ( + f"Movimentação de {self.quantity} de {self.product.name} " + f"({self.movement_type.name}) em {self.movement_date.strftime('%d/%m/%Y %H:%M')}" + ) + + class Meta: + ordering = ['-movement_date'] \ No newline at end of file diff --git a/gestaoRaul/db.sqlite3 b/gestaoRaul/db.sqlite3 index d6770f152faec413398623e28b6a7ce0a5a7d393..663c5a7481f6e9a8e553d6f2dcfeabacdde234e5 100644 GIT binary patch delta 8739 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 delta 4441 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 ON?8}pT{#4eO8XzhJ7LoR diff --git a/gestaoRaul/products/__pycache__/models.cpython-312.pyc b/gestaoRaul/products/__pycache__/models.cpython-312.pyc index 11aac8f2c290009876b9e415fedae88772c7f40c..a9e6b0de2da7b6d2a23d4ad7fec24753cf0f762d 100644 GIT binary patch literal 4366 zcmb_fT}&I<6`t`Q9{++31VTtAZ% z8jrv3?EfB|O@RnR%nJoEBZ}yI@}7b> zP%6BK zA4rK#pkNT1H^KAWGbw}r(1dEyoWV3|W?zp;5Sr8cHI!}&RLF=#$ap*g^)3ew16`kp zJDwM!>u3BN)n=l^OGM(^@gJTr^w$m<0A$A@WRSpQGg3)Pg`DU;U9;{i-lnQqWORO8 zbiyl4E2ylb+^40z_h1-nr=}i$C=UaWsDuu`BM;xop`FnzW(=piPN<+hRPt2MSxZi! zsA~_3)RC5Genqk9Lu(KBe=W)TDC*eozT12_Tc0GKD*Cv0`zOI{3Xgx@DMSpD<&YqI37| z^{I)m95pS~xT_ZPV=K%c#jItHxm%iEDLEaAVp>d5)_RUCP`X|mgHM@g%7PtF*5Yy{ zF7F2AeH`vAENf6vbhSVg#R(}2^jgfLA5oMCMK$l%Fr2L;jTbFrTBCX5cr@Zj6H6*{ zUwsH;T>xS|V73L;i+(qnj)sxIF>io*EZ9>2dT&kYuSosRNmUvxU$?^p>sM;wfl7Gb zIeU42_xfkmuv(t9ljk+`!GE7jy@<(Yk-=s)Xz1G_(Rg0TRfeTbF+ z;|bpJHP1POE1cd=_cMnroLv#lE_@fCjKp!c2rW+wF3fR#Eg*O$0f>cQv%e_Eooa)V zNN6YA#Kk#IeiKK#VBF{5EZ>PV+a`J2OK)O`v=eQvK+mx#@er!_*m0bIalG5+8?b&P zwiAC*XQ50#@8NPAWGCq&2_li?PInVMKzit@MGxtH?8^+26Tlm%NgvoVrT)}OrvqXN zBWIo=kL?jKDUpTo&*S*?Vm|Nq7xJoppJA-*;U+=_=L@3cG|O~igl2(m^2$nH%~Erk zxfnJCP^W{?MTk!eB3?3d1?ZMq6h1Hvm22nggd`Ix7bpR8l2=rw$`IC6<`Hcf>6DM* zy7TVXIrO4vl3<+9`rs#w!iu2-M{IkXt}MQonnjg5Db$OwzF8F4Ooan^sj-;yIUUv# zGm5z-CsucqMGR`w37e%tfm%$0?1>bW=ng?-pr6Noq z<6znfs-Y9QSx|G-t?)x=<){;xbc3v32m+sl!kao|E7VmRhU0KT(*~njPQOJ<4C%t@ zm>8d%7@wSSf>}4UDLIkrhLNYL?)KG@Eo!EwQzxKiEp3%@WpaXZQ}fE~y_p#&4(WiU z7>i25O)#AJZB;ML8))4gLd`%j9WO{O7d!SLPVHf%2VK2_bQ5qqo*IT%Kv9@@-wjB5 z4>Q!_H87uY`onx0P$*c!rE`oe`N46QifX_b4 z!|QD(V#ZtYq`cqtw2EH(HnmhX0_a%~%cJDO!xxrJv5XwGmMCk9M#sk+-^0f6Gciqs za6CErB<`NVpFzP9c|%s=(y|85aq_l&Sd0LN&sT6a1bL~SJGacWP~(A`#`!)})xMwK z_~(R_cXll(GYWHK@|q8K3MM}aZC!5dYRHp<7>!ZF-oeVYI@|ZglGZN?pF$J!8kn;1 zSG*)#sKhVS;v<##$Zl+O>nguEVA*c$;&ZZfxi&gp86B^UPFF^!cSml#@`}-$;w!IL z3e~kC+Oj>aHca8bWHi%g_#|+!PWLC6$N(uHA^M*q2=~P$+7^1nIO4(d5jf^57}(Fg z)U!aXFIDMF*}*u{Rr+b#?isNY*AFCre_+?w^C}|rkF*1gwty}p=>1CH`*vrSotQuH zdwKhRheZFB_zxhmDRDpG^Sd+V1Hs#rM3z-OXQau3ducjZf6p2iHq)$ delta 599 zcmYLGzi$&U7`5+L?yhapq}L`PX%or-UV=bE;z!j5Q3gbW5JI8|9oO1TLoav5mq>&G zI%I&QaPmO^g|5KFUx35{8?pov14Fio05hKx5SH%U=jZpnXY1Qv-p^$}%*?n5*5LKy z?JIhkE#bBFletJ%-rBH?QM2%L6fOn-tGjv@9(hwkU|UK+)nVw z4_VaeZWB!!Q7;Uoxe*4@&d?Q(bsD?kf>kwUK`kno)#*dr1eXy79YzGz?vdQzfQIiU zUGDn@P$pS`J@mP-@QS45W#yy2I6~ryeNlYPoW-8V+oi$+NTmL-OA`&MdYu==CA)^_ z#a(+Dmq8pBJviVM1xo<`b=axp%Zfg(Kvhjr5x=#|8lM-potuR!P|{tCIcv9~Ypl-= z@yIW^vJ;G(!tya!S9Eqncm0-7{`tc zO=3xhJ_w>#+@Kp=2dm6)23^*Qd7CAT$>g{in>4ShF-~&MtFZAiRJOENK-de}Dqn#u ihA&Z1KdR{%<1eWC9i94Vd)Rxn^&)&8{z6cW-G2bjPLlcn diff --git a/gestaoRaul/products/migrations/0004_unitofmeasure_productcomponent_product_components_and_more.py b/gestaoRaul/products/migrations/0004_unitofmeasure_productcomponent_product_components_and_more.py new file mode 100644 index 0000000..c8c7a3a --- /dev/null +++ b/gestaoRaul/products/migrations/0004_unitofmeasure_productcomponent_product_components_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 5.1.4 on 2025-07-22 18:36 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0003_product_cuisine'), + ] + + operations = [ + migrations.CreateModel( + name='UnitOfMeasure', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('name', models.CharField(help_text="Ex: 'Unidade', 'Kg', 'Litro'", max_length=50, unique=True)), + ('abbreviation', models.CharField(help_text="Ex: 'un', 'kg', 'L'", max_length=10, unique=True)), + ], + ), + migrations.CreateModel( + name='ProductComponent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity_required', models.PositiveIntegerField(default=1, help_text='Quantidade deste componente necessária para o produto composto.')), + ('component_product', models.ForeignKey(help_text='Um produto que é componente de outro produto.', on_delete=django.db.models.deletion.CASCADE, related_name='used_as_component_in', to='products.product')), + ('composite_product', models.ForeignKey(help_text='O produto que é composto por outros produtos.', on_delete=django.db.models.deletion.CASCADE, related_name='composition_entries', to='products.product')), + ], + options={ + 'unique_together': {('composite_product', 'component_product')}, + }, + ), + migrations.AddField( + model_name='product', + name='components', + field=models.ManyToManyField(related_name='is_component_of', through='products.ProductComponent', to='products.product'), + ), + migrations.AddField( + model_name='product', + name='unit_of_measure', + field=models.ForeignKey(blank=True, help_text='Unidade de medida para este produto.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='products.unitofmeasure'), + ), + ] diff --git a/gestaoRaul/products/migrations/__pycache__/0004_unitofmeasure_productcomponent_product_components_and_more.cpython-312.pyc b/gestaoRaul/products/migrations/__pycache__/0004_unitofmeasure_productcomponent_product_components_and_more.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9ada42cc81b00e2cd2f3f939fd0df8e454b506e7 GIT binary patch literal 3038 zcmcImOKclO7~Wm4pLx_y+?e#0O=IG?fYU;u2vw+V;zFNkN-I^Su-#-P_NMlZJG|25;E z1_n|J{4TPO>#GSx`IQUdFWQ|vy8x5N3Q~~TP^v17T0?6_s*$E%)m24P-ceBGGX?25 zvMj8H2IRONkz+NwsurV9xp1whu~gHpQOmQ5zpY{w=?Vd4%Z=ppY5SNjI!;6As#Rt5t<`CG;_Fr`OrVt zm-~CH9qF-l?4N7s1vJ_|w1?;6=b|6^AJC8PN3ZGV7#gdqw%Rtr+=&brJ(!Q94zIpce3>P$hW!Q2 zmS|Ce{6)`Y*^?(vzGiksbJ4e5+rez$mScN!OINYw`V=$GMmI0OvA!0yn-*O)@8MOJ zbTPH9hP{TF?pRH{cBHcMmQjF{$U?aAvQfBPdiH7|}jBLV0zw{s)*Y5Eq-AILqAkEyuIHRg>cTzD+TD zs)Ck(4nFf@i+f}s?0VQ(3?Z=L;6?1ZKYRsYFj^M13}T2tdPHiu9w|Z8;s`HUe#4^& zICN&mKp1tu1nak&J7*yd#t+}@1p;v5Lli@m63hB7MyBPOyVh)HEghz{)SVP{37RC1 z2{$VCAi@+kcr>Kznn${fT-(F@7|n%f#$H0;lhGnn@^M2Ix5S186R-j|xCt4cHg?$o znO4&yHSEt<6Y(~wc{C>vG+Pkmexjh9KHUx#Dmo_ zVbH5n;@9fb5KvHT{7Df`%hHL8(h&?jlPsA{S?g>0ZUIBOjV4A=%rdtk`2rTQx;C;y z06g@_QulN*%AyMm%eg1Rt~-9CLHRu?Xk061S;74&)C5odaqEc#6-3F1yex|T7Y+_-VRGBaI+ zs9NL(bjNfU(COX(0n>0doi_IcIIPf};s_UZ8^JX#2SI2lF11!^4CshY944*}ul;Ar zR!m90vK7&?u}`jSrIh5@=c$dvu}b1=vi9zEE|6*{@Xx3k|@p5!hC>C2m$ zTrgVvVq{~q*cmMbr*8zN6)ZbXMoExvZDz)T@l#)pY>c1kjGqe5&Icdf4eaKVaVJQV zt+<{Y+>XYRsjc)rtON1s{YYLbw8v6wv^-Q+p^N zSGtg|j}65>y+q4l?G$(?=C@S?|M@t)&WgsJmfF>zMj s8gJ7Ii2R*$`GvO?QC0O>Oi{;wR;IRNFRHOesf~2Llg|IHfFKO~1$$W$u>b%7 literal 0 HcmV?d00001 diff --git a/gestaoRaul/products/models.py b/gestaoRaul/products/models.py index 93e978b..7d3c312 100644 --- a/gestaoRaul/products/models.py +++ b/gestaoRaul/products/models.py @@ -1,6 +1,18 @@ from django.db import models +from django.contrib.auth.models import User from categories.models import Categories +# from comandas.models import Comanda + + + +class UnitOfMeasure(models.Model): + id = models.AutoField(primary_key=True) + name = models.CharField(max_length=50, unique=True, help_text="Ex: 'Unidade', 'Kg', 'Litro'") + abbreviation = models.CharField(max_length=10, unique=True, help_text="Ex: 'un', 'kg', 'L'") + + def __str__(self): + return self.abbreviation # Create your models here. @@ -14,6 +26,23 @@ class Product(models.Model): category = models.ForeignKey(Categories, on_delete=models.CASCADE) cuisine = models.BooleanField(default=False) active = models.BooleanField(default=True) + unit_of_measure = models.ForeignKey( + UnitOfMeasure, + on_delete=models.SET_NULL, # Define como NULL se a unidade de medida for excluída + null=True, + blank=True, + help_text="Unidade de medida para este produto." + ) + + # Campo de composição (mantido da resposta anterior) + components = models.ManyToManyField( + 'self', + through='ProductComponent', + through_fields=('composite_product', 'component_product'), + symmetrical=False, + related_name='is_component_of' + ) + def __str__(self) -> str: return f"{self.name}" @@ -25,3 +54,36 @@ class Product(models.Model): def addStock(self, qtd): self.quantity += qtd self.save() + + + +class ProductComponent(models.Model): + composite_product = models.ForeignKey( + Product, + on_delete=models.CASCADE, + related_name='composition_entries', + help_text="O produto que é composto por outros produtos." + ) + component_product = models.ForeignKey( + Product, + on_delete=models.CASCADE, + related_name='used_as_component_in', + help_text="Um produto que é componente de outro produto." + ) + quantity_required = models.PositiveIntegerField( + default=1, + help_text="Quantidade deste componente necessária para o produto composto." + ) + + class Meta: + unique_together = ('composite_product', 'component_product') + + def __str__(self): + return ( + f"{self.composite_product.name} requer " + f"{self.quantity_required} de {self.component_product.name}" + ) + + + +