boleto_bancario 0.0.1.beta → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -2
  3. data/.travis.yml +10 -0
  4. data/Changelog.markdown +4 -0
  5. data/Gemfile +1 -1
  6. data/Planning.markdown +18 -86
  7. data/README.markdown +107 -55
  8. data/Rakefile +7 -1
  9. data/TODO.markdown +15 -1
  10. data/boleto_bancario.gemspec +7 -3
  11. data/lib/boleto_bancario.rb +27 -15
  12. data/lib/boleto_bancario/calculos/modulo11_fator_de9a2.rb +65 -0
  13. data/lib/boleto_bancario/calculos/modulo11_fator_de9a2_resto_x.rb +5 -51
  14. data/lib/boleto_bancario/calculos/modulo_numero_de_controle.rb +117 -0
  15. data/lib/boleto_bancario/core/banco_brasil.rb +30 -5
  16. data/lib/boleto_bancario/core/banrisul.rb +182 -0
  17. data/lib/boleto_bancario/core/boleto.rb +67 -34
  18. data/lib/boleto_bancario/core/bradesco.rb +28 -16
  19. data/lib/boleto_bancario/core/caixa.rb +233 -0
  20. data/lib/boleto_bancario/core/hsbc.rb +170 -0
  21. data/lib/boleto_bancario/core/itau.rb +20 -10
  22. data/lib/boleto_bancario/core/real.rb +177 -0
  23. data/lib/boleto_bancario/core/santander.rb +19 -22
  24. data/lib/boleto_bancario/core/sicoob.rb +172 -0
  25. data/lib/boleto_bancario/core/sicredi.rb +290 -0
  26. data/lib/boleto_bancario/version.rb +1 -2
  27. data/spec/boleto_bancario/calculos/modulo10_spec.rb +4 -0
  28. data/spec/boleto_bancario/calculos/modulo11_fator_de2a9_spec.rb +6 -0
  29. data/spec/boleto_bancario/calculos/modulo11_fator_de9a2_spec.rb +31 -0
  30. data/spec/boleto_bancario/calculos/modulo_numero_de_controle_spec.rb +37 -0
  31. data/spec/boleto_bancario/core/banco_brasil_spec.rb +59 -65
  32. data/spec/boleto_bancario/core/banrisul_spec.rb +129 -0
  33. data/spec/boleto_bancario/core/boleto_spec.rb +148 -32
  34. data/spec/boleto_bancario/core/bradesco_spec.rb +29 -36
  35. data/spec/boleto_bancario/core/caixa_spec.rb +111 -0
  36. data/spec/boleto_bancario/core/hsbc_spec.rb +72 -0
  37. data/spec/boleto_bancario/core/itau_spec.rb +33 -36
  38. data/spec/boleto_bancario/core/real_spec.rb +104 -0
  39. data/spec/boleto_bancario/core/santander_spec.rb +26 -24
  40. data/spec/boleto_bancario/core/sicoob_spec.rb +111 -0
  41. data/spec/boleto_bancario/core/sicredi_spec.rb +149 -0
  42. data/spec/inheritance/banco_brasil_spec.rb +22 -0
  43. data/spec/inheritance/banrisul_spec.rb +22 -0
  44. data/spec/inheritance/boleto_spec.rb +15 -0
  45. data/spec/inheritance/bradesco_spec.rb +22 -0
  46. data/spec/inheritance/caixa_spec.rb +22 -0
  47. data/spec/inheritance/hsbc_spec.rb +22 -0
  48. data/spec/inheritance/itau_spec.rb +22 -0
  49. data/spec/inheritance/real_spec.rb +22 -0
  50. data/spec/inheritance/santander_spec.rb +22 -0
  51. data/spec/inheritance/sicoob_spec.rb +22 -0
  52. data/spec/inheritance/sicredi_spec.rb +22 -0
  53. data/spec/shared_examples/boleto_bancario_shared_example.rb +21 -34
  54. data/spec/spec_helper.rb +2 -2
  55. metadata +119 -47
  56. data/.rvmrc +0 -1
@@ -0,0 +1,170 @@
1
+ # encoding: utf-8
2
+ module BoletoBancario
3
+ module Core
4
+ # Implementação de emissão de boleto bancário pelo Banco HSBC.
5
+ #
6
+ # === Documentação Implementada
7
+ #
8
+ # A documentação na qual essa implementação foi baseada está localizada na pasta
9
+ # 'documentacoes_dos_boletos/hsbc' dentro dessa biblioteca.
10
+ #
11
+ # === Carteiras
12
+ # ______________________________________________
13
+ # | Carteira | Descrição | Produto |
14
+ # | CNR | Cobrança não Registrada | 2 |
15
+ # |______________________________________________|
16
+ #
17
+ class Hsbc < Boleto
18
+ # Tamanho máximo do código do cedente emitido no Boleto.
19
+ # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
20
+ #
21
+ # @return [Fixnum] 7
22
+ #
23
+ def self.tamanho_maximo_codigo_cedente
24
+ 7
25
+ end
26
+
27
+ # Tamanho máximo do número do documento emitido no Boleto.
28
+ # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
29
+ #
30
+ # @return [Fixnum] 13
31
+ #
32
+ def self.tamanho_maximo_numero_documento
33
+ 13
34
+ end
35
+
36
+ # <b>Carteiras suportadas.</b>
37
+ # <b>Método criado para validar se a carteira informada é suportada.</b>
38
+ #
39
+ # @return [Array]
40
+ #
41
+ def self.carteiras_suportadas
42
+ %w[CNR]
43
+ end
44
+
45
+ # Validações para os campos abaixo:
46
+ #
47
+ # * Conta Corrente
48
+ # * Número do documento
49
+ #
50
+ # Se você quiser sobrescrever os metodos, <b>ficará a sua responsabilidade.</b>
51
+ # Basta você sobrescrever os métodos de validação:
52
+ #
53
+ # class Hsbc < BoletoBancario::Core::Hsbc
54
+ # def self.tamanho_maximo_codigo_cedente
55
+ # 5
56
+ # end
57
+ #
58
+ # def self.tamanho_maximo_numero_documento
59
+ # 10
60
+ # end
61
+ # end
62
+ #
63
+ # Obs.: Mudar as regras de validação podem influenciar na emissão do boleto em si.
64
+ # Talvez você precise analisar o efeito no #codigo_de_barras e na #linha_digitável (ambos podem ser
65
+ # sobreescritos também).
66
+ #
67
+ validates :codigo_cedente, presence: true
68
+
69
+ validates :codigo_cedente, length: { maximum: tamanho_maximo_codigo_cedente }, if: :deve_validar_codigo_cedente?
70
+ validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
71
+
72
+ validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
73
+
74
+ # @return [String] 7 caracteres
75
+ #
76
+ def codigo_cedente
77
+ @codigo_cedente.to_s.rjust(7, '0') if @codigo_cedente.present?
78
+ end
79
+
80
+ # @return [String] 13 caracteres
81
+ #
82
+ def numero_documento
83
+ @numero_documento.to_s.rjust(13, '0') if @numero_documento.present?
84
+ end
85
+
86
+ def produto
87
+ '2'
88
+ end
89
+
90
+ # @return [String] Código do Banco descrito na documentação.
91
+ #
92
+ def codigo_banco
93
+ '399'
94
+ end
95
+
96
+ # @return [String] Não possui dígito do código do banco.
97
+ #
98
+ def digito_codigo_banco
99
+ '9'
100
+ end
101
+
102
+ # Campo Agência / Código do Cedente
103
+ #
104
+ # @return [String]
105
+ #
106
+ def agencia_codigo_cedente
107
+ "#{codigo_cedente}"
108
+ end
109
+
110
+ # Nosso numero calculado pelo Tipo Identificador 4 descrito na documentação
111
+ #
112
+ # @return [String]
113
+ #
114
+ def nosso_numero
115
+ "#{numero_documento}#{nosso_numero_dv_1}#{tipo_identificador}#{nosso_numero_dv_2}"
116
+ end
117
+
118
+ def nosso_numero_dv_1
119
+ Modulo11FatorDe9a2.new(numero_documento)
120
+ end
121
+
122
+ def tipo_identificador
123
+ 4
124
+ end
125
+
126
+ def nosso_numero_dv_2
127
+ soma = "#{numero_documento}#{nosso_numero_dv_1}#{tipo_identificador}".to_i
128
+ soma += codigo_cedente.to_i
129
+ soma += data_vencimento_para_calculo.to_i
130
+
131
+ Modulo11FatorDe9a2.new(soma)
132
+ end
133
+
134
+ # Data do vencimento para ser usada no calculo do segundto dígito identificador do nosso numero
135
+ #
136
+ # Exemplo: 18/03/2015 => 180315
137
+ #
138
+ # @return [String]
139
+ #
140
+ def data_vencimento_para_calculo
141
+ @data_vencimento.strftime('%d%m%y') if @data_vencimento.present?
142
+ end
143
+
144
+ # === Código de barras do banco
145
+ #
146
+ # _______________________________________________________________________________________
147
+ # | Posição | Tamanho | Descrição |
148
+ # |----------|---------|------------------------------------------------------------------|
149
+ # | 20 - 26 | 07 | Código do Cedente |
150
+ # | 27 - 39 | 13 | Código do Documento |
151
+ # | 40 - 43 | 04 | Data de Vencimento no Formato Juliano. |
152
+ # | 44 – 44 | 01 | Código do Produto CNR, número 2. |
153
+ # |_______________________________________________________________________________________|
154
+ #
155
+ # @return [String]
156
+ #
157
+ def codigo_de_barras_do_banco
158
+ "#{codigo_cedente}#{numero_documento}#{data_vencimento_formato_juliano}#{produto}"
159
+ end
160
+
161
+ # Data do vencimento no formato Juliano composta por 4 dígitos
162
+ #
163
+ # @return [String]
164
+ #
165
+ def data_vencimento_formato_juliano
166
+ "#{@data_vencimento.yday.to_s.rjust(3, '0')}#{@data_vencimento.year.to_s.last}" if @data_vencimento.present?
167
+ end
168
+ end
169
+ end
170
+ end
@@ -180,15 +180,14 @@ module BoletoBancario
180
180
  7
181
181
  end
182
182
 
183
- # Tamanho máximo da carteira.
184
- # O tamanho máximo é justamente 3 porque no código de barras só é permitido 3 posições para este campo.
183
+ # <b>Carteiras suportadas.</b>
185
184
  #
186
- # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
185
+ # <b>Método criado para validar se a carteira informada é suportada.</b>
187
186
  #
188
- # @return [Fixnum] 3
187
+ # @return [Array]
189
188
  #
190
- def self.tamanho_maximo_carteira
191
- 3
189
+ def self.carteiras_suportadas
190
+ %w[107 109 174 175 196 198 126 131 146 122 142 143 150 168]
192
191
  end
193
192
 
194
193
  # Campos obrigatórios
@@ -198,16 +197,15 @@ module BoletoBancario
198
197
  # * Dígito da conta corrente
199
198
  #
200
199
  validates :agencia, :conta_corrente, :digito_conta_corrente, presence: true
201
- validates :digito_conta_corrente, length: { maximum: 1 }
202
200
 
203
- # Validações de tamanho para os campos abaixo:
201
+ # Validações para os campos abaixo:
204
202
  #
205
203
  # * Número do documento
206
204
  # * Conta Corrente
207
205
  # * Agencia
208
206
  # * Carteira
209
207
  #
210
- # Se você quiser sobrescrever os tamanhos permitidos, ficará a sua responsabilidade.
208
+ # Se você quiser sobrescrever os metodos, ficará a sua responsabilidade.
211
209
  # Basta você sobrescrever os métodos de validação:
212
210
  #
213
211
  # class BoletoItau < BoletoBancario::Core::Itau
@@ -222,6 +220,9 @@ module BoletoBancario
222
220
  # def self.tamanho_maximo_numero_documento
223
221
  # 9
224
222
  # end
223
+ # def self.carteiras_suportadas
224
+ # %w[107 109 174 175 196 198 126 131 146 122 142 143 150 168]
225
+ # end
225
226
  # end
226
227
  #
227
228
  # Obs.: Mudar as regras de validação podem influenciar na emissão do boleto em si.
@@ -231,7 +232,8 @@ module BoletoBancario
231
232
  validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
232
233
  validates :conta_corrente, length: { maximum: tamanho_maximo_conta_corrente }, if: :deve_validar_conta_corrente?
233
234
  validates :agencia, length: { maximum: tamanho_maximo_agencia }, if: :deve_validar_agencia?
234
- validates :carteira, length: { maximum: tamanho_maximo_carteira }, if: :deve_validar_carteira?
235
+
236
+ validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
235
237
 
236
238
  # Campos obrigatórios e validações de tamanho para os campos:
237
239
  #
@@ -298,6 +300,14 @@ module BoletoBancario
298
300
  '7'
299
301
  end
300
302
 
303
+ # Dígito da conta corrente. Precisa mostrar esse dígito no boleto.
304
+ #
305
+ # @return [String] Dígito da conta corrente calculado apartir do Modulo10.
306
+ #
307
+ def digito_conta_corrente
308
+ Modulo10.new("#{agencia}#{conta_corrente}")
309
+ end
310
+
301
311
  # Agência, conta corrente and dígito da conta corrente formatado.
302
312
  #
303
313
  # @return [String] Campo descrito na documentação (Pag. 50).
@@ -0,0 +1,177 @@
1
+ # encoding: utf-8
2
+ module BoletoBancario
3
+ module Core
4
+ # Implementação de emissão de boleto bancário pelo Banco Real.
5
+ #
6
+ # === Documentação Implementada
7
+ #
8
+ # A documentação na qual essa implementação foi baseada está localizada na pasta
9
+ # 'documentacoes_dos_boletos/real' dentro dessa biblioteca.
10
+ #
11
+ # Cobrança sem registro:
12
+ # Nosso número: 13 dígitos
13
+ # Código da Agência: 4 dígitos
14
+ # Número da Conta: 7 dígitos
15
+ #
16
+ # === Código da Carteira
17
+ #
18
+ # '00' - Carteira do convênio
19
+ # '20' - Cobrança Simples
20
+ # '31' - Cobrança Câmbio
21
+ # '42' - Cobrança Caucionada
22
+ # '47' - Cobr. Caucionada Crédito Imobiliário
23
+ # '85' - Cobrança Partilhada
24
+ #
25
+ class Real < Boleto
26
+ # Tamanho máximo de uma agência no Banco Real.
27
+ # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
28
+ #
29
+ # @return [Fixnum] 4
30
+ #
31
+ def self.tamanho_maximo_agencia
32
+ 4
33
+ end
34
+
35
+ # Tamanho máximo da conta corrente no Boleto.
36
+ # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
37
+ #
38
+ # @return [Fixnum] 7
39
+ #
40
+ def self.tamanho_maximo_conta_corrente
41
+ 7
42
+ end
43
+
44
+ # Tamanho máximo do numero do documento no Boleto.
45
+ # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
46
+ #
47
+ # @return [Fixnum] 13
48
+ #
49
+ def self.tamanho_maximo_numero_documento
50
+ 13
51
+ end
52
+
53
+ # <b>Carteiras suportadas.</b>
54
+ #
55
+ # <b>Método criado para validar se a carteira informada é suportada.</b>
56
+ #
57
+ # @return [Array]
58
+ #
59
+ def self.carteiras_suportadas
60
+ %w[00 20 31 42 47 85]
61
+ end
62
+
63
+ # Validações para os campos abaixo:
64
+ #
65
+ # * Agencia
66
+ # * Conta Corrente
67
+ # * Número do documento
68
+ #
69
+ # Se você quiser sobrescrever os metodos, <b>ficará a sua responsabilidade.</b>
70
+ # Basta você sobrescrever os métodos de validação:
71
+ #
72
+ # class Real < BoletoBancario::Core::Real
73
+ # def self.tamanho_maximo_agencia
74
+ # 6
75
+ # end
76
+ #
77
+ # def self.tamanho_maximo_conta_corrente
78
+ # 9
79
+ # end
80
+ #
81
+ # def self.tamanho_maximo_numero_documento
82
+ # 10
83
+ # end
84
+ # end
85
+ #
86
+ # Obs.: Mudar as regras de validação podem influenciar na emissão do boleto em si.
87
+ # Talvez você precise analisar o efeito no #codigo_de_barras e na #linha_digitável (ambos podem ser
88
+ # sobreescritos também).
89
+ #
90
+ validates :agencia, :conta_corrente, presence: true
91
+
92
+ validates :agencia, length: { maximum: tamanho_maximo_agencia }, if: :deve_validar_agencia?
93
+ validates :conta_corrente, length: { maximum: tamanho_maximo_conta_corrente }, if: :deve_validar_conta_corrente?
94
+ validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
95
+
96
+ validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
97
+
98
+ # @return [String] 4 caracteres
99
+ #
100
+ def agencia
101
+ @agencia.to_s.rjust(4, '0') if @agencia.present?
102
+ end
103
+
104
+ # @return [String] 7 caracteres
105
+ #
106
+ def conta_corrente
107
+ @conta_corrente.to_s.rjust(7, '0') if @conta_corrente.present?
108
+ end
109
+
110
+ # @return [String] 13 caracteres
111
+ #
112
+ def numero_documento
113
+ @numero_documento.to_s.rjust(13, '0') if @numero_documento.present?
114
+ end
115
+
116
+ # @return [String] 2 caracteres
117
+ #
118
+ def carteira
119
+ @carteira.to_s.rjust(2, '0') if @carteira.present?
120
+ end
121
+
122
+ # @return [String] Código do Banco descrito na documentação.
123
+ #
124
+ def codigo_banco
125
+ '356'
126
+ end
127
+
128
+ # @return [String] Dígito do código do banco descrito na documentação.
129
+ #
130
+ def digito_codigo_banco
131
+ '5'
132
+ end
133
+
134
+ # Campo Agência/Código Cedente
135
+ #
136
+ # @return [String] Campo descrito na documentação.
137
+ #
138
+ def agencia_codigo_cedente
139
+ "#{agencia}/#{conta_corrente}/#{cobranca_dv}"
140
+ end
141
+
142
+ # Cálculo do Digito verificador da Cobrança
143
+ # Nosso Número + Agência + Conta Corrente
144
+ # Calculado atravez do modulo 10
145
+ #
146
+ # @return [String]
147
+ #
148
+ def cobranca_dv
149
+ Modulo10.new("#{nosso_numero}#{agencia}#{conta_corrente}")
150
+ end
151
+
152
+ # O nosso numero é o mesmo numero que o cliente informa para o numero do documento
153
+ #
154
+ # @return [String]
155
+ #
156
+ def nosso_numero
157
+ "#{numero_documento}"
158
+ end
159
+
160
+ # === Código de barras do banco
161
+ # ____________________________________________________
162
+ # | Posição | Tamanho | Descrição |
163
+ # |---------|---------|--------------------------------|
164
+ # | 20 – 23 | 04 | Agencia |
165
+ # | 24 – 30 | 07 | Conta corrente |
166
+ # | 31 – 31 | 01 | Digito verificador da cobrança |
167
+ # | 32 – 44 | 13 | Nosso numero |
168
+ # |____________________________________________________|
169
+ #
170
+ # @return [String]
171
+ #
172
+ def codigo_de_barras_do_banco
173
+ "#{agencia}#{conta_corrente}#{cobranca_dv}#{nosso_numero}"
174
+ end
175
+ end
176
+ end
177
+ end
@@ -80,17 +80,6 @@ module BoletoBancario
80
80
  12
81
81
  end
82
82
 
83
- # Tamanho máximo da carteira.
84
- # O tamanho máximo é justamente 2 porque no código de barras só é permitido 2 posições para este campo.
85
- #
86
- # <b>Método criado justamente para ficar documentado o tamanho máximo aceito até a data corrente.</b>
87
- #
88
- # @return [Fixnum] 2
89
- #
90
- def self.tamanho_maximo_carteira
91
- 3
92
- end
93
-
94
83
  # Tamanho máximo do código do cedente emitido no Boleto.
95
84
  # O tamanho máximo é justamente 7 porque no código de barras só é permitido 7 posições para este campo.
96
85
  #
@@ -102,14 +91,24 @@ module BoletoBancario
102
91
  7
103
92
  end
104
93
 
105
- # Validações de tamanho para os campos abaixo:
94
+ # <b>Carteiras suportadas.</b>
95
+ #
96
+ # <b>Método criado para validar se a carteira informada é suportada.</b>
97
+ #
98
+ # @return [Array]
99
+ #
100
+ def self.carteiras_suportadas
101
+ %w[101 102 121]
102
+ end
103
+
104
+ # Validações para os campos abaixo:
106
105
  #
107
106
  # * Número do documento
108
107
  # * Conta Corrente
109
108
  # * Agencia
110
109
  # * Carteira
111
110
  #
112
- # Se você quiser sobrescrever os tamanhos permitidos, <b>ficará a sua responsabilidade.</b>
111
+ # Se você quiser sobrescrever os metodos, <b>ficará a sua responsabilidade.</b>
113
112
  # Basta você sobrescrever os métodos de validação:
114
113
  #
115
114
  # class Santander < BoletoBancario::Core::Santander
@@ -124,6 +123,10 @@ module BoletoBancario
124
123
  # def self.tamanho_maximo_numero_documento
125
124
  # 9
126
125
  # end
126
+ #
127
+ # def self.carteiras_suportadas
128
+ # %w[101 102 121]
129
+ # end
127
130
  # end
128
131
  #
129
132
  # Obs.: Mudar as regras de validação podem influenciar na emissão do boleto em si.
@@ -135,7 +138,8 @@ module BoletoBancario
135
138
  validates :agencia, length: { maximum: tamanho_maximo_agencia }, if: :deve_validar_agencia?
136
139
  validates :codigo_cedente, length: { maximum: tamanho_maximo_codigo_cedente }, if: :deve_validar_codigo_cedente?
137
140
  validates :numero_documento, length: { maximum: tamanho_maximo_numero_documento }, if: :deve_validar_numero_documento?
138
- validates :carteira, length: { maximum: tamanho_maximo_carteira }, if: :deve_validar_carteira?
141
+
142
+ validates :carteira, inclusion: { in: ->(object) { object.class.carteiras_suportadas } }, if: :deve_validar_carteira?
139
143
 
140
144
  # @return [String] 4 caracteres
141
145
  #
@@ -155,12 +159,6 @@ module BoletoBancario
155
159
  @numero_documento.to_s.rjust(12, '0') if @numero_documento.present?
156
160
  end
157
161
 
158
- # @return [String] 3 caracteres
159
- #
160
- def carteira
161
- @carteira.to_s.rjust(3, '0') if @carteira.present?
162
- end
163
-
164
162
  # Formata a carteira dependendo se ela é registrada ou não.
165
163
  #
166
164
  # Para cobrança COM registro usar: <b>COBRANCA SIMPLES ECR</b>
@@ -206,7 +204,7 @@ module BoletoBancario
206
204
  # @return [String]
207
205
  #
208
206
  def agencia_codigo_cedente
209
- "#{agencia}-#{digito_agencia} / #{codigo_cedente}"
207
+ "#{agencia} / #{codigo_cedente}"
210
208
  end
211
209
 
212
210
  # Mostra o campo nosso número calculando o dígito verificador do nosso número.
@@ -260,7 +258,6 @@ module BoletoBancario
260
258
  #
261
259
  # Seguradoras (Se 7% informar 7. Limitado a 9%)
262
260
  # <b>Demais clientes usar 0 (zero)</b>
263
- # O padrão é zero.
264
261
  #
265
262
  # @return [String]
266
263
  #