vyapari 0.1.5dev9 → 0.1.5dev10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|