瀏覽代碼

vendor product edit

tum 4 年之前
父節點
當前提交
7db1ef0b8f

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

142
 .form-legend {
142
 .form-legend {
143
     width:auto !important;
143
     width:auto !important;
144
 }
144
 }
145
+
146
+.multiField {
147
+    border:1px solid #ccc;
148
+}

+ 17 - 1
app/fruit/admin.py

2
 
2
 
3
 from django.contrib import admin
3
 from django.contrib import admin
4
 from django.contrib.gis.admin import OSMGeoAdmin
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
 # Register your models here.
6
 # Register your models here.
7
 
7
 
8
 from django_google_maps import widgets as map_widgets
8
 from django_google_maps import widgets as map_widgets
30
         map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
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
 @admin.register(Buyer)
49
 @admin.register(Buyer)
34
 class BuyerAdmin(UtilModel, admin.ModelAdmin):
50
 class BuyerAdmin(UtilModel, admin.ModelAdmin):
35
     search_fields = ('name',)
51
     search_fields = ('name',)

+ 34 - 1
app/fruit/forms.py

1
 from django.forms.models import inlineformset_factory, modelform_factory, modelformset_factory
1
 from django.forms.models import inlineformset_factory, modelform_factory, modelformset_factory
2
 from django import forms
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
 from django.forms import ModelForm
4
 from django.forms import ModelForm
5
 from django_google_maps import widgets as map_widgets
5
 from django_google_maps import widgets as map_widgets
6
 from django_google_maps import fields as map_fields
6
 from django_google_maps import fields as map_fields
49
     widgets = GeneralWidgets,
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
 PhotoFormSet = modelformset_factory(
73
 PhotoFormSet = modelformset_factory(
53
     Photo,
74
     Photo,
54
     fields="__all__",
75
     fields="__all__",
59
 
80
 
60
 InlinePhotoFormset = inlineformset_factory(Product, Photo,  fields="__all__", widgets= GeneralWidgets)
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
 class ProductFilter(django_filters.FilterSet):
86
 class ProductFilter(django_filters.FilterSet):
64
     class Meta:
87
     class Meta:
75
         model = Inbox
98
         model = Inbox
76
         fields = ['store', 'product', 'buyer', 'subject', 'body', 'tel', 'status', 'created_at']
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

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

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

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

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

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

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

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

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
         return f"{self.name} Tel.:{self.tel} Email:{self.email}"
108
         return f"{self.name} Tel.:{self.tel} Email:{self.email}"
109
 
109
 
110
 class Inbox(GenericModel, models.Model):
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
     subject = models.CharField(max_length=200)
115
     subject = models.CharField(max_length=200)
116
     body = models.TextField(blank=False)
116
     body = models.TextField(blank=False)
171
     code = models.CharField(max_length=200)
171
     code = models.CharField(max_length=200)
172
     product_type = TreeForeignKey('ProductType', on_delete=models.SET_NULL, null=True)
172
     product_type = TreeForeignKey('ProductType', on_delete=models.SET_NULL, null=True)
173
     description = models.TextField(blank=True, null=True)
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
     price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
175
     price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
176
 
176
 
177
 
177
 
183
     def __str__(self):
183
     def __str__(self):
184
         return f"{self.name} {self.code}"
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
 class Vendor(GenericModel, models.Model ):
194
 class Vendor(GenericModel, models.Model ):
187
     name = models.CharField(max_length=200)
195
     name = models.CharField(max_length=200)
188
     code = models.CharField(max_length=200)
196
     code = models.CharField(max_length=200)
189
     #product_type = TreeForeignKey('ProductType', on_delete=models.SET_NULL, null=True)
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
     description = models.TextField(blank=True, null=True)
200
     description = models.TextField(blank=True, null=True)
192
     store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False)
201
     store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False)
193
     price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
202
     price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
211
         return f"{self.name} {self.code}"
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
 class ProductSKU(GenericModel, models.Model ):
249
 class ProductSKU(GenericModel, models.Model ):
215
     sku = models.CharField(max_length=200)
250
     sku = models.CharField(max_length=200)
216
     product  = models.ForeignKey('Product', on_delete=models.CASCADE, null=True)
251
     product  = models.ForeignKey('Product', on_delete=models.CASCADE, null=True)

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

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>
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
     <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>
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
     <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>
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
   </div>
27
   </div>
27
   <div class="tab-content p-3 col-md-9 col-lg-10" id="v-pills-tabContent">
28
   <div class="tab-content p-3 col-md-9 col-lg-10" id="v-pills-tabContent">
28
       {% block breadcrumbs %}
29
       {% block breadcrumbs %}

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

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

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

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

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

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

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

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
     path('sales/<pk>', views.sale_edit, name='sale_edit'),
15
     path('sales/<pk>', views.sale_edit, name='sale_edit'),
16
     path('inbox/', views.inbox_index, name='inbox_index'),
16
     path('inbox/', views.inbox_index, name='inbox_index'),
17
     path('inbox/<pk>', views.inbox_edit, name='inbox_edit'),
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
     path('signup', views.signup, name='signup'),
26
     path('signup', views.signup, name='signup'),
19
 ]
27
 ]
20
 
28
 

+ 228 - 3
app/fruit/views.py

6
 from django.urls import reverse
6
 from django.urls import reverse
7
 from django.contrib.auth.decorators import login_required
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
 from django.contrib import messages
12
 from django.contrib import messages
12
 from django.core.paginator import Paginator
13
 from django.core.paginator import Paginator
13
 
14
 
115
             messages.success(request, "Product Save")
116
             messages.success(request, "Product Save")
116
             return redirect("fruit:edit_sku", pk=i.pk)
117
             return redirect("fruit:edit_sku", pk=i.pk)
117
         else:
118
         else:
118
-            message.error(request, "SKU  created failed")
119
+            messages.error(request, form.errors)
119
             return redirect("fruit:create_sku", pk=int(pk))
120
             return redirect("fruit:create_sku", pk=int(pk))
120
 
121
 
121
     return render(request, 'fruit/sku_form.html', {'form': form, 'pid': p.pk})
122
     return render(request, 'fruit/sku_form.html', {'form': form, 'pid': p.pk})
245
 
246
 
246
     return render(request, 'fruit/inbox_form.html', {'inbox_active': True, 'form': form, 'object': obj})
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
 def signup(request):
473
 def signup(request):
249
     if request.method == 'POST':
474
     if request.method == 'POST':
250
         form = UserCreationForm(request.POST)
475
         form = UserCreationForm(request.POST)