vyapari 0.1.5dev9 → 0.1.5dev10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/vyapari/store_manager/base_controller.rb +3 -0
- data/app/controllers/vyapari/store_manager/dashboard_controller.rb +1 -0
- data/app/controllers/vyapari/store_manager/reports/invoices_controller.rb +206 -101
- data/app/controllers/vyapari/store_manager/reports/sales_controller.rb +299 -0
- data/app/controllers/vyapari/store_manager/reports/stock_controller.rb +1 -1
- data/app/controllers/vyapari/terminal_staff/dashboard_controller.rb +2 -1
- data/app/models/bank_account.rb +44 -0
- data/app/models/brand.rb +8 -13
- data/app/models/category.rb +3 -3
- data/app/models/contact.rb +72 -0
- data/app/models/country.rb +6 -4
- data/app/models/exchange_rate.rb +2 -2
- data/app/models/invoice.rb +12 -8
- data/app/models/line_item.rb +3 -3
- data/app/models/product.rb +3 -3
- data/app/models/region.rb +11 -17
- data/app/models/stock_bundle.rb +4 -4
- data/app/models/stock_entry.rb +8 -7
- data/app/models/store.rb +52 -21
- data/app/models/supplier.rb +19 -25
- data/app/models/terminal.rb +3 -3
- data/app/models/vyapari/application_record.rb +1 -2
- data/app/views/layouts/vyapari/_store_manager_menu.html.erb +24 -5
- data/app/views/layouts/vyapari/_terminal_staff_menu.html.erb +6 -3
- data/app/views/layouts/vyapari/store_manager.html.erb +4 -4
- data/app/views/vyapari/store_manager/dashboard/_sales_counts.html.erb +90 -0
- data/app/views/vyapari/store_manager/dashboard/_stock_counts.html.erb +63 -0
- data/app/views/vyapari/store_manager/dashboard/_terminals.html.erb +23 -0
- data/app/views/vyapari/store_manager/dashboard/index.html.erb +51 -79
- data/app/views/vyapari/store_manager/reports/invoices/_index.html.erb +65 -0
- data/app/views/vyapari/store_manager/reports/invoices/index.html.erb +105 -0
- data/app/views/vyapari/store_manager/reports/sales/_index.html.erb +64 -0
- data/app/views/vyapari/store_manager/reports/sales/index.html.erb +105 -0
- data/app/views/vyapari/terminal_staff/dashboard/_counts.html.erb +61 -18
- data/config/routes.rb +2 -0
- data/db/migrate/20170000000203_create_contacts.rb +1 -1
- data/db/migrate/20170000000206_create_stores.rb +1 -1
- data/lib/vyapari/version.rb +1 -1
- metadata +16 -6
@@ -4,6 +4,7 @@ module Vyapari
|
|
4
4
|
|
5
5
|
# GET /dashboard
|
6
6
|
def index
|
7
|
+
@date = params[:date] ? Date.parse(params[:date]) : Date.today
|
7
8
|
end
|
8
9
|
|
9
10
|
def search
|
@@ -19,7 +20,7 @@ module Vyapari
|
|
19
20
|
description: "#{@store.name}",
|
20
21
|
links: [
|
21
22
|
{name: "Home", link: user_dashboard_path, icon: 'fa-building-o'},
|
22
|
-
{name: @terminal.name, link: terminal_staff_dashboard_path(@store), icon: 'fa-desktop'}
|
23
|
+
{name: @terminal.name, link: terminal_staff_dashboard_path(@store), icon: 'fa-desktop', active: true}
|
23
24
|
]
|
24
25
|
}
|
25
26
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class BankAccount < Vyapari::ApplicationRecord
|
2
|
+
|
3
|
+
# Validations
|
4
|
+
validates :account_number, presence: true
|
5
|
+
#validates :email, length: {maximum: 128}, allow_blank: true
|
6
|
+
#validates :phone, length: {maximum: 128}, allow_blank: true
|
7
|
+
|
8
|
+
# Associations
|
9
|
+
belongs_to :bank_accountable, :polymorphic => true
|
10
|
+
|
11
|
+
# ------------------
|
12
|
+
# Class Methods
|
13
|
+
# ------------------
|
14
|
+
|
15
|
+
# return an active record relation object with the search query in its where clause
|
16
|
+
# Return the ActiveRecord::Relation object
|
17
|
+
# == Examples
|
18
|
+
# >>> obj.search(query)
|
19
|
+
# => ActiveRecord::Relation object
|
20
|
+
scope :search, lambda {|query| joins(:country).where("LOWER(bank_accounts.account_number) LIKE LOWER('%#{query}%') OR
|
21
|
+
LOWER(bank_accounts.iban) LIKE LOWER('%#{query}%') OR
|
22
|
+
LOWER(bank_accounts.ifsc_swiftcode) LIKE LOWER('%#{query}%') OR
|
23
|
+
LOWER(bank_accounts.bank_name) LIKE LOWER('%#{query}%') OR
|
24
|
+
LOWER(bank_accounts.city) LIKE LOWER('%#{query}%') OR
|
25
|
+
LOWER(countries.name) LIKE LOWER('%#{query}%')
|
26
|
+
")}
|
27
|
+
|
28
|
+
# ------------------
|
29
|
+
# Instance Methods
|
30
|
+
# ------------------
|
31
|
+
|
32
|
+
def display_name
|
33
|
+
self.account_number_was
|
34
|
+
end
|
35
|
+
|
36
|
+
def can_be_edited?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def can_be_deleted?
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/app/models/brand.rb
CHANGED
@@ -5,15 +5,15 @@ class Brand < Vyapari::ApplicationRecord
|
|
5
5
|
UNPUBLISHED = "unpublished"
|
6
6
|
REMOVED = "removed"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
STATUS = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
|
9
|
+
STATUS_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
|
10
10
|
|
11
11
|
FEATURED_HASH = {"Featured" => true, "Non Featured" => false}
|
12
12
|
FEATURED_HASH_REVERSE = {true => "Featured", false => "Non Featured"}
|
13
13
|
|
14
14
|
# Validations
|
15
|
-
validates :name, :presence=> true, uniqueness: true
|
16
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
15
|
+
validates :name, :presence=> true, uniqueness: true, length: {minimum: 3, maximum: 250}
|
16
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
17
17
|
|
18
18
|
# Associations
|
19
19
|
has_one :brand_image, :as => :imageable, :dependent => :destroy, :class_name => "Image::BrandImage"
|
@@ -32,16 +32,18 @@ class Brand < Vyapari::ApplicationRecord
|
|
32
32
|
# => ActiveRecord::Relation object
|
33
33
|
scope :search, lambda { |query| where("LOWER(name) LIKE LOWER('%#{query}%')")
|
34
34
|
}
|
35
|
-
|
36
|
-
scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
|
37
35
|
scope :featured, lambda { |val| where(featured: val) }
|
38
36
|
|
37
|
+
scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
|
39
38
|
scope :published, -> { where(status: PUBLISHED) }
|
40
39
|
scope :unpublished, -> { where(status: UNPUBLISHED) }
|
41
40
|
scope :removed, -> { where(status: REMOVED) }
|
42
41
|
|
43
42
|
scope :this_month, lambda { where("created_at >= ? AND created_at <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
|
44
43
|
|
44
|
+
# Import Methods
|
45
|
+
# --------------
|
46
|
+
|
45
47
|
def self.save_row_data(row)
|
46
48
|
|
47
49
|
row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
|
@@ -155,13 +157,6 @@ class Brand < Vyapari::ApplicationRecord
|
|
155
157
|
|
156
158
|
def can_be_deleted?
|
157
159
|
removed? && self.products.blank?
|
158
|
-
#if self.jobs.any?
|
159
|
-
# self.errors.add(:base, DELETE_MESSAGE)
|
160
|
-
# return false
|
161
|
-
#else
|
162
|
-
# return true
|
163
|
-
#end
|
164
|
-
#return true
|
165
160
|
end
|
166
161
|
|
167
162
|
end
|
data/app/models/category.rb
CHANGED
@@ -5,8 +5,8 @@ class Category < Vyapari::ApplicationRecord
|
|
5
5
|
UNPUBLISHED = "unpublished"
|
6
6
|
REMOVED = "removed"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
STATUS = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
|
9
|
+
STATUS_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
|
10
10
|
|
11
11
|
FEATURED_HASH = {"Featured" => true, "Non Featured" => false}
|
12
12
|
FEATURED_HASH_REVERSE = {true => "Featured", false => "Non Featured"}
|
@@ -14,7 +14,7 @@ class Category < Vyapari::ApplicationRecord
|
|
14
14
|
# Validations
|
15
15
|
validates :name, presence: true, uniqueness: true
|
16
16
|
validates :one_liner, presence: false
|
17
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
17
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
18
18
|
|
19
19
|
# Associations
|
20
20
|
has_many :products
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class Contact < Vyapari::ApplicationRecord
|
2
|
+
|
3
|
+
# Validations
|
4
|
+
validates :name, presence: true, length: {minimum: 2, maximum: 250}, allow_blank: false
|
5
|
+
validates :email, length: {maximum: 128}, allow_blank: true
|
6
|
+
validates :phone, length: {maximum: 128}, allow_blank: true
|
7
|
+
|
8
|
+
# Associations
|
9
|
+
belongs_to :contactable, :polymorphic => true
|
10
|
+
|
11
|
+
# ------------------
|
12
|
+
# Class Methods
|
13
|
+
# ------------------
|
14
|
+
|
15
|
+
# return an active record relation object with the search query in its where clause
|
16
|
+
# Return the ActiveRecord::Relation object
|
17
|
+
# == Examples
|
18
|
+
# >>> obj.search(query)
|
19
|
+
# => ActiveRecord::Relation object
|
20
|
+
scope :search, lambda {|query| where("LOWER(contacts.name) LIKE LOWER('%#{query}%') OR
|
21
|
+
LOWER(contacts.email) LIKE LOWER('%#{query}%') OR
|
22
|
+
LOWER(contacts.phone) LIKE LOWER('%#{query}%') OR
|
23
|
+
LOWER(contacts.landline) LIKE LOWER('%#{query}%') OR
|
24
|
+
LOWER(contacts.fax) LIKE LOWER('%#{query}%') OR
|
25
|
+
LOWER(contacts.designation) LIKE LOWER('%#{query}%')
|
26
|
+
")}
|
27
|
+
|
28
|
+
# Import Methods
|
29
|
+
# --------------
|
30
|
+
|
31
|
+
# TODO - this is yet to be done
|
32
|
+
def self.save_row_data(row)
|
33
|
+
|
34
|
+
row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
|
35
|
+
|
36
|
+
return if row[:name].blank?
|
37
|
+
|
38
|
+
country = Contact.find_by_code(row[:code]) || Contact.new
|
39
|
+
country.name = row[:name]
|
40
|
+
country.code = row[:code]
|
41
|
+
|
42
|
+
# Initializing error hash for displaying all errors altogether
|
43
|
+
error_object = Kuppayam::Importer::ErrorHash.new
|
44
|
+
|
45
|
+
if country.valid?
|
46
|
+
country.save!
|
47
|
+
else
|
48
|
+
summary = "Error while saving country: #{country.name}"
|
49
|
+
details = "Error! #{country.errors.full_messages.to_sentence}"
|
50
|
+
error_object.errors << { summary: summary, details: details }
|
51
|
+
end
|
52
|
+
|
53
|
+
return error_object
|
54
|
+
end
|
55
|
+
|
56
|
+
# ------------------
|
57
|
+
# Instance Methods
|
58
|
+
# ------------------
|
59
|
+
|
60
|
+
def display_name
|
61
|
+
self.name_was
|
62
|
+
end
|
63
|
+
|
64
|
+
def can_be_edited?
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
def can_be_deleted?
|
69
|
+
false
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/app/models/country.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
class Country < Vyapari::ApplicationRecord
|
2
2
|
|
3
3
|
# Validations
|
4
|
-
validates :name, presence: true, length: {minimum: 2, maximum:
|
5
|
-
validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum:
|
4
|
+
validates :name, presence: true, length: {minimum: 2, maximum: 128}, allow_blank: false
|
5
|
+
validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 16}, allow_blank: false
|
6
6
|
|
7
7
|
# Associations
|
8
8
|
has_many :regions
|
@@ -19,6 +19,9 @@ class Country < Vyapari::ApplicationRecord
|
|
19
19
|
# => ActiveRecord::Relation object
|
20
20
|
scope :search, lambda {|query| where("LOWER(countries.name) LIKE LOWER('%#{query}%')")}
|
21
21
|
|
22
|
+
# Import Methods
|
23
|
+
# --------------
|
24
|
+
|
22
25
|
def self.save_row_data(row)
|
23
26
|
|
24
27
|
row.headers.each{ |cell| row[cell] = row[cell].to_s.strip }
|
@@ -56,8 +59,7 @@ class Country < Vyapari::ApplicationRecord
|
|
56
59
|
end
|
57
60
|
|
58
61
|
def can_be_deleted?
|
59
|
-
if self.regions.any?
|
60
|
-
#self.errors.add(:base, DELETE_MESSAGE)
|
62
|
+
if self.regions.any? || self.stores.any?
|
61
63
|
return false
|
62
64
|
else
|
63
65
|
return true
|
data/app/models/exchange_rate.rb
CHANGED
@@ -3,7 +3,7 @@ class ExchangeRate < Vyapari::ApplicationRecord
|
|
3
3
|
# Validations
|
4
4
|
validates :base_currency, presence: true, length: {minimum: 2, maximum: 6}, allow_blank: false
|
5
5
|
validates :counter_currency, presence: true, length: {minimum: 2, maximum: 6}, allow_blank: false
|
6
|
-
validates :value, presence: true
|
6
|
+
validates :value, presence: true, numericality: { greater_than: 0 }
|
7
7
|
validates :effective_date, presence: true
|
8
8
|
|
9
9
|
# ------------------
|
@@ -15,7 +15,7 @@ class ExchangeRate < Vyapari::ApplicationRecord
|
|
15
15
|
# == Examples
|
16
16
|
# >>> obj.search(query)
|
17
17
|
# => ActiveRecord::Relation object
|
18
|
-
scope :search, lambda {|query| where("LOWER(base_currency) LIKE LOWER('%#{query}%') OR LOWER(counter_currency) LIKE LOWER('%#{query}%')")}
|
18
|
+
scope :search, lambda {|query| where("LOWER(exchange_rates.base_currency) LIKE LOWER('%#{query}%') OR LOWER(exchange_rates.counter_currency) LIKE LOWER('%#{query}%')")}
|
19
19
|
|
20
20
|
def self.save_row_data(row)
|
21
21
|
|
data/app/models/invoice.rb
CHANGED
@@ -10,8 +10,11 @@ class Invoice < Vyapari::ApplicationRecord
|
|
10
10
|
CREDIT_CARD = "credit_card"
|
11
11
|
CHEQUE = "cheque"
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
STATUS = {"Draft" => DRAFT, "Active" => ACTIVE, "Cancelled" => CANCELLED}
|
14
|
+
STATUS_REVERSE = {DRAFT => "Draft", ACTIVE => "Active", CANCELLED => "Cancelled"}
|
15
|
+
|
16
|
+
PAYMENT_METHOD = {"Cash" => CASH, "Credit" => CREDIT, "Credit Card" => CREDIT_CARD, "Cheque" => CHEQUE}
|
17
|
+
PAYMENT_METHOD_REVERSE = {CASH => "Cash", CREDIT => "Credid", CREDIT_CARD => "Credit Card", CHEQUE => "Cheque"}
|
15
18
|
|
16
19
|
# Call backs
|
17
20
|
before_save :calculate_gross_total_amount
|
@@ -20,7 +23,7 @@ class Invoice < Vyapari::ApplicationRecord
|
|
20
23
|
validates :invoice_number, :presence=> true
|
21
24
|
validates :invoice_date, :presence=> true
|
22
25
|
|
23
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
26
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
24
27
|
|
25
28
|
# Associations
|
26
29
|
belongs_to :terminal
|
@@ -40,7 +43,7 @@ class Invoice < Vyapari::ApplicationRecord
|
|
40
43
|
# == Examples
|
41
44
|
# >>> invoice.search(query)
|
42
45
|
# => ActiveRecord::Relation object
|
43
|
-
scope :search, lambda { |query| where("LOWER(invoice_number) LIKE LOWER('%#{query}%') OR LOWER(customer_name) LIKE LOWER('%#{query}%') OR LOWER(customer_address) LIKE LOWER('%#{query}%')")
|
46
|
+
scope :search, lambda { |query| where("LOWER(invoice_number) LIKE LOWER('%#{query}%') OR LOWER(notes) LIKE LOWER('%#{query}%') OR LOWER(credit_card_number) LIKE LOWER('%#{query}%') OR LOWER(cheque_number) LIKE LOWER('%#{query}%') OR LOWER(customer_name) LIKE LOWER('%#{query}%') OR LOWER(customer_address) LIKE LOWER('%#{query}%') OR LOWER(net_total_amount) LIKE LOWER('%#{query}%')")
|
44
47
|
}
|
45
48
|
|
46
49
|
scope :status, lambda { |status| where("LOWER(status)='#{status}'") }
|
@@ -54,10 +57,11 @@ class Invoice < Vyapari::ApplicationRecord
|
|
54
57
|
scope :credit_card_invoices, -> { where(payment_method: CREDIT_CARD) }
|
55
58
|
scope :cheque_invoices, -> { where(payment_method: CHEQUE) }
|
56
59
|
|
57
|
-
scope :payment_method, lambda { |pm| where("LOWER(payment_method)
|
60
|
+
scope :payment_method, lambda { |pm| where("LOWER(payment_method)=?", ) }
|
58
61
|
|
59
|
-
scope :this_month, lambda { where("
|
60
|
-
scope :today, lambda { where('DATE(
|
62
|
+
scope :this_month, lambda { where("invoice_date >= ? AND invoice_date <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
|
63
|
+
scope :today, lambda { where('DATE(invoice_date) = ?', Date.current.in_time_zone)}
|
64
|
+
scope :dated, lambda { |d| where('DATE(invoice_date) = ?', d)}
|
61
65
|
|
62
66
|
# ------------------
|
63
67
|
# Instance Methods
|
@@ -78,7 +82,7 @@ class Invoice < Vyapari::ApplicationRecord
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def display_status
|
81
|
-
|
85
|
+
STATUS_REVERSE[self.status]
|
82
86
|
end
|
83
87
|
|
84
88
|
def display_payment_method
|
data/app/models/line_item.rb
CHANGED
@@ -7,8 +7,8 @@ class LineItem < Vyapari::ApplicationRecord
|
|
7
7
|
RETURNED = "returned"
|
8
8
|
CANCELLED = "cancelled"
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
STATUS = {"Draft" => DRAFT, "Sold" => SOLD, "Damaged" => DAMAGED, "Returned" => RETURNED, "Cancelled" => CANCELLED}
|
11
|
+
STATUS_REVERSE = {DRAFT => "Draft", SOLD => "Sold", DAMAGED => "Damaged", RETURNED => "Returned", CANCELLED => "Cancelled"}
|
12
12
|
|
13
13
|
# Call backs
|
14
14
|
before_save :calculate_total_amount
|
@@ -18,7 +18,7 @@ class LineItem < Vyapari::ApplicationRecord
|
|
18
18
|
validates :quantity, :presence=> true
|
19
19
|
validates :rate, :presence=> true
|
20
20
|
|
21
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
21
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
22
22
|
|
23
23
|
# Associations
|
24
24
|
belongs_to :product, optional: true
|
data/app/models/product.rb
CHANGED
@@ -5,8 +5,8 @@ class Product < Vyapari::ApplicationRecord
|
|
5
5
|
UNPUBLISHED = "unpublished"
|
6
6
|
REMOVED = "removed"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
STATUS = {"Published" => PUBLISHED, "Unpublished" => UNPUBLISHED, "Removed" => REMOVED}
|
9
|
+
STATUS_REVERSE = {PUBLISHED => "Published", UNPUBLISHED => "Unpublished", REMOVED => "Removed"}
|
10
10
|
|
11
11
|
FEATURED_HASH = {"Featured" => true, "Non Featured" => false}
|
12
12
|
FEATURED_HASH_REVERSE = {true => "Featured", false => "Non Featured"}
|
@@ -19,7 +19,7 @@ class Product < Vyapari::ApplicationRecord
|
|
19
19
|
validates :ean_sku, presence: true
|
20
20
|
|
21
21
|
#validates :description, presence: true
|
22
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
22
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
23
23
|
|
24
24
|
# Associations
|
25
25
|
has_one :product_image, :as => :imageable, :dependent => :destroy, :class_name => "Image::ProductImage"
|
data/app/models/region.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
class Region < Vyapari::ApplicationRecord
|
2
2
|
|
3
3
|
# Validations
|
4
|
-
validates :name, presence: true, length: {minimum: 2, maximum:
|
5
|
-
validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum:
|
4
|
+
validates :name, presence: true, length: {minimum: 2, maximum: 128}, allow_blank: false
|
5
|
+
validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 16}, allow_blank: false
|
6
6
|
validates :country, presence: true
|
7
7
|
|
8
8
|
# Associations
|
@@ -18,7 +18,10 @@ class Region < Vyapari::ApplicationRecord
|
|
18
18
|
# == Examples
|
19
19
|
# >>> obj.search(query)
|
20
20
|
# => ActiveRecord::Relation object
|
21
|
-
scope :search, lambda {|query| joins(:country).where("LOWER(
|
21
|
+
scope :search, lambda {|query| joins(:country).where("LOWER(regions.name) LIKE LOWER('%#{query}%') OR LOWER(countries.name) LIKE LOWER('%#{query}%')")}
|
22
|
+
|
23
|
+
# Import Methods
|
24
|
+
# --------------
|
22
25
|
|
23
26
|
def self.save_row_data(row)
|
24
27
|
|
@@ -62,20 +65,11 @@ class Region < Vyapari::ApplicationRecord
|
|
62
65
|
end
|
63
66
|
|
64
67
|
def can_be_deleted?
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
# end
|
71
|
-
return true
|
72
|
-
end
|
73
|
-
|
74
|
-
def report_heading
|
75
|
-
rh = []
|
76
|
-
rh << self.company.try(:name) if self.company.name
|
77
|
-
rh << self.display_name
|
78
|
-
rh.join(", ")
|
68
|
+
if self.stores.any?
|
69
|
+
return false
|
70
|
+
else
|
71
|
+
return true
|
72
|
+
end
|
79
73
|
end
|
80
74
|
|
81
75
|
end
|
data/app/models/stock_bundle.rb
CHANGED
@@ -7,13 +7,13 @@ class StockBundle < ActiveRecord::Base
|
|
7
7
|
ERRORED = "errored"
|
8
8
|
APPROVED = "approved"
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
STATUS = {"Pending" => PENDING, "Approved" => APPROVED, "Errored" => ERRORED}
|
11
|
+
STATUS_REVERSE = {PENDING => "Pending", APPROVED => "Approved", ERRORED => "Errored"}
|
12
12
|
|
13
13
|
# Validations
|
14
14
|
validates :name, :presence=> true, uniqueness: true
|
15
15
|
validates :uploaded_date, presence: true
|
16
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
16
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
17
17
|
# validates :file, :presence=> true
|
18
18
|
|
19
19
|
# Associations
|
@@ -163,7 +163,7 @@ class StockBundle < ActiveRecord::Base
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def display_status
|
166
|
-
|
166
|
+
STATUS_REVERSE[self.status]
|
167
167
|
end
|
168
168
|
|
169
169
|
def display_file_name
|
data/app/models/stock_entry.rb
CHANGED
@@ -9,14 +9,14 @@ class StockEntry < Vyapari::ApplicationRecord
|
|
9
9
|
RESERVED = "reserved"
|
10
10
|
PENDING = "pending"
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
STATUS = {"Active" => ACTIVE, "Sold" => SOLD, "Damaged" => DAMAGED, "Received" => RECEIVED, "Reserved" => RESERVED, "Pending" => PENDING, "Returned" => RETURNED}
|
13
|
+
STATUS_REVERSE = {ACTIVE => "Active", SOLD => "Sold", DAMAGED => "Damaged", RECEIVED => "Received", RESERVED => "Reserved", PENDING => "Pending", RETURNED => "Returned"}
|
14
14
|
|
15
15
|
# Validations
|
16
16
|
validates :store, presence: true
|
17
17
|
validates :product, presence: true
|
18
18
|
validates :quantity, presence: true, numericality: true
|
19
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
19
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
20
20
|
|
21
21
|
# Associations
|
22
22
|
belongs_to :store
|
@@ -50,8 +50,9 @@ class StockEntry < Vyapari::ApplicationRecord
|
|
50
50
|
scope :reserved, -> { where(status: RESERVED) }
|
51
51
|
scope :in_stock, -> { where(status: [ACTIVE, RECEIVED, RETURNED]) }
|
52
52
|
|
53
|
-
scope :this_month, lambda { where("
|
54
|
-
scope :today, lambda { where('DATE(
|
53
|
+
scope :this_month, lambda { joins(:invoice).where("invoices.invoice_date >= ? AND invoices.invoice_date <= ?", Time.zone.now.beginning_of_month, Time.zone.now.end_of_month) }
|
54
|
+
scope :today, lambda { joins(:invoice).where('DATE(invoices.invoice_date) = ?', Date.current.in_time_zone)}
|
55
|
+
scope :dated, lambda { |d| joins(:invoice).where('DATE(invoices.invoice_date) = ?', d)}
|
55
56
|
|
56
57
|
def self.save_row_data(row)
|
57
58
|
|
@@ -112,11 +113,11 @@ class StockEntry < Vyapari::ApplicationRecord
|
|
112
113
|
end
|
113
114
|
|
114
115
|
def display_store_type
|
115
|
-
|
116
|
+
STATUS[self.status]
|
116
117
|
end
|
117
118
|
|
118
119
|
def display_status
|
119
|
-
|
120
|
+
STATUS_REVERSE[self.status]
|
120
121
|
end
|
121
122
|
|
122
123
|
def slug
|
data/app/models/store.rb
CHANGED
@@ -5,8 +5,8 @@ class Store < Vyapari::ApplicationRecord
|
|
5
5
|
INACTIVE = "inactive"
|
6
6
|
CLOSED = "closed"
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
STATUS = {"Active" => ACTIVE, "Inactive" => INACTIVE, "Closed" => CLOSED}
|
9
|
+
STATUS_REVERSE = {ACTIVE => "Active", INACTIVE => "Inactive", CLOSED => "Closed"}
|
10
10
|
|
11
11
|
# Constants
|
12
12
|
WAREHOUSE = "warehouse"
|
@@ -26,15 +26,18 @@ class Store < Vyapari::ApplicationRecord
|
|
26
26
|
validates :name, presence: true, length: {minimum: 2, maximum: 250}, allow_blank: false
|
27
27
|
validates :code, presence: true, uniqueness: true, length: {minimum: 2, maximum: 24}, allow_blank: false
|
28
28
|
validates :store_type, :presence => true, :inclusion => {:in => STORE_TYPES.keys, :presence_of => :store_type, :message => "%{value} is not a valid store type" }
|
29
|
-
validates :status, :presence=> true, :inclusion => {:in =>
|
29
|
+
validates :status, :presence=> true, :inclusion => {:in => STATUS_REVERSE.keys, :presence_of => :status, :message => "%{value} is not a valid status" }
|
30
30
|
|
31
31
|
# Associations
|
32
32
|
belongs_to :region, optional: true
|
33
33
|
belongs_to :country, optional: true
|
34
34
|
|
35
35
|
has_many :terminals
|
36
|
+
has_many :invoices
|
36
37
|
has_many :stock_entries
|
37
38
|
has_many :stock_bundles
|
39
|
+
has_many :products, through: :stock_entries
|
40
|
+
|
38
41
|
|
39
42
|
# ------------------
|
40
43
|
# Class Methods
|
@@ -131,6 +134,33 @@ class Store < Vyapari::ApplicationRecord
|
|
131
134
|
true
|
132
135
|
end
|
133
136
|
|
137
|
+
# Total Counts
|
138
|
+
|
139
|
+
def total_quantity_of_products_in_stock
|
140
|
+
self.stock_entries.active.sum(:quantity) - self.stock_entries.sold.sum(:quantity)
|
141
|
+
end
|
142
|
+
|
143
|
+
def total_no_of_products_in_stock
|
144
|
+
self.stock_entries.active.count
|
145
|
+
# - self.stock_entries.sold.count
|
146
|
+
# self.stock_entries.active.count - self.stock_entries.sold.count
|
147
|
+
#begin
|
148
|
+
# result = Product.select("COUNT(products.id) as id, MAX(se.store_id) as store_id").
|
149
|
+
# joins("LEFT JOIN stock_entries se ON se.product_id = products.id").
|
150
|
+
# where("se.store_id = ?", self.id).
|
151
|
+
# group("products.id")
|
152
|
+
# return result.size.to_i
|
153
|
+
#rescue
|
154
|
+
#0
|
155
|
+
#end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Sold Items Count
|
159
|
+
|
160
|
+
def sold_items_count(date=Date.today)
|
161
|
+
self.stock_entries.dated(date).sold.sum(:quantity)
|
162
|
+
end
|
163
|
+
|
134
164
|
def sold_items_count_for_today
|
135
165
|
self.stock_entries.today.sold.sum(:quantity)
|
136
166
|
end
|
@@ -139,6 +169,12 @@ class Store < Vyapari::ApplicationRecord
|
|
139
169
|
self.stock_entries.this_month.sold.sum(:quantity)
|
140
170
|
end
|
141
171
|
|
172
|
+
# Damaged Items Count
|
173
|
+
|
174
|
+
def damaged_items_count(date=Date.today)
|
175
|
+
self.stock_entries.dated(date).damaged.sum(:quantity)
|
176
|
+
end
|
177
|
+
|
142
178
|
def damaged_items_count_for_today
|
143
179
|
self.stock_entries.today.damaged.sum(:quantity)
|
144
180
|
end
|
@@ -147,6 +183,12 @@ class Store < Vyapari::ApplicationRecord
|
|
147
183
|
self.stock_entries.this_month.damaged.sum(:quantity)
|
148
184
|
end
|
149
185
|
|
186
|
+
# Returned Items Count
|
187
|
+
|
188
|
+
def returned_items_count(date=Date.today)
|
189
|
+
self.stock_entries.dated(date).returned.sum(:quantity)
|
190
|
+
end
|
191
|
+
|
150
192
|
def returned_items_count_for_today
|
151
193
|
self.stock_entries.today.returned.sum(:quantity)
|
152
194
|
end
|
@@ -155,6 +197,12 @@ class Store < Vyapari::ApplicationRecord
|
|
155
197
|
self.stock_entries.this_month.returned.sum(:quantity)
|
156
198
|
end
|
157
199
|
|
200
|
+
# Reserved Items Count
|
201
|
+
|
202
|
+
def reserved_items_count(date=Date.today)
|
203
|
+
self.stock_entries.dated(date).reserved.sum(:quantity)
|
204
|
+
end
|
205
|
+
|
158
206
|
def reserved_items_count_for_today
|
159
207
|
self.stock_entries.today.reserved.sum(:quantity)
|
160
208
|
end
|
@@ -163,24 +211,7 @@ class Store < Vyapari::ApplicationRecord
|
|
163
211
|
self.stock_entries.this_month.reserved.sum(:quantity)
|
164
212
|
end
|
165
213
|
|
166
|
-
|
167
|
-
self.stock_entries.active.sum(:quantity) - self.stock_entries.sold.sum(:quantity)
|
168
|
-
end
|
169
|
-
|
170
|
-
def total_no_of_products_in_stock
|
171
|
-
self.stock_entries.active.count
|
172
|
-
# - self.stock_entries.sold.count
|
173
|
-
# self.stock_entries.active.count - self.stock_entries.sold.count
|
174
|
-
#begin
|
175
|
-
# result = Product.select("COUNT(products.id) as id, MAX(se.store_id) as store_id").
|
176
|
-
# joins("LEFT JOIN stock_entries se ON se.product_id = products.id").
|
177
|
-
# where("se.store_id = ?", self.id).
|
178
|
-
# group("products.id")
|
179
|
-
# return result.size.to_i
|
180
|
-
#rescue
|
181
|
-
#0
|
182
|
-
#end
|
183
|
-
end
|
214
|
+
|
184
215
|
|
185
216
|
|
186
217
|
|