bosta 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b763bc46efc4f314e066658f3a4f20be1df8bba6ae33e07359dbdbb9b108d9fb
4
+ data.tar.gz: bc2c61b3c495038afcf82fe0ae253a3299994516e72b3487cc0d12734f417bce
5
+ SHA512:
6
+ metadata.gz: 1d4813c16ba102666cdac9db2b3c7b5f56bd5d1799d409df302e8678db97c6accece4a5ad1d742955db92b20dfc93458e4a81cdb6cde5d874a919c3647becc36
7
+ data.tar.gz: 271b47d8505663ae7c2d4c385ef85a07b98f57be6dfbf5711c1e41b348f631b235d6d8a438e4822a896836c1a1ac203085aaff25a96e046407c3c8f13c4f9e06
@@ -0,0 +1,74 @@
1
+ # Contributor Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to make participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at `:author_email`. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
@@ -0,0 +1,48 @@
1
+ # Contributing
2
+
3
+ We are open to, and grateful for, any contributions made by the community. By contributing to Bosta Ruby SDK, you agree to abide by the [code of conduct](https://github.com/bostaapp/bosta-ruby/blob/master/CONTRIBUTING.md).
4
+
5
+
6
+ # Code Style
7
+
8
+ - Consider the best practices and rules recommended by the
9
+ [Ruby Community Style Guide](https://github.com/bbatsov/ruby-style-guide).
10
+ - To check style linting run the following command:
11
+ ```bash
12
+ gem install rubocop
13
+
14
+ rubocop {source_file_or_directory}
15
+
16
+ ```
17
+ - You can auto-correct offenses with the following command:
18
+ ```bash
19
+ rubocop -a
20
+ ```
21
+
22
+ ### Commit Messages
23
+
24
+ Commit messages should be verb based, using the following pattern:
25
+
26
+ - `Fixing ...`
27
+ - `Adding ...`
28
+ - `Updating ...`
29
+ - `Removing ...`
30
+
31
+ ### Documentation
32
+
33
+ Please update the [docs](README.md) accordingly so that there are no discrepancies between the API and the documentation.
34
+
35
+ ### Developing
36
+
37
+ - `bundle install` install dependencies
38
+
39
+ ### Releasing
40
+
41
+ - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
42
+
43
+ - **Create feature branches** - Don't ask us to pull from your master branch.
44
+
45
+ - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
46
+
47
+ - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
48
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Bosta
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,126 @@
1
+ ## Bosta Ruby Package
2
+ The Bosta Ruby SDK provides convenient access to the Bosta API from applications written in the Ruby language.
3
+
4
+ - [Installation](#installation)
5
+ - [Usage](#usage)
6
+ - [Contribution](#contribution)
7
+ - [License](#license)
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ gem install bosta
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ #### Initiating Bosta Client
18
+ ```bash
19
+ require('bosta');
20
+
21
+ Bosta.api_key= ENV['API_KEY']
22
+ Bosta.base_url= ENV['BASE_URL']
23
+ ```
24
+
25
+ `API_KEY` is your integartion api key with bosta, to get an api key you must be registered, here is the registration link [Bosta](https://business.bosta.co/signup). And `BASE_URL` is the url to bosta Apis wheither it's [staging](https://stg-app.bosta.co) or [production](https://app.bosta.co). If `BASE_URL` is not sent in initialization as parameter it's [production](https://app.bosta.co) by default.
26
+
27
+ #### Use initiated bosta client to do the functionality of the following
28
+
29
+ ##### list utilities
30
+
31
+ ###### delivery types to use in shipment creation
32
+ ```bash
33
+ deliveryTypes = Bosta::DELIVERY_TYPES;
34
+ ```
35
+ ###### pickup timeslots to use in pickup creation
36
+ ```bash
37
+ pickupTimeSlots_1 = Bosta::TIME_SLOT_10_TO_13;
38
+ pickupTimeSlots_2 = Bosta::TIME_SLOT_13_TO_16;
39
+ ```
40
+
41
+ ##### Shipments
42
+ ###### created shipment
43
+ ```bash
44
+ receiver1 = Bosta::Receiver.new('Ahmad Mohamad', '01029394959')
45
+ address1 = Bosta::Address.new('EG-01', 'address firstline')
46
+ type = Bosta::DELIVERY_TYPES[:SEND]
47
+ spec = Bosta::Specs.new(Bosta::DELIVERY_SIZES[:SMALL])
48
+ create_delivery = Bosta::Delivery.create(type, 100, receiver1, address1, spec)
49
+
50
+ delivery_id = create_delivery['_id'];
51
+ tracking_number = create_delivery['trackingNumber'];
52
+ ```
53
+ ###### update shipment by id
54
+ ```bash
55
+ update_delivery = Bosta::Delivery.update(delivery_id, cod=nil, address= nil, receiver = nil, business_reference=nil, webhook_url=nil, notes=nil);
56
+ ```
57
+ ###### list all created shipments
58
+ ```bash
59
+ deliveries = Bosta::Delivery.find_all_deliveries();
60
+ ```
61
+ ###### get shipment by tracking number
62
+ ```bash
63
+ delivery = Bosta::Delivery.find_delivery_by_traking_number(tracking_number);
64
+ ```
65
+ ###### track shipment
66
+ ```bash
67
+ tracking_history = Bosta::Delivery.track_delivery(tracking_number);
68
+ ```
69
+ ###### print airwayBill
70
+ ```bash
71
+ airwayBill = Bosta::Delivery.print_delivery_awb(delivery_id);
72
+ ```
73
+ ###### terminate delivery
74
+ ```bash
75
+ Bosta::Delivery.terminate_delivery(delivery_id);
76
+ ```
77
+
78
+ ##### pickups
79
+ ###### get your pickup location
80
+ ```bash
81
+ pickup_locations = Bosta::Pickup.find_pickup_locations();
82
+ business_location_id = pickup_locations["pickupLocations"][0]['_id'];
83
+ ```
84
+ ###### create pickup
85
+ ```bash
86
+ create_pickup = Bosta::Pickup.create(business_location_id, scheduled_date, scheduled_time_slot, contact_person);
87
+ ```
88
+ ###### update pickup
89
+ ```bash
90
+ update_pickup = Bosta::Pickup.update(pickup_id, business_location_id=nil, scheduled_date=nil, scheduled_time_slot=nil, contact_person=nil, notes=nil);
91
+ ```
92
+ ###### get all pickups
93
+ ```bash
94
+ pickup_requests = Bosta::Pickup.find_pickups();
95
+ ```
96
+ ###### get pickup by id
97
+ ```bash
98
+ pikcup_request = Bosta::Pickup.find_pickup_by_id(pickup_id);
99
+ ```
100
+ ###### delete pickup
101
+ ```bash
102
+ Bosta::Pickup.delete_pickup(pickup_id);
103
+ ```
104
+
105
+ ##### cities
106
+ ###### get all cities to select one of them and its code in shipment
107
+ ```bash
108
+ cities = Bosta::City.find_all_cities();
109
+ ```
110
+
111
+ ##### zones
112
+ ###### get zones of the city by city id to use one of them in the shipment
113
+ ```bash
114
+ zones = Bosta::City.show_city_zones(city_id);
115
+ ```
116
+
117
+ ## Contribution
118
+
119
+ We are open to, and grateful for, any contributions made by the community.
120
+ By contributing to Bosta, you agree to abide by the code of conduct.
121
+ - [Contributing Guide](CONTRIBUTING.md)
122
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
123
+
124
+ ## License
125
+
126
+ The MIT License (MIT) [License](LICENSE).
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'bosta'
5
+ s.version = '0.0.1'
6
+ s.authors = ['Ahmad Elkhateeb']
7
+ s.email = 'ahmed.khateeb@bosta.co'
8
+ s.date = '2020-11-01'
9
+ s.licenses = ['MIT']
10
+ s.homepage = 'https://github.com/bostaapp/bosta-ruby'
11
+ s.summary = 'A Ruby client SDK for Bosta APIs integration.'
12
+ s.description = 'This gem simplifies the integration process with Bosta.
13
+ create, update and track your shimpents easily'
14
+ s.required_ruby_version = '>= 2.4'
15
+ s.files = Dir[
16
+ 'README.md',
17
+ 'LICENSE',
18
+ 'CONTRIBUTING.md',
19
+ 'CODE_OF_CONDUCT.md',
20
+ 'lib/**/*.rb',
21
+ 'bosta.gemspec'
22
+ ]
23
+ s.extra_rdoc_files = ['README.md']
24
+ s.test_files = Dir.glob('test/*_test.rb')
25
+ s.add_runtime_dependency 'faraday', '~> 1.1.0'
26
+ s.add_development_dependency 'rubocop', '~> 0.60'
27
+ s.add_development_dependency 'rubocop-performance', '~> 1.5'
28
+ s.add_development_dependency 'rubocop-rspec', '~> 1.37'
29
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('bosta/config')
4
+ require_relative('bosta/resource')
5
+ require_relative('bosta/utils/bosta_object')
6
+ require_relative('bosta/utils/address')
7
+ require_relative('bosta/utils/specs')
8
+ require_relative('bosta/utils/receiver')
9
+ require_relative('bosta/utils/contact_person')
10
+ require_relative('bosta/utils/constants')
11
+ require_relative('bosta/cities/city')
12
+ require_relative('bosta/zones/zone')
13
+ require_relative('bosta/deliveries/delivery')
14
+ require_relative('bosta/pickups/pickup')
15
+
16
+ #= Bosta
17
+ #
18
+ # * Create and list shimpents easily using Delivery
19
+ # * Create and list your pickups using Pickup
20
+ # * List Different cities that we cover using City
21
+ # * List all zones that we cover using Zone
22
+ #
23
+ #== Start with bosta
24
+ #
25
+ # Visit https://bosta.co/
26
+ #
27
+ module Bosta
28
+ Bosta.base_url = 'https://app.bosta.co' # Default base_url
29
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ ##
5
+ # This class represents the citoes that your addresses will contain in creating deliveries and pickups.
6
+ class City
7
+ ##
8
+ # Get all cities names and codes.
9
+ #
10
+ # Here you will find all city codes that you will need to provide in
11
+ # creating shipments and pickups.
12
+ #
13
+ # An Error is raised if the endpoint didn't return data
14
+
15
+ def self.find_all_cities
16
+ Bosta::Resource.send('get', 'cities')
17
+ end
18
+
19
+ ##
20
+ # Get all zones in a specific city.
21
+ #
22
+ # +cityId+ represents the city id for which zones is obtained
23
+ # an exception raises.
24
+ #
25
+ # An Error is raised if the endpoint didn't return data or wrong +cityId+ was given
26
+
27
+ def self.show_city_zones(city_id)
28
+ Bosta::Resource.send('get', "cities/#{city_id}/zones")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Configuration of bosta module
4
+ module Bosta
5
+ class << self
6
+ attr_writer :api_key, :base_url
7
+
8
+ #:nodoc:
9
+ def api_key
10
+ get_key :api_key
11
+ end
12
+
13
+ #:nodoc:
14
+ def base_url
15
+ get_key :base_url
16
+ end
17
+
18
+ private
19
+
20
+ def get_key(key)
21
+ instance_variable_get("@#{key}") || raise("Set Bosta.#{key} to use this feature")
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Find, create, update, and delete deliveries
5
+ class Delivery
6
+ #=== Create new delivery
7
+ # * +package_type+ should be on of DELIVERY_TYPES in Bosta module
8
+ # * +cod+ should be 0 in case delivery type = CRP
9
+ # * +address+ should be of type Address
10
+ # * +receiver+ should be of type Receiver
11
+ # * +specs+ (optinal) should be of type Specs
12
+ # * +business_reference+ (optional) String
13
+ # * +webhook_url+ (optional) String url
14
+ # * +notes+ String
15
+ #
16
+
17
+ def self.create(package_type,
18
+ cod,
19
+ receiver,
20
+ address,
21
+ specs = nil,
22
+ business_reference = nil,
23
+ webhook_url = nil,
24
+ notes = nil)
25
+ params_hash = {
26
+ type: package_type,
27
+ cod: cod,
28
+ address: address,
29
+ receiver: receiver,
30
+ businessReference: business_reference,
31
+ specs: specs,
32
+ webhookUrl: webhook_url,
33
+ notes: notes
34
+ }
35
+ delivery_hash = Delivery.format_params(params_hash)
36
+ Bosta::Resource.send('post', 'deliveries', delivery_hash)
37
+ end
38
+
39
+ #=== Edit delivery data
40
+ # * +delivery_id+
41
+ # * +cod+ (optional) the cash on delivery (number)
42
+ # * +address+ (optional) should be of type Address
43
+ # * +receiver+ (optional) should be of type Receiver
44
+ # * +business_reference+ (optional) String
45
+ # * +webhook_url+ (optional) String url
46
+ # * +notes+ (optional) String
47
+ #
48
+
49
+ def self.update(delivery_id,
50
+ cod = nil,
51
+ address = nil,
52
+ receiver = nil,
53
+ business_reference = nil,
54
+ webhook_url = nil,
55
+ notes = nil)
56
+ params_hash = {
57
+ cod: cod,
58
+ address: address,
59
+ receiver: receiver,
60
+ businessReference: business_reference,
61
+ webhookUrl: webhook_url,
62
+ notes: notes
63
+ }
64
+ delivery_hash = Delivery.format_params(params_hash)
65
+ Bosta::Resource.send('put', "deliveries/#{delivery_id}", delivery_hash)
66
+ end
67
+
68
+ #
69
+ # * Get all your created Deliveries
70
+ #
71
+
72
+ def self.find_all_deliveries
73
+ Bosta::Resource.send('get', 'deliveries')
74
+ end
75
+
76
+ #
77
+ # * Get specific delivery using +tracking_number+
78
+ #
79
+
80
+ def self.find_delivery_by_traking_number(tracking_number)
81
+ Bosta::Resource.send('get', "deliveries/#{tracking_number}")
82
+ end
83
+
84
+ #
85
+ # * see delivery tracking using +tracking_number+
86
+ #
87
+
88
+ def self.track_delivery(tracking_number)
89
+ Bosta::Resource.send('get', "deliveries/#{tracking_number}/tracking")
90
+ end
91
+
92
+ #
93
+ # * get base64 pdf data representing the package using +delivery_id+
94
+ #
95
+
96
+ def self.print_delivery_awb(delivery_id)
97
+ Bosta::Resource.send('get', "deliveries/awb/#{delivery_id}")
98
+ end
99
+
100
+ #
101
+ # * Terminate the shipment +delivery_id+
102
+ #
103
+
104
+ def self.terminate_delivery(delivery_id)
105
+ Bosta::Resource.send('delete', "deliveries/#{delivery_id}")
106
+ end
107
+
108
+ #:nodoc: all
109
+ def self.format_params(params_hash)
110
+ params_hash = Delivery.check_objects_types(params_hash)
111
+ delivery_hash = {}
112
+ params_hash.each do |key, value|
113
+ if key == :address && !value.nil?
114
+ forward_types = [Bosta::DELIVERY_TYPES[:SEND], Bosta::DELIVERY_TYPES[:EXCHANGE]]
115
+ delivery_hash[:pickupAddress] = value unless forward_types.include? params_hash[:type]
116
+ delivery_hash[:dropOffAddress] = value if forward_types.include? params_hash[:type]
117
+ else
118
+ delivery_hash[key] = value
119
+ end
120
+ end
121
+ delivery_hash
122
+ end
123
+
124
+ #:nodoc: all
125
+ def self.check_objects_types(params_hash)
126
+ object_strings = %w[receiver address specs]
127
+
128
+ object_strings.each do |string|
129
+ upper_string = string[0].upcase + string[1..-1]
130
+ bosta_object = Object.const_get("Bosta::#{upper_string}")
131
+ next if params_hash[:"#{string}"].nil?
132
+ unless params_hash[:"#{string}"].instance_of?(bosta_object)
133
+ raise "#{string} should be of Class Bosta::#{upper_string}"
134
+ end
135
+
136
+ params_hash[:"#{string}"] = params_hash[:"#{string}"].format_obj
137
+ end
138
+ params_hash.compact
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Find, create, update, and delete pickups
5
+ class Pickup
6
+ #=== Create A new pickup
7
+ # * +business_location_id+ should be on of your business locations ids
8
+ # * +scheduled_date+ is the date to be scheduled for pickup
9
+ # * +scheduled_time_slot+ should be one of TIME_SLOT_10_TO_13, TIME_SLOT_13_TO_16 in Bosta
10
+ # * +contact_person+ should be of type ContactPerson
11
+ # * +notes+ (optional) String
12
+ #
13
+
14
+ def self.create(business_location_id, scheduled_date, scheduled_time_slot, contact_person, notes = nil)
15
+ unless contact_person.instance_of?(Bosta::ContactPerson)
16
+ raise 'contact_person should be of Class Bosta::ContactPerson'
17
+ end
18
+
19
+ pickup_hash = {
20
+ businessLocationId: business_location_id,
21
+ scheduledDate: scheduled_date,
22
+ scheduledTimeSlot: scheduled_time_slot,
23
+ contactPerson: contact_person.format_obj
24
+ }
25
+
26
+ pickup_hash[:notes] = notes unless notes.nil?
27
+
28
+ Bosta::Resource.send('post', 'pickups', pickup_hash)
29
+ end
30
+
31
+ #=== Edit A created pickup
32
+ # * +pickup_id+ the id of the pickup to be updated
33
+ # * +business_location_id+ (optional) should be on of your business locations ids
34
+ # * +scheduled_date+ (optional) is the date to be scheduled for pickup
35
+ # * +scheduled_time_slot+ (optional) should be one of TIME_SLOT_10_TO_13, TIME_SLOT_13_TO_16 in Bosta
36
+ # * +contact_person+ (optional) should be of type ContactPerson
37
+ # * +notes+ (optional) String
38
+ #
39
+
40
+ def self.update(pickup_id, business_location_id = nil,
41
+ scheduled_date = nil,
42
+ scheduled_time_slot = nil,
43
+ contact_person = nil,
44
+ notes = nil)
45
+
46
+ unless contact_person.nil?
47
+ unless contact_person.instance_of?(Bosta::ContactPerson)
48
+ raise 'contact_person should be of Class Bosta::ContactPerson'
49
+ end
50
+
51
+ contact_person = contact_person.format_obj
52
+ end
53
+ pickup_hash = {
54
+ businessLocationId: business_location_id,
55
+ scheduledDate: scheduled_date,
56
+ scheduledTimeSlot: scheduled_time_slot,
57
+ contactPerson: contact_person,
58
+ notes: notes
59
+ }
60
+
61
+ pickup_hash = pickup_hash.compact
62
+ Bosta::Resource.send('put', "pickups/#{pickup_id}", pickup_hash)
63
+ end
64
+
65
+ #
66
+ # * get all your pickup locations that you will use in creating pickups
67
+ #
68
+
69
+ def self.find_pickup_locations
70
+ Bosta::Resource.send('get', 'pickup-locations')
71
+ end
72
+
73
+ #
74
+ # * get all your created pickups
75
+ #
76
+
77
+ def self.find_pickups(page_id = 0)
78
+ Bosta::Resource.send('get', 'pickups', {}, { pageId: page_id })
79
+ end
80
+
81
+ #
82
+ # * retrieve specific pickup using +pickup_id+
83
+ #
84
+
85
+ def self.find_pickup_by_id(pickup_id)
86
+ Bosta::Resource.send('get', "pickups/#{pickup_id}")
87
+ end
88
+
89
+ #
90
+ # * delete specific pickup using +pickup_id+
91
+ #
92
+
93
+ def self.delete_pickup(pickup_id)
94
+ Bosta::Resource.send('delete', "pickups/#{pickup_id}")
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'json'
5
+
6
+ module Bosta #:nodoc: all
7
+ class Resource
8
+ def self.connection(method)
9
+ conn = Faraday.new(
10
+ url: Bosta.base_url,
11
+ params: { param: '1' },
12
+ headers: {
13
+ 'Content-Type' => 'application/json',
14
+ 'Authorization': Bosta.api_key,
15
+ 'X-Requested-By': 'ruby-sdk'
16
+ }
17
+ )
18
+ raise 'Not Existed Method' unless conn.respond_to? method
19
+
20
+ conn
21
+ end
22
+
23
+ def self.send(method, path, body = {}, params = {})
24
+ conn = Resource.connection(method)
25
+ full_path = "#{Bosta.base_url}/api/v1/#{path}"
26
+
27
+ res = conn.public_send(method, full_path) do |req|
28
+ req.params = params
29
+ req.body = body.to_json
30
+ end
31
+ res = JSON.parse(res.body)
32
+
33
+ return res['data'] || res['message'] if res['success']
34
+
35
+ # if not Success
36
+ raise res['message']
37
+ rescue StandardError
38
+ raise
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Represents the address type that used by bosta apis
5
+ class Address < BostaObject
6
+ attr_accessor :city_code, :zone, :first_line, :second_line, :district, :building_number, :floor, :apartment
7
+
8
+ #=== Initialize Address Object
9
+ # * +city_code+ The city code like 'EG-01', you can get all cities codes from City Class
10
+ # * +first_line+ your address firstline
11
+ # * +zone+ (optional), find all zones in a city thorugh the City Class
12
+ # * +second_line+ (optional) Sring
13
+ # * +building_number+ (optional) String
14
+ # * +floor+ (optional) String
15
+ # * +apartment+ (optional) String
16
+ #
17
+ def initialize(city_code,
18
+ first_line,
19
+ zone = nil,
20
+ second_line = nil,
21
+ building_number = nil,
22
+ floor = nil,
23
+ apartment = nil)
24
+ super()
25
+ @city_code = city_code
26
+ @first_line = first_line
27
+ @zone = zone
28
+ @second_line = second_line
29
+ @building_number = building_number
30
+ @floor = floor
31
+ @apartment = apartment
32
+
33
+ check_required_fields('city_code', 'first_line')
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta #:nodoc: all
4
+ class BostaObject
5
+ def check_required_fields(*fields)
6
+ fields.map do |field|
7
+ value = instance_variable_get("@#{field}")
8
+ if !instance_variable_defined?("@#{field}") || value.nil? || value.gsub(/\s+/, '').empty?
9
+ raise "#{field} is not allowed to be empty"
10
+ end
11
+ end
12
+ end
13
+
14
+ def format_obj
15
+ obj = {}
16
+ instance_variables.map do |attribute|
17
+ key = attribute.to_s.gsub('@', '')
18
+ value = instance_variable_get(attribute)
19
+ camel_key = key.split('_').map(&:capitalize).join
20
+ camel_key[0] = camel_key[0].downcase
21
+ obj[camel_key] = value unless value.nil?
22
+ end
23
+ obj
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Set your pick in Time Slot '10:00 to 13:00'
5
+ TIME_SLOT_10_TO_13 = '10:00 to 13:00'
6
+
7
+ # Set your pick in Time Slot '13:00 to 16:00'
8
+ TIME_SLOT_13_TO_16 = '13:00 to 16:00'
9
+
10
+ #=== Four different types
11
+ #
12
+ # * SEND => 10
13
+ # * CASH_COLLECTION => 15
14
+ # * CRP => 25
15
+ # * EXCHANGE => 30
16
+ #
17
+
18
+ DELIVERY_TYPES = {
19
+ SEND: 10,
20
+ CASH_COLLECTION: 15,
21
+ CRP: 25,
22
+ EXCHANGE: 30
23
+ }.freeze
24
+
25
+ #=== Three different sizes
26
+ #
27
+ # * SMALL
28
+ # * MEDIUM
29
+ # * LARGE
30
+ #
31
+ DELIVERY_SIZES = {
32
+ SMALL: 'SMALL',
33
+ MEDIUM: 'MEDIUM',
34
+ LARGE: 'LARGE'
35
+ }.freeze
36
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Represents the contact person type that used by bosta apis
5
+ class ContactPerson < BostaObject
6
+ attr_accessor :name, :phone, :email
7
+
8
+ #=== Initialize Contact Person Object
9
+ # * +name+
10
+ # * +phone+
11
+ # * +email+ (optional) String
12
+ #
13
+ def initialize(name, phone, email = nil)
14
+ super()
15
+ @name = name
16
+ @phone = phone
17
+ @email = email
18
+
19
+ check_required_fields('name', 'phone')
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Represents the receiver type that used by bosta apis
5
+ class Receiver < BostaObject
6
+ attr_accessor :first_name, :last_name, :phone, :email
7
+
8
+ #=== Initialize Receiver Object
9
+ # * +name+
10
+ # * +phone+
11
+ # * +email+ (optional) String
12
+ #
13
+ def initialize(name, phone, email = nil)
14
+ super()
15
+ names_arr = name.split
16
+ @first_name = names_arr.shift
17
+ @last_name = names_arr.join(' ')
18
+ @last_name = '-' if @last_name.empty?
19
+ @phone = phone
20
+ @email = email
21
+
22
+ check_required_fields('first_name', 'phone')
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ # Represents the spec type that used by bosta apis
5
+ class Specs < BostaObject
6
+ attr_accessor :size, :items_count, :desc
7
+
8
+ #=== Initialize Specs Object
9
+ # * +size+ (optional) String
10
+ # * +items_count+ (optional) String
11
+ # * +desc+ (optional) String
12
+ #
13
+ def initialize(size = nil, items_count = nil, desc = nil)
14
+ super()
15
+ @size = size
16
+ @items_count = items_count
17
+ @description = desc
18
+ end
19
+
20
+ def format_obj #:nodoc: all
21
+ obj = {}
22
+ package_details = {}
23
+ obj[:size] = @size unless @size.nil?
24
+ package_details[:items_count] = @items_count unless @items_count.nil?
25
+ package_details[:description] = @description unless @description.nil?
26
+
27
+ obj[:package_details] = package_details unless package_details.empty?
28
+ obj
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ #:nodoc: all
4
+ class Hash
5
+ def compact
6
+ delete_if { |_k, v| v.nil? }
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bosta
4
+ ##
5
+ # This class represents the zones that your addresses will contain in creating deliveries and pickups.
6
+ class Zone
7
+ ##
8
+ # Get all zones names.
9
+ #
10
+ # Here you will find all zones that you will need to provide in
11
+ # creating shipments and pickups.
12
+ #
13
+ # An Error is raised if the endpoint didn't return data
14
+
15
+ def self.find_all_zones
16
+ Bosta::Resource.send('get', 'zones')
17
+ end
18
+
19
+ ##
20
+ # Get all zones in a specific city.
21
+ #
22
+ # +zone_id+ represents the id of the zone to be obtaines
23
+ #
24
+ # An Error is raised if the endpoint didn't return data or wrong +zone_id+ was given
25
+
26
+ def self.show_zone(zone_id)
27
+ Bosta::Resource.send('get', "zones/#{zone_id}")
28
+ end
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bosta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ahmad Elkhateeb
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-11-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.60'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.60'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop-performance
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.37'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.37'
69
+ description: |-
70
+ This gem simplifies the integration process with Bosta.
71
+ create, update and track your shimpents easily
72
+ email: ahmed.khateeb@bosta.co
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files:
76
+ - README.md
77
+ files:
78
+ - CODE_OF_CONDUCT.md
79
+ - CONTRIBUTING.md
80
+ - LICENSE
81
+ - README.md
82
+ - bosta.gemspec
83
+ - lib/bosta.rb
84
+ - lib/bosta/cities/city.rb
85
+ - lib/bosta/config.rb
86
+ - lib/bosta/deliveries/delivery.rb
87
+ - lib/bosta/pickups/pickup.rb
88
+ - lib/bosta/resource.rb
89
+ - lib/bosta/utils/address.rb
90
+ - lib/bosta/utils/bosta_object.rb
91
+ - lib/bosta/utils/constants.rb
92
+ - lib/bosta/utils/contact_person.rb
93
+ - lib/bosta/utils/receiver.rb
94
+ - lib/bosta/utils/specs.rb
95
+ - lib/bosta/utils/utils.rb
96
+ - lib/bosta/zones/zone.rb
97
+ homepage: https://github.com/bostaapp/bosta-ruby
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '2.4'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.7.6
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: A Ruby client SDK for Bosta APIs integration.
121
+ test_files: []