Explorar el Código

vendor product edit

tum %!s(int64=4) %!d(string=hace) años
padre
commit
7db1ef0b8f

+ 4 - 0
app/front/static/front/css/blog.css

@@ -142,3 +142,7 @@ h1, h2, h3, h4, h5, h6 {
142 142
 .form-legend {
143 143
     width:auto !important;
144 144
 }
145
+
146
+.multiField {
147
+    border:1px solid #ccc;
148
+}

+ 17 - 1
app/fruit/admin.py

@@ -2,7 +2,7 @@ from django.contrib import admin
2 2
 
3 3
 from django.contrib import admin
4 4
 from django.contrib.gis.admin import OSMGeoAdmin
5
-from .models import Store, ProductType, Product, Photo, ProductSKU, StoreCat, Buyer, Sale, Inbox
5
+from .models import Store, ProductType, Product, Photo, ProductSKU, StoreCat, Buyer, Sale, Inbox, Vendor, VendorOrder
6 6
 # Register your models here.
7 7
 
8 8
 from django_google_maps import widgets as map_widgets
@@ -30,6 +30,22 @@ class StoreAdmin(UtilModel, admin.ModelAdmin):
30 30
         map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
31 31
     }
32 32
 
33
+@admin.register(Vendor)
34
+class VendorAdmin(UtilModel, admin.ModelAdmin):
35
+    search_fields = ('name',)
36
+    list_display = ('name', 'code', 'created_at', 'created_by')
37
+    formfield_overrides = {
38
+        map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
39
+    }
40
+
41
+@admin.register(VendorOrder)
42
+class VendorOrderAdmin(UtilModel, admin.ModelAdmin):
43
+    search_fields = ('name',)
44
+    list_display = ('vendor', 'product', 'store', 'price',  'n_unit',  'unit_name', 'created_at', 'created_by')
45
+    formfield_overrides = {
46
+        map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
47
+    }
48
+
33 49
 @admin.register(Buyer)
34 50
 class BuyerAdmin(UtilModel, admin.ModelAdmin):
35 51
     search_fields = ('name',)

+ 34 - 1
app/fruit/forms.py

@@ -1,6 +1,6 @@
1 1
 from django.forms.models import inlineformset_factory, modelform_factory, modelformset_factory
2 2
 from django import forms
3
-from .models import Store, Product, Photo, ProductSKU, Sale, Inbox
3
+from .models import Store, Product, Photo, ProductSKU, Sale, Inbox, Vendor, VendorOrder, VendorProduct
4 4
 from django.forms import ModelForm
5 5
 from django_google_maps import widgets as map_widgets
6 6
 from django_google_maps import fields as map_fields
@@ -49,6 +49,27 @@ InboxForm = modelform_factory(
49 49
     widgets = GeneralWidgets,
50 50
     )
51 51
 
52
+VendorForm = modelform_factory(
53
+    Vendor,
54
+    fields="__all__",
55
+    exclude  = ("store", ),
56
+    widgets = GeneralWidgets,
57
+    )
58
+
59
+VendorProductForm = modelform_factory(
60
+    VendorProduct,
61
+    fields="__all__",
62
+    exclude  = ("store", "vendor"),
63
+    widgets = GeneralWidgets,
64
+    )
65
+
66
+VendorOrderForm = modelform_factory(
67
+    VendorOrder,
68
+    fields="__all__",
69
+    exclude  = ("store", ),
70
+    widgets = GeneralWidgets,
71
+    )
72
+
52 73
 PhotoFormSet = modelformset_factory(
53 74
     Photo,
54 75
     fields="__all__",
@@ -59,6 +80,8 @@ PhotoFormSet = modelformset_factory(
59 80
 
60 81
 InlinePhotoFormset = inlineformset_factory(Product, Photo,  fields="__all__", widgets= GeneralWidgets)
61 82
 
83
+InlineVendorProductFormset = inlineformset_factory(Vendor, VendorProduct,  fields="__all__", widgets= GeneralWidgets)
84
+
62 85
 
63 86
 class ProductFilter(django_filters.FilterSet):
64 87
     class Meta:
@@ -75,4 +98,14 @@ class InboxFilter(django_filters.FilterSet):
75 98
         model = Inbox
76 99
         fields = ['store', 'product', 'buyer', 'subject', 'body', 'tel', 'status', 'created_at']
77 100
 
101
+class VendorFilter(django_filters.FilterSet):
102
+    class Meta:
103
+        model = Vendor
104
+        fields = ['name', 'code',  'description', 'tel',  'line_id', 'email', 'created_at']
105
+
106
+class VendorOrderFilter(django_filters.FilterSet):
107
+    class Meta:
108
+        model = VendorOrder
109
+        fields = ['vendor', 'product', 'store', 'price', 'n_unit',  'unit_name', 'total', 'created_at']
110
+
78 111
 

+ 38 - 0
app/fruit/migrations/0021_vendororder.py

@@ -0,0 +1,38 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 07:25
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('fruit', '0020_purchase_vendor'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.CreateModel(
17
+            name='VendorOrder',
18
+            fields=[
19
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
21
+                ('updated_at', models.DateTimeField(auto_now=True)),
22
+                ('price', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
23
+                ('n_unit', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
24
+                ('unit_name', models.CharField(max_length=200, null=True)),
25
+                ('sub_total', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
26
+                ('vat', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
27
+                ('total', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
28
+                ('created_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vendororder_created', to=settings.AUTH_USER_MODEL)),
29
+                ('modified_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vendororder_modified', to=settings.AUTH_USER_MODEL)),
30
+                ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fruit.product')),
31
+                ('store', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fruit.store')),
32
+                ('vendor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fruit.vendor')),
33
+            ],
34
+            options={
35
+                'abstract': False,
36
+            },
37
+        ),
38
+    ]

+ 20 - 0
app/fruit/migrations/0022_alter_vendororder_product.py

@@ -0,0 +1,20 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 07:32
2
+
3
+from django.db import migrations
4
+import django.db.models.deletion
5
+import smart_selects.db_fields
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        ('fruit', '0021_vendororder'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.AlterField(
16
+            model_name='vendororder',
17
+            name='product',
18
+            field=smart_selects.db_fields.ChainedForeignKey(auto_choose=True, chained_field='vendor', chained_model_field='vendor', null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.product'),
19
+        ),
20
+    ]

+ 18 - 0
app/fruit/migrations/0023_alter_vendororder_price.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 08:09
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('fruit', '0022_alter_vendororder_product'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AlterField(
14
+            model_name='vendororder',
15
+            name='price',
16
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True),
17
+        ),
18
+    ]

+ 22 - 0
app/fruit/migrations/0024_auto_20210809_1516.py

@@ -0,0 +1,22 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 08:16
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('fruit', '0023_alter_vendororder_price'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.RemoveField(
14
+            model_name='vendor',
15
+            name='product',
16
+        ),
17
+        migrations.AddField(
18
+            model_name='vendor',
19
+            name='products',
20
+            field=models.ManyToManyField(to='fruit.Product'),
21
+        ),
22
+    ]

+ 34 - 0
app/fruit/migrations/0025_vendorproduct.py

@@ -0,0 +1,34 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 08:22
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('fruit', '0024_auto_20210809_1516'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.CreateModel(
17
+            name='VendorProduct',
18
+            fields=[
19
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
21
+                ('updated_at', models.DateTimeField(auto_now=True)),
22
+                ('price', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
23
+                ('n_unit', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
24
+                ('unit_name', models.CharField(max_length=200, null=True)),
25
+                ('created_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vendorproduct_created', to=settings.AUTH_USER_MODEL)),
26
+                ('modified_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='vendorproduct_modified', to=settings.AUTH_USER_MODEL)),
27
+                ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fruit.product')),
28
+                ('vendor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fruit.vendor')),
29
+            ],
30
+            options={
31
+                'abstract': False,
32
+            },
33
+        ),
34
+    ]

+ 17 - 0
app/fruit/migrations/0026_remove_vendor_products.py

@@ -0,0 +1,17 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 14:23
2
+
3
+from django.db import migrations
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('fruit', '0025_vendorproduct'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.RemoveField(
14
+            model_name='vendor',
15
+            name='products',
16
+        ),
17
+    ]

+ 24 - 0
app/fruit/migrations/0027_auto_20210809_2129.py

@@ -0,0 +1,24 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 14:29
2
+
3
+from django.db import migrations, models
4
+import django.db.models.deletion
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('fruit', '0026_remove_vendor_products'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AlterField(
15
+            model_name='inbox',
16
+            name='product',
17
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='fruit.product'),
18
+        ),
19
+        migrations.AlterField(
20
+            model_name='inbox',
21
+            name='store',
22
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='fruit.store'),
23
+        ),
24
+    ]

+ 29 - 0
app/fruit/migrations/0028_auto_20210809_2130.py

@@ -0,0 +1,29 @@
1
+# Generated by Django 3.2.6 on 2021-08-09 14:30
2
+
3
+from django.db import migrations, models
4
+import django.db.models.deletion
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('fruit', '0027_auto_20210809_2129'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AlterField(
15
+            model_name='inbox',
16
+            name='buyer',
17
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='fruit.buyer'),
18
+        ),
19
+        migrations.AlterField(
20
+            model_name='inbox',
21
+            name='product',
22
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='fruit.product'),
23
+        ),
24
+        migrations.AlterField(
25
+            model_name='inbox',
26
+            name='store',
27
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='fruit.store'),
28
+        ),
29
+    ]

+ 40 - 5
app/fruit/models.py

@@ -108,9 +108,9 @@ class Buyer(GenericModel, models.Model):
108 108
         return f"{self.name} Tel.:{self.tel} Email:{self.email}"
109 109
 
110 110
 class Inbox(GenericModel, models.Model):
111
-    store = models.ForeignKey('Store', on_delete=models.DO_NOTHING, null=False, blank=False)
112
-    product = models.ForeignKey('Product', on_delete=models.DO_NOTHING, null=False, blank=False)
113
-    buyer = models.ForeignKey('Buyer', on_delete=models.DO_NOTHING, null=True, blank=True)
111
+    store = models.ForeignKey('Store', on_delete=models.SET_NULL, null=True, blank=False)
112
+    product = models.ForeignKey('Product', on_delete=models.SET_NULL, null=True, blank=False)
113
+    buyer = models.ForeignKey('Buyer', on_delete=models.SET_NULL, null=True, blank=True)
114 114
 
115 115
     subject = models.CharField(max_length=200)
116 116
     body = models.TextField(blank=False)
@@ -171,7 +171,7 @@ class Product(GenericModel, models.Model ):
171 171
     code = models.CharField(max_length=200)
172 172
     product_type = TreeForeignKey('ProductType', on_delete=models.SET_NULL, null=True)
173 173
     description = models.TextField(blank=True, null=True)
174
-    store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False)
174
+    store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=True)
175 175
     price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
176 176
 
177 177
 
@@ -183,11 +183,20 @@ class Product(GenericModel, models.Model ):
183 183
     def __str__(self):
184 184
         return f"{self.name} {self.code}"
185 185
 
186
+
187
+class VendorProduct(GenericModel, models.Model):
188
+    product = models.ForeignKey('Product', on_delete=models.CASCADE)
189
+    vendor = models.ForeignKey('Vendor', on_delete=models.CASCADE)
190
+    price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=7)
191
+    n_unit = models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)
192
+    unit_name = models.CharField(max_length=200, null=True)
193
+
186 194
 class Vendor(GenericModel, models.Model ):
187 195
     name = models.CharField(max_length=200)
188 196
     code = models.CharField(max_length=200)
189 197
     #product_type = TreeForeignKey('ProductType', on_delete=models.SET_NULL, null=True)
190
-    product = models.ForeignKey('Product', on_delete=models.CASCADE)
198
+    #product = models.ForeignKey('Product', on_delete=models.CASCADE)
199
+    #products = models.ManyToManyField('Product',)
191 200
     description = models.TextField(blank=True, null=True)
192 201
     store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False)
193 202
     price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
@@ -211,6 +220,32 @@ class Vendor(GenericModel, models.Model ):
211 220
         return f"{self.name} {self.code}"
212 221
 
213 222
 
223
+class VendorOrder(GenericModel, models.Model):
224
+    vendor = models.ForeignKey('Vendor', on_delete=models.CASCADE,  null=False, blank=False)
225
+    product = ChainedForeignKey(
226
+        "Product",
227
+        chained_field="vendor",
228
+        chained_model_field="vendor",
229
+        show_all=False,
230
+        auto_choose=True,
231
+        null=True
232
+    )
233
+    store = models.ForeignKey('Store', on_delete=models.CASCADE, null=False, blank=False)
234
+
235
+    price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
236
+    n_unit = models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)
237
+    unit_name = models.CharField(max_length=200, null=True)
238
+
239
+    sub_total = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
240
+    vat = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
241
+    total = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
242
+
243
+    def save(self, *args, **kwargs):
244
+        self.sub_total = self.price * self.n_unit
245
+        self.vat  = self.sub_total * decimal.Decimal(VAT)
246
+        self.total = self.sub_total + self.vat
247
+        super(VendorOrder, self).save(*args, **kwargs)
248
+
214 249
 class ProductSKU(GenericModel, models.Model ):
215 250
     sku = models.CharField(max_length=200)
216 251
     product  = models.ForeignKey('Product', on_delete=models.CASCADE, null=True)

+ 2 - 1
app/fruit/templates/fruit/mystore.html

@@ -22,7 +22,8 @@
22 22
       <a class="nav-link {{ product|yesno:"active," }}" id="v-pills-profile-tab"  href="{% url "fruit:product_index" %}" type="button" role="tab" aria-controls="v-pills-profile" aria-selected="false">Products</a>
23 23
     <a class="nav-link" id="v-pills-messages-tab" href="{% url "fruit:inbox_index" %}" type="button" role="tab" aria-controls="v-pills-messages" aria-selected="false">Inbox</a>
24 24
     <a class="nav-link {{ sale_active|yesno:"active," }}" id="v-pills-settings-tab" href="{% url "fruit:sale_index" %}"  type="button" role="tab" aria-controls="v-pills-settings" aria-selected="false">Saled Items</a>
25
-    <a class="nav-link" id="v-pills-vendor-tab" data-toggle="pill" data-bs-target="#v-pills-vendor" type="button" role="tab" aria-controls="v-pills-vendor" aria-selected="false">Vendors</a>
25
+    <a class="nav-link" id="v-pills-vendor-tab" href="{% url "fruit:vendor_index" %}" type="button" role="tab" aria-controls="v-pills-vendor" aria-selected="false">Vendors</a>
26
+    <a class="nav-link" id="v-pills-vendororder-tab" href="{% url "fruit:vendororder_index" %}" type="button" role="tab" aria-controls="v-pills-vendororder" aria-selected="false">Vendor Order</a>
26 27
   </div>
27 28
   <div class="tab-content p-3 col-md-9 col-lg-10" id="v-pills-tabContent">
28 29
       {% block breadcrumbs %}

+ 2 - 0
app/fruit/templates/fruit/product_form.html

@@ -47,7 +47,9 @@
47 47
     </form>
48 48
     <hr>
49 49
     <h2>SKUs</h2>
50
+    {% if obj %}
50 51
     <a href="{% url "fruit:create_sku" pk=obj.pk %}" class='btn btn-primary'>Create SKU</a><br><br>
52
+    {% endif %}
51 53
 
52 54
 <table class='table table-bordered  table-striped'>
53 55
     <thead>

+ 47 - 0
app/fruit/templates/fruit/vendor_form.html

@@ -0,0 +1,47 @@
1
+{% extends "fruit/vendor_index.html" %}
2
+{% load static %}
3
+{% load crispy_forms_tags %}
4
+{% load django_bootstrap_breadcrumbs %}
5
+
6
+{% block header %}            
7
+{{ form.media  }}
8
+{{ form2.media }}
9
+{% endblock %}
10
+
11
+{% block breadcrumbs %}
12
+    {{ block.super }}
13
+    {% breadcrumb "Vendor Edit" "fruit:vendor_edit" vendor.pk %}
14
+{% endblock %}
15
+
16
+{% block store_main %}
17
+<h2>Vendor Form</h2>
18
+<form  method="post" enctype="multipart/form-data">
19
+    {% csrf_token %}
20
+    {{ form | crispy  }}
21
+    <hr>
22
+    <a href="{% url "fruit:vendorproduct_create" pk=obj.id %}" class='btn btn-primary'>Create Product</a>
23
+    <h2>Products</h2>
24
+    <table class='table table-borded table-striped'>
25
+    <thead>
26
+        <tr>
27
+            <th>ID</th>
28
+            <th>Product</th>
29
+            <th>Created At</th>
30
+        </tr>
31
+    </thead>   
32
+    <tbody>
33
+        {% for p in obj.vendorproduct_set.all %}
34
+        <tr>
35
+            <td><a href="{% url "fruit:vendorproduct_edit" pk=p.id %}">{{ p.id }}</a></td>
36
+            <td>{{ p.product }}</td>
37
+            <td>{{ p.created_at }}</td>
38
+        </tr>
39
+        {% endfor %}
40
+    </tbody>
41
+    </table>
42
+    <br>
43
+    <input type='submit' class='btn btn-primary' value="Update" />
44
+
45
+</form>
46
+
47
+{% endblock %}

+ 52 - 0
app/fruit/templates/fruit/vendor_index.html

@@ -0,0 +1,52 @@
1
+{% extends "fruit/mystore.html" %}
2
+{% load static %}
3
+{% load crispy_forms_tags %}
4
+
5
+{% block header %}            
6
+{% endblock %}
7
+
8
+{% load django_bootstrap_breadcrumbs %}
9
+{% block breadcrumbs %}
10
+    {{ block.super }}
11
+    {% breadcrumb "Vendors" "fruit:vendor_index" %}
12
+{% endblock %}
13
+
14
+{% block store_main %}
15
+
16
+<a  class='btn btn-primary' href="{% url "fruit:vendor_create" %}">Create Vendor</a>
17
+<hr>
18
+<h2>
19
+    Vendor Index</h2>
20
+{% include "fruit/_searchcenter.html" %}
21
+<hr>
22
+<table class='table table-borded table-striped'>
23
+    <thead>
24
+        <tr>
25
+            <th>ID</th>
26
+            <th>Name</th>
27
+            <th>Products</th>
28
+            <th>Price</th>
29
+            <th>Detail</th>
30
+            <th>Tel</th>
31
+            <th>Email</th>
32
+            <th>LineId</th>
33
+            <th>Created At</th></tr>
34
+    </thead>
35
+    <tbody>
36
+{% for p in page_obj %}
37
+        <tr>
38
+            <td><a href="{% url "fruit:vendor_edit" pk=p.pk %}">{{ p.id }}</a></td><td>{{ p.product }}</td>
39
+            <td>{{ p.name }}</td>
40
+            <td>{{ p.products }}</td>
41
+            <td>{{ p.price }}</td>
42
+            <td>{{ p.detail }}</td>
43
+            <td>{{ p.tel }}</td>
44
+            <td>{{ p.email }}</td>
45
+            <td>{{ p.line_id }}</td>
46
+            <td>{{ p.created_at }}</td>
47
+        </tr>
48
+{% endfor %}
49
+    </tbody>
50
+</table>
51
+{% include "fruit/_paging.html" %}
52
+{% endblock %}

+ 25 - 0
app/fruit/templates/fruit/vendororder_form.html

@@ -0,0 +1,25 @@
1
+{% extends "fruit/vendororder_index.html" %}
2
+{% load static %}
3
+{% load crispy_forms_tags %}
4
+{% load django_bootstrap_breadcrumbs %}
5
+
6
+{% block header %}            
7
+{{ form.media  }}
8
+{% endblock %}
9
+
10
+{% block breadcrumbs %}
11
+    {{ block.super }}
12
+    {% breadcrumb "Vendor Order Form" "fruit:vendororder_edit" form.instance.pk %}
13
+{% endblock %}
14
+
15
+{% block store_main %}
16
+<h2>Vendor Order Form</h2>
17
+<form  method="post" enctype="multipart/form-data">
18
+    {% csrf_token %}
19
+    {{ form | crispy  }}
20
+    <br>
21
+    <input type='submit' class='btn btn-primary' value="Update" />
22
+
23
+</form>
24
+
25
+{% endblock %}

+ 47 - 0
app/fruit/templates/fruit/vendororder_index.html

@@ -0,0 +1,47 @@
1
+{% extends "fruit/mystore.html" %}
2
+{% load static %}
3
+{% load crispy_forms_tags %}
4
+
5
+{% block header %}            
6
+{% endblock %}
7
+
8
+{% load django_bootstrap_breadcrumbs %}
9
+{% block breadcrumbs %}
10
+    {{ block.super }}
11
+    {% breadcrumb "Vendor Orders" "fruit:vendororder_index" %}
12
+{% endblock %}
13
+
14
+{% block store_main %}
15
+
16
+<a  class='btn btn-primary' href="{% url "fruit:vendororder_create" %}">Create Vendor Order</a>
17
+<hr>
18
+<h2>
19
+    Vendor Order Index</h2>
20
+{% include "fruit/_searchcenter.html" %}
21
+<hr>
22
+<table class='table table-borded table-striped'>
23
+    <thead>
24
+        <tr>
25
+            <th>ID</th>
26
+            <th>Vendor</th>
27
+            <th>Product</th>
28
+            <th>Price</th>
29
+            <th>Unit</th>
30
+            <th>Total</th>
31
+            <th>Created At</th></tr>
32
+    </thead>
33
+    <tbody>
34
+{% for p in page_obj %}
35
+        <tr>
36
+            <td><a href="{% url "fruit:vendororder_edit" pk=p.pk %}">{{ p.id }}</a></td><td>{{ p.vendor }}</td>
37
+            <td>{{ p.product }}</td>
38
+            <td>{{ p.price }}</td>
39
+            <td>{{ p.unit }}</td>
40
+            <td>{{ p.total }}</td>
41
+            <td>{{ p.created_at }}</td>
42
+        </tr>
43
+{% endfor %}
44
+    </tbody>
45
+</table>
46
+{% include "fruit/_paging.html" %}
47
+{% endblock %}

+ 27 - 0
app/fruit/templates/fruit/vendorproduct_form.html

@@ -0,0 +1,27 @@
1
+{% extends "fruit/vendor_form.html" %}
2
+{% load static %}
3
+{% load crispy_forms_tags %}
4
+{% load django_bootstrap_breadcrumbs %}
5
+
6
+{% block header %}            
7
+{{ form.media  }}
8
+{{ form2.media }}
9
+{% endblock %}
10
+
11
+{% block breadcrumbs %}
12
+    {{ block.super }}
13
+    {% breadcrumb "Vendor Product Form" "fruit:vendorproduct_edit" form.instance.pk %}
14
+{% endblock %}
15
+
16
+{% block store_main %}
17
+<h2>Vendor Product  Form</h2>
18
+<form  method="post" enctype="multipart/form-data">
19
+    {% csrf_token %}
20
+    {{ form | crispy  }}
21
+    <hr>
22
+    <br>
23
+    <input type='submit' class='btn btn-primary' value="Update" />
24
+
25
+</form>
26
+
27
+{% endblock %}

+ 8 - 0
app/fruit/urls.py

@@ -15,6 +15,14 @@ urlpatterns = [
15 15
     path('sales/<pk>', views.sale_edit, name='sale_edit'),
16 16
     path('inbox/', views.inbox_index, name='inbox_index'),
17 17
     path('inbox/<pk>', views.inbox_edit, name='inbox_edit'),
18
+    path('vendor/', views.vendor_index, name='vendor_index'),
19
+    path('vendor/create', views.vendor_create, name='vendor_create'),
20
+    path('vendor/<pk>', views.vendor_edit, name='vendor_edit'),
21
+    path('vendor/<pk>/product/create', views.vendorproduct_create, name='vendorproduct_create'),
22
+    path('vendorproduct/<pk>', views.vendorproduct_edit, name='vendorproduct_edit'),
23
+    path('vendororder/', views.vendororder_index, name='vendororder_index'),
24
+    path('vendororder/create', views.vendororder_create, name='vendororder_create'),
25
+    path('vendororder/<pk>', views.vendororder_edit, name='vendororder_edit'),
18 26
     path('signup', views.signup, name='signup'),
19 27
 ]
20 28
 

+ 228 - 3
app/fruit/views.py

@@ -6,8 +6,9 @@ from django.contrib.auth.forms import UserCreationForm
6 6
 from django.urls import reverse
7 7
 from django.contrib.auth.decorators import login_required
8 8
 
9
-from fruit.models import Store, Product, Photo, ProductSKU, Sale, Inbox
10
-from .forms import StoreForm, ProductForm, InboxForm, SaleForm,  PhotoFormSet, InlinePhotoFormset, ProductSKUForm, ProductFilter, SaleFilter, InboxFilter
9
+from fruit.models import Store, Product, Photo, ProductSKU, Sale, Inbox, Vendor, VendorProduct
10
+
11
+from .forms import StoreForm, ProductForm, InboxForm, SaleForm,  PhotoFormSet,VendorFilter,  InlinePhotoFormset, ProductSKUForm, ProductFilter, SaleFilter, InboxFilter, VendorForm, VendorOrderForm, VendorOrderFilter, VendorOrder, InlineVendorProductFormset, VendorProductForm
11 12
 from django.contrib import messages
12 13
 from django.core.paginator import Paginator
13 14
 
@@ -115,7 +116,7 @@ def create_sku(request, pk):
115 116
             messages.success(request, "Product Save")
116 117
             return redirect("fruit:edit_sku", pk=i.pk)
117 118
         else:
118
-            message.error(request, "SKU  created failed")
119
+            messages.error(request, form.errors)
119 120
             return redirect("fruit:create_sku", pk=int(pk))
120 121
 
121 122
     return render(request, 'fruit/sku_form.html', {'form': form, 'pid': p.pk})
@@ -245,6 +246,230 @@ def inbox_edit(request, pk):
245 246
 
246 247
     return render(request, 'fruit/inbox_form.html', {'inbox_active': True, 'form': form, 'object': obj})
247 248
 
249
+@login_required
250
+def vendor_index(request):
251
+    stores = request.user.store_created.all().order_by("-created_at")
252
+    o_qs = stores[0].vendor_set.all().order_by("-created_at")
253
+
254
+    f = VendorFilter(request.GET, queryset=o_qs)
255
+
256
+    paginator = Paginator(f.qs, 25)
257
+    page_number = request.GET.get('page')
258
+    page_obj = paginator.get_page(page_number)
259
+
260
+    return render(request, 'fruit/vendor_index.html', {'o_qs': o_qs, 'vendor_active': True, 'page_obj': page_obj, 'filter': f})
261
+
262
+@login_required
263
+def vendor_edit(request, pk):
264
+    stores = request.user.store_created.all().order_by("-created_at")
265
+
266
+    obj = Vendor.objects.get(pk=pk)
267
+    form = VendorForm(instance = obj)
268
+    form2 = InlineVendorProductFormset(instance = obj)
269
+    for f in form2:
270
+        f.fields['product'].queryset = stores[0].product_set.all().order_by("-created_at")
271
+
272
+    if request.method == "POST":
273
+        form = VendorForm(request.POST)
274
+        form2 = InlineVendorProductFormset(request.POST, instance = obj)
275
+        if form.is_valid() and form2.is_valid():
276
+            instance1 = form.save()
277
+            instance2 = form2.save(commit=False)
278
+
279
+            for i in instance2:
280
+                i.created_by = request.user
281
+                i.save()
282
+
283
+            '''
284
+            print(instances)
285
+            for s in instances:
286
+                s.product = instance1
287
+                s.save()
288
+            '''
289
+            messages.success(request, "Vendor Save")
290
+        else:
291
+            print("Invalid ")
292
+            if form.errors:
293
+                messages.error(request, form.errors)
294
+            if form2.errors:
295
+                messages.error(request, form2.errors)
296
+
297
+        return redirect("fruit:vendor_edit", pk =  int(pk))
298
+
299
+    return render(request, 'fruit/vendor_form.html', {'vendor_active': True, 'form': form, 'obj': obj, 'form2': form2})
300
+
301
+@login_required
302
+def vendor_create(request):
303
+    stores = request.user.store_created.all().order_by("-created_at")
304
+
305
+    form = VendorForm()
306
+
307
+    form.fields['products'].queryset = stores[0].product_set.all().order_by("-created_at")
308
+
309
+    if request.method == "POST":
310
+        form = VendorForm(request.POST)
311
+        if form.is_valid():
312
+
313
+            instance1 = form.save(commit=False)
314
+            instance1.store = stores[0]
315
+            instance1.created_by = request.user
316
+            instance1.save()
317
+            '''
318
+            print(instances)
319
+            for s in instances:
320
+                s.product = instance1
321
+                s.save()
322
+            '''
323
+            messages.success(request, "Sale Save")
324
+        else:
325
+            print("Invalid ")
326
+            if form.errors:
327
+                messages.error(request, form.errors)
328
+
329
+        return redirect("fruit:vendor_edit", pk =  instance1.pk)
330
+
331
+    return render(request, 'fruit/vendor_form.html', {'vendor_active': True, 'form': form})
332
+
333
+@login_required
334
+def vendorproduct_create(request, pk):
335
+    stores = request.user.store_created.all().order_by("-created_at")
336
+    print(pk)
337
+    vendor = Vendor.objects.get(pk=pk)
338
+
339
+    form = VendorProductForm()
340
+
341
+    form.fields['product'].queryset = stores[0].product_set.all().order_by("-created_at")
342
+
343
+    if request.method == "POST":
344
+        form = VendorProductForm(request.POST)
345
+        if form.is_valid():
346
+
347
+            instance1 = form.save(commit=False)
348
+            instance1.store = stores[0]
349
+            instance1.vendor = vendor
350
+            instance1.created_by = request.user
351
+            instance1.save()
352
+            '''
353
+            print(instances)
354
+            for s in instances:
355
+                s.product = instance1
356
+                s.save()
357
+            '''
358
+            messages.success(request, "Sale Save")
359
+        else:
360
+            print("Invalid ")
361
+            if form.errors:
362
+                messages.error(request, form.errors)
363
+
364
+        return redirect("fruit:vendorproduct_edit", pk =  instance1.pk)
365
+
366
+    return render(request, 'fruit/vendorproduct_form.html', {'vendor_active': True, 'form': form, 'vendor': vendor})
367
+
368
+@login_required
369
+def vendorproduct_edit(request, pk):
370
+    stores = request.user.store_created.all().order_by("-created_at")
371
+
372
+    obj = VendorProduct.objects.get(pk=pk)
373
+    form = VendorProductForm(instance = obj)
374
+    vendor = obj.vendor
375
+
376
+    form.fields['product'].queryset = stores[0].product_set.all().order_by("-created_at")
377
+
378
+    if request.method == "POST":
379
+        form = VendorProductForm(request.POST)
380
+        if form.is_valid():
381
+            instance1 = form.save()
382
+
383
+            '''
384
+            print(instances)
385
+            for s in instances:
386
+                s.product = instance1
387
+                s.save()
388
+            '''
389
+            messages.success(request, "Vendor Product Save")
390
+        else:
391
+            print("Invalid ")
392
+            if form.errors:
393
+                messages.error(request, form.errors)
394
+
395
+        return redirect("fruit:vendorproduct_edit", pk =  int(pk))
396
+
397
+    return render(request, 'fruit/vendorproduct_form.html', {'vendor_active': True, 'form': form, 'obj': obj, 'vendor': vendor})
398
+
399
+#vendor order
400
+@login_required
401
+def vendororder_index(request):
402
+    stores = request.user.store_created.all().order_by("-created_at")
403
+    o_qs = stores[0].vendororder_set.all().order_by("-created_at")
404
+
405
+    f = VendorOrderFilter(request.GET, queryset=o_qs)
406
+
407
+    paginator = Paginator(f.qs, 25)
408
+    page_number = request.GET.get('page')
409
+    page_obj = paginator.get_page(page_number)
410
+
411
+    return render(request, 'fruit/vendororder_index.html', {'o_qs': o_qs, 'vendor_active': True, 'page_obj': page_obj, 'filter': f})
412
+
413
+
414
+@login_required
415
+def vendororder_edit(request, pk):
416
+    stores = request.user.store_created.all().order_by("-created_at")
417
+
418
+    obj = VendorOrder.objects.get(pk=pk)
419
+    form = VendorOrderForm(instance = obj)
420
+
421
+    #form.fields['product'].queryset = stores[0].product_set.all().order_by("-created_at")
422
+
423
+    if request.method == "POST":
424
+        form = VendorOrderForm(request.POST)
425
+        if form.is_valid():
426
+            instance1 = form.save()
427
+            '''
428
+            print(instances)
429
+            for s in instances:
430
+                s.product = instance1
431
+                s.save()
432
+            '''
433
+            messages.success(request, "Sale Save")
434
+        else:
435
+            print("Invalid ")
436
+            if form.errors:
437
+                messages.error(request, form.errors)
438
+
439
+        return redirect("fruit:vendororder_edit", pk =  int(pk))
440
+
441
+    return render(request, 'fruit/vendororder_form.html', {'vendor_active': True, 'form': form, 'object': obj})
442
+
443
+@login_required
444
+def vendororder_create(request):
445
+    stores = request.user.store_created.all().order_by("-created_at")
446
+
447
+    form = VendorOrderForm()
448
+
449
+
450
+    if request.method == "POST":
451
+        form = VendorOrderForm(request.POST)
452
+        if form.is_valid():
453
+
454
+            instance1 = form.save(commit=False)
455
+            instance1.store = stores[0]
456
+            instance1.save()
457
+            '''
458
+            print(instances)
459
+            for s in instances:
460
+                s.product = instance1
461
+                s.save()
462
+            '''
463
+            messages.success(request, "Vendor Order Save")
464
+            return redirect("fruit:vendororder_edit", pk =  instance1.pk)
465
+        else:
466
+            print("Invalid ")
467
+            if form.errors:
468
+                messages.error(request, form.errors)
469
+
470
+
471
+    return render(request, 'fruit/vendororder_form.html', {'vendororder_active': True, 'form': form})
472
+
248 473
 def signup(request):
249 474
     if request.method == 'POST':
250 475
         form = UserCreationForm(request.POST)