pennylane 0.1.0 → 0.2.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -1
- data/Gemfile.lock +22 -1
- data/README.md +46 -0
- data/lib/pennylane/client.rb +1 -2
- data/lib/pennylane/object.rb +2 -5
- data/lib/pennylane/resources/base.rb +34 -6
- data/lib/pennylane/resources/category.rb +27 -0
- data/lib/pennylane/resources/category_group.rb +16 -0
- data/lib/pennylane/resources/customer.rb +3 -2
- data/lib/pennylane/resources/customer_invoice.rb +45 -0
- data/lib/pennylane/resources/product.rb +22 -0
- data/lib/pennylane/resources/supplier.rb +20 -0
- data/lib/pennylane/util.rb +18 -8
- data/lib/pennylane/version.rb +2 -2
- data/lib/pennylane.rb +6 -1
- data/pennylane.gemspec +1 -0
- metadata +23 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a60c1035dbad731707f86c3e97610c740d286cb8e6f70b7ac30709bbe29a0f0
|
4
|
+
data.tar.gz: b3fd35e53857c0d8df547bb361d4ae69bd1b73a482b7552232ab4cfcce5e8926
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 903f576a32e59f954c68c255ce0aeacf6a820315f233f9825b2d35036cff3ab0928c6ac9fb0e84daa059da40dfde4f1829c5dff61ad58a57a406a3483e69b9e8
|
7
|
+
data.tar.gz: 72ed99e03c1d31ff1a871ebf0d335110c9a0a38a9acc9d8e14ecaf27a50731afef55ce6d1c77d89cbb0f95558eba121938ba8da7b87827e6c2416be10def3c5d
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.0-alpha] - 2024-04-20
|
4
|
+
|
5
|
+
- Support resources
|
6
|
+
- `CategoryGroup`
|
7
|
+
- `Category`
|
8
|
+
- `Product`
|
9
|
+
- Added missing `#create` to `Supplier`
|
10
|
+
- Adding `#update` to `Customer` and `Supplier`
|
11
|
+
|
12
|
+
|
3
13
|
## [0.1.0] - 2024-04-04
|
4
14
|
|
5
|
-
- Initial release
|
15
|
+
- Initial release
|
data/Gemfile.lock
CHANGED
@@ -1,15 +1,33 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pennylane (0.
|
4
|
+
pennylane (0.2.0.pre.alpha)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
activesupport (7.1.3.2)
|
10
|
+
base64
|
11
|
+
bigdecimal
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
+
connection_pool (>= 2.2.5)
|
14
|
+
drb
|
15
|
+
i18n (>= 1.6, < 2)
|
16
|
+
minitest (>= 5.1)
|
17
|
+
mutex_m
|
18
|
+
tzinfo (~> 2.0)
|
9
19
|
ast (2.4.2)
|
20
|
+
base64 (0.2.0)
|
21
|
+
bigdecimal (3.1.7)
|
22
|
+
concurrent-ruby (1.2.3)
|
23
|
+
connection_pool (2.4.1)
|
24
|
+
drb (2.2.1)
|
25
|
+
i18n (1.14.4)
|
26
|
+
concurrent-ruby (~> 1.0)
|
10
27
|
json (2.7.2)
|
11
28
|
language_server-protocol (3.17.0.3)
|
12
29
|
minitest (5.22.3)
|
30
|
+
mutex_m (0.2.0)
|
13
31
|
parallel (1.24.0)
|
14
32
|
parser (3.3.0.5)
|
15
33
|
ast (~> 2.4.1)
|
@@ -36,6 +54,8 @@ GEM
|
|
36
54
|
ruby-progressbar (1.13.0)
|
37
55
|
test-unit (3.6.2)
|
38
56
|
power_assert
|
57
|
+
tzinfo (2.0.6)
|
58
|
+
concurrent-ruby (~> 1.0)
|
39
59
|
unicode-display_width (2.5.0)
|
40
60
|
vcr (6.2.0)
|
41
61
|
|
@@ -43,6 +63,7 @@ PLATFORMS
|
|
43
63
|
arm64-darwin-22
|
44
64
|
|
45
65
|
DEPENDENCIES
|
66
|
+
activesupport (~> 7.1)
|
46
67
|
minitest (~> 5.22)
|
47
68
|
pennylane!
|
48
69
|
rake (~> 13.0)
|
data/README.md
CHANGED
@@ -38,6 +38,32 @@ Pennylane::Customer.list(filter: [{field: 'name', operator: 'eq', value: 'Apple'
|
|
38
38
|
|
39
39
|
# Retrieve single customer
|
40
40
|
Pennylane::Customer.retrieve('38a1f19a-256d-4692-a8fe-0a16403f59ff')
|
41
|
+
|
42
|
+
# Update a customer
|
43
|
+
cus = Pennylane::Customer.retrieve('38a1f19a-256d-4692-a8fe-0a16403f59ff')
|
44
|
+
cus.update(name: 'Apple Inc')
|
45
|
+
|
46
|
+
```
|
47
|
+
|
48
|
+
### Per-request api key [TODO]
|
49
|
+
For apps that need to use multiple keys during the lifetime of a process. it's also possible to set a per-request key:
|
50
|
+
```ruby
|
51
|
+
require "pennylane"
|
52
|
+
|
53
|
+
Pennylane::Customer.list(
|
54
|
+
{},
|
55
|
+
{
|
56
|
+
api_key: 'x1fa....'
|
57
|
+
}
|
58
|
+
)
|
59
|
+
|
60
|
+
Pennylane::Customer.retrieve(
|
61
|
+
'38a1f19a-256d-4692-a8fe-0a16403f59ff',
|
62
|
+
{
|
63
|
+
api_key: 'x1fa....'
|
64
|
+
}
|
65
|
+
)
|
66
|
+
|
41
67
|
```
|
42
68
|
|
43
69
|
## Test mode
|
@@ -50,6 +76,26 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
50
76
|
|
51
77
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
52
78
|
|
79
|
+
Resources implemented so far :
|
80
|
+
### CUSTOMER INVOICING
|
81
|
+
|
82
|
+
- Customer Invoices 🚧
|
83
|
+
- Estimates 🚧
|
84
|
+
- Billing Subscriptions 🚧
|
85
|
+
|
86
|
+
### REFERENTIALS
|
87
|
+
|
88
|
+
- Customers ✅
|
89
|
+
- Suppliers ✅
|
90
|
+
- Categories ✅
|
91
|
+
- CategoryGroups ✅
|
92
|
+
- Products ✅
|
93
|
+
- Plan Items 🚧
|
94
|
+
- Enums 🚧
|
95
|
+
|
96
|
+
### SUPPLIER INVOICING
|
97
|
+
- Supplier Invoices 🚧
|
98
|
+
|
53
99
|
## Contributing
|
54
100
|
|
55
101
|
Bug reports and pull requests are welcome on GitHub at https://github.com/sbounmy/pennylane. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/pennylane/blob/main/CODE_OF_CONDUCT.md).
|
data/lib/pennylane/client.rb
CHANGED
@@ -36,8 +36,7 @@ module Pennylane
|
|
36
36
|
|
37
37
|
def request method, path, params:, opts: {}
|
38
38
|
req = initialize_request(method, path, params[:query]).tap do |req|
|
39
|
-
req.body = params[:body].to_json if params[:body]
|
40
|
-
# req.query = params if !params.empty? && method == :get
|
39
|
+
req.body = params[:body].to_json if params[:body]
|
41
40
|
end
|
42
41
|
|
43
42
|
http.request(req).tap do |resp|
|
data/lib/pennylane/object.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
module Pennylane
|
2
2
|
class Object
|
3
3
|
include Enumerable
|
4
|
-
|
5
|
-
def initialize(id = nil)
|
6
|
-
@id = id
|
7
|
-
end
|
4
|
+
attr_reader :id
|
8
5
|
|
9
6
|
def initialize_from_response(response, params = {}, opts = {})
|
10
7
|
values = Util.symbolize_names(response)
|
@@ -19,7 +16,7 @@ module Pennylane
|
|
19
16
|
end
|
20
17
|
|
21
18
|
def self.build_from(response, params = {}, opts = {})
|
22
|
-
new
|
19
|
+
new.initialize_from_response(response, params, opts)
|
23
20
|
end
|
24
21
|
|
25
22
|
def self.objects
|
@@ -11,9 +11,9 @@ module Pennylane
|
|
11
11
|
"#{object_name}s"
|
12
12
|
end
|
13
13
|
|
14
|
-
def request_pennylane_object(method:, path:, params: {}, opts: {}, usage: [])
|
14
|
+
def request_pennylane_object(method:, path:, params: {}, opts: {}, usage: [], with: {})
|
15
15
|
resp, opts = execute_resource_request(method, path, params, opts, usage)
|
16
|
-
Util.convert_to_pennylane_object(Util.normalize_response(resp), params, opts)
|
16
|
+
Util.convert_to_pennylane_object(Util.normalize_response(resp, with), params, opts)
|
17
17
|
end
|
18
18
|
|
19
19
|
def execute_resource_request(method, path, params = {}, opts = {}, usage = [])
|
@@ -33,18 +33,46 @@ module Pennylane
|
|
33
33
|
def client
|
34
34
|
@client ||= Pennylane::Client.new(Pennylane.api_key)
|
35
35
|
end
|
36
|
+
|
37
|
+
def normalize_filters(filters)
|
38
|
+
filters[:filter] = filters[:filter].to_json if filters[:filter]
|
39
|
+
filters
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# object happens to be nil when the object is in a list
|
44
|
+
def id
|
45
|
+
object.source_id
|
46
|
+
rescue
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
def object
|
52
|
+
@values[self.class.object_name.to_sym]
|
53
|
+
end
|
54
|
+
|
55
|
+
# def inspect
|
56
|
+
# id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : ""
|
57
|
+
# "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " +
|
58
|
+
# JSON.pretty_generate(object.instance_variable_get(:@values) || @values)
|
59
|
+
# end
|
60
|
+
|
61
|
+
def update(attributes)
|
62
|
+
resp, opts = self.class.request_pennylane_object(method: :put, path: "/#{self.class.object_name_plural}/#{id}", params: { body: { self.class.object_name => attributes } })
|
63
|
+
@values = resp.instance_variable_get :@values
|
64
|
+
self
|
36
65
|
end
|
37
66
|
|
38
67
|
# So we can call directly method on the object rather than going through his key
|
39
68
|
# Pennylane::Customer.retrieve('any-id').name == Pennylane::Customer.retrieve('any-id').customer.name
|
40
69
|
def method_missing(method_name, *args, &block)
|
41
|
-
|
42
|
-
|
43
|
-
obj.send(method_name, *args, &block)
|
70
|
+
raise NoMethodError, "undefined method `#{method_name}` for #{self.class}" unless object
|
71
|
+
object.send(method_name, *args, &block)
|
44
72
|
end
|
45
73
|
|
46
74
|
def respond_to_missing?(method_name, include_private = false)
|
47
|
-
|
75
|
+
object.respond_to?(method_name) || super
|
48
76
|
end
|
49
77
|
|
50
78
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Pennylane
|
2
|
+
class Category < Resources::Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# override the object_name_plural method otherwise it will return 'categorys'
|
7
|
+
def object_name_plural
|
8
|
+
'categories'
|
9
|
+
end
|
10
|
+
|
11
|
+
def list filters = {}, opts = {}
|
12
|
+
normalize_filters(filters)
|
13
|
+
request_pennylane_object(method: :get, path: "/categories", params: { query: filters }, opts: opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def retrieve id, opts = {}
|
17
|
+
request_pennylane_object(method: :get, path: "/categories/#{id}", params: {}, opts: opts)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create params, opts = {}
|
21
|
+
request_pennylane_object(method: :post, path: "/categories", params: { body: { object_name => params } }, opts: opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Pennylane
|
2
|
+
class CategoryGroup < Resources::Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def object_name
|
7
|
+
'category_group'
|
8
|
+
end
|
9
|
+
|
10
|
+
def list filters = {}, opts = {}
|
11
|
+
request_pennylane_object(method: :get, path: "/category_groups", params: { query: filters }, opts: opts)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -4,11 +4,12 @@ module Pennylane
|
|
4
4
|
class << self
|
5
5
|
|
6
6
|
def list filters = {}, opts = {}
|
7
|
+
normalize_filters(filters)
|
7
8
|
request_pennylane_object(method: :get, path: "/customers", params: { query: filters }, opts: opts)
|
8
9
|
end
|
9
10
|
|
10
|
-
def retrieve
|
11
|
-
request_pennylane_object(method: :get, path: "/customers/#{
|
11
|
+
def retrieve id, opts = {}
|
12
|
+
request_pennylane_object(method: :get, path: "/customers/#{id}", params: {}, opts: opts)
|
12
13
|
end
|
13
14
|
|
14
15
|
def create params, opts = {}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Pennylane
|
2
|
+
class CustomerInvoice < Resources::Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def object_name
|
7
|
+
'customer_invoice'
|
8
|
+
end
|
9
|
+
|
10
|
+
def list filters = {}, opts = {}
|
11
|
+
normalize_filters(filters)
|
12
|
+
request_pennylane_object(method: :get, path: "/customer_invoices", params: { query: filters }, opts: opts, with: { invoice: 'customer_invoice' })
|
13
|
+
end
|
14
|
+
|
15
|
+
def retrieve id, opts = {}
|
16
|
+
request_pennylane_object(method: :get, path: "/customer_invoices/#{id}", params: {}, opts: opts, with: { invoice: 'customer_invoice' })
|
17
|
+
end
|
18
|
+
|
19
|
+
def create params, opts = {}
|
20
|
+
request_pennylane_object(method: :post, path: "/customer_invoices", params: { body: params }, opts: opts, with: { invoice: 'customer_invoice' })
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
# since object name is different from the class name, we need to override the method
|
26
|
+
def update(attributes)
|
27
|
+
resp, opts = self.class.request_pennylane_object(method: :put, path: "/#{self.class.object_name_plural}/#{id}",
|
28
|
+
params: { body: { 'invoice' => attributes } },
|
29
|
+
opts: {}, with: { invoice: 'customer_invoice' })
|
30
|
+
@values = resp.instance_variable_get :@values
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# since object name is different from the class name, we need to override the object_name method
|
35
|
+
def object
|
36
|
+
@values[:invoice]
|
37
|
+
end
|
38
|
+
|
39
|
+
# doesnt have a `source_id` so we override it
|
40
|
+
def id
|
41
|
+
object.id
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Pennylane
|
2
|
+
class Product < Resources::Base
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def list filters = {}, opts = {}
|
7
|
+
normalize_filters(filters)
|
8
|
+
request_pennylane_object(method: :get, path: "/products", params: { query: filters }, opts: opts)
|
9
|
+
end
|
10
|
+
|
11
|
+
def retrieve id, opts = {}
|
12
|
+
request_pennylane_object(method: :get, path: "/products/#{id}", params: {}, opts: opts)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create params, opts = {}
|
16
|
+
request_pennylane_object(method: :post, path: "/products", params: { body: { product: params } }, opts: opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Pennylane
|
2
|
+
class Supplier < Resources::Base
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def list filters = {}, opts = {}
|
6
|
+
normalize_filters(filters)
|
7
|
+
request_pennylane_object(method: :get, path: "/suppliers", params: { query: filters }, opts: opts)
|
8
|
+
end
|
9
|
+
|
10
|
+
def retrieve supplier_id, opts = {}
|
11
|
+
request_pennylane_object(method: :get, path: "/suppliers/#{supplier_id}", params: {}, opts: opts)
|
12
|
+
end
|
13
|
+
|
14
|
+
def create params, opts = {}
|
15
|
+
request_pennylane_object(method: :post, path: "/suppliers", params: { body: { object_name => params } }, opts: opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/pennylane/util.rb
CHANGED
@@ -20,28 +20,38 @@ module Pennylane
|
|
20
20
|
# It will add an _object key to each hash in the response
|
21
21
|
# This key will contain the name of the object
|
22
22
|
# It will also add an _object key to the root of the response
|
23
|
-
|
23
|
+
# with: is used to map the object name to a different class
|
24
|
+
# Example : GET /customer_invoices will return a list of invoices
|
25
|
+
# {
|
26
|
+
# "total_pages": 5,
|
27
|
+
# "current_page": 1,
|
28
|
+
# "total_invoices": 12,
|
29
|
+
# "invoices": []
|
30
|
+
# }
|
31
|
+
# `invoices` should be `customer_invoice` so we can cast it to the right class CustomerInvoice
|
32
|
+
# Since we don't have the ability to change the API response.
|
33
|
+
# We can achieve this by calling normalize_response(response, with: {invoice: 'customer_invoice'})
|
34
|
+
def normalize_response(object, with={})
|
24
35
|
# puts object.inspect
|
25
36
|
case object
|
26
37
|
when Hash
|
27
38
|
new_hash = {}
|
28
|
-
new_hash['_object'] = object.has_key?('total_pages') ? 'list' : singularize(object.keys.first)
|
29
|
-
|
39
|
+
new_hash['_object'] = object.has_key?('total_pages') ? 'list' : (with[singularize(object.keys.first).to_sym] || singularize(object.keys.first))
|
30
40
|
object.each do |key, value|
|
31
41
|
if value.is_a? Array
|
32
42
|
new_hash[key] = value.map do |h|
|
33
|
-
h['_object'] = singularize(key) if h.is_a? Hash
|
34
|
-
normalize_response(h)
|
43
|
+
h['_object'] = with[singularize(key).to_sym] || singularize(key) if h.is_a? Hash
|
44
|
+
normalize_response(h, with)
|
35
45
|
end
|
36
46
|
elsif value.is_a? Hash
|
37
|
-
value['_object'] = singularize(key)
|
47
|
+
value['_object'] = with[singularize(key).to_sym] || singularize(key)
|
38
48
|
end
|
39
|
-
new_hash[key] = normalize_response(value)
|
49
|
+
new_hash[key] = normalize_response(value, with)
|
40
50
|
end
|
41
51
|
new_hash
|
42
52
|
when Array
|
43
53
|
object.map do |value|
|
44
|
-
normalize_response(value)
|
54
|
+
normalize_response(value, with)
|
45
55
|
end
|
46
56
|
else
|
47
57
|
object
|
data/lib/pennylane/version.rb
CHANGED
data/lib/pennylane.rb
CHANGED
@@ -22,7 +22,12 @@ module Pennylane
|
|
22
22
|
|
23
23
|
API_RESOURCES = {
|
24
24
|
ListObject.object_name => ListObject,
|
25
|
-
|
25
|
+
Category.object_name => Category,
|
26
|
+
CategoryGroup.object_name => CategoryGroup,
|
27
|
+
Customer.object_name => Customer,
|
28
|
+
CustomerInvoice.object_name => CustomerInvoice,
|
29
|
+
Product.object_name => Product,
|
30
|
+
Supplier.object_name => Supplier
|
26
31
|
}.freeze
|
27
32
|
|
28
33
|
@config = Pennylane::Configuration.new
|
data/pennylane.gemspec
CHANGED
@@ -34,5 +34,6 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "vcr", "~> 6.2"
|
35
35
|
spec.add_development_dependency "test-unit", "~> 3.6"
|
36
36
|
spec.add_development_dependency "minitest", "~> 5.22"
|
37
|
+
spec.add_development_dependency "activesupport", "~> 7.1"
|
37
38
|
# guide at: https://bundler.io/guides/creating_gem.html
|
38
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pennylane
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0.pre.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephane Bounmy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: vcr
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.22'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '7.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '7.1'
|
55
69
|
description: Pennylane offers integrated financial management and accounting tools
|
56
70
|
for businesses. See https://pennylane.com for details.
|
57
71
|
email:
|
@@ -74,7 +88,12 @@ files:
|
|
74
88
|
- lib/pennylane/list_object.rb
|
75
89
|
- lib/pennylane/object.rb
|
76
90
|
- lib/pennylane/resources/base.rb
|
91
|
+
- lib/pennylane/resources/category.rb
|
92
|
+
- lib/pennylane/resources/category_group.rb
|
77
93
|
- lib/pennylane/resources/customer.rb
|
94
|
+
- lib/pennylane/resources/customer_invoice.rb
|
95
|
+
- lib/pennylane/resources/product.rb
|
96
|
+
- lib/pennylane/resources/supplier.rb
|
78
97
|
- lib/pennylane/util.rb
|
79
98
|
- lib/pennylane/version.rb
|
80
99
|
- pennylane.gemspec
|
@@ -97,9 +116,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
116
|
version: 2.6.0
|
98
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
118
|
requirements:
|
100
|
-
- - "
|
119
|
+
- - ">"
|
101
120
|
- !ruby/object:Gem::Version
|
102
|
-
version:
|
121
|
+
version: 1.3.1
|
103
122
|
requirements: []
|
104
123
|
rubygems_version: 3.4.10
|
105
124
|
signing_key:
|