sunat_books 0.0.1 → 0.0.2

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,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DiaryEntries
4
+ def initial_entry(tickets, counts, total_sums)
5
+ initial = tickets.where(operation_type: "inicial")
6
+ if !initial.empty?
7
+ initial_data = get_row_sums(initial, counts, total_sums)
8
+ else
9
+ initial_data = []
10
+ total_sums.map do |sum|
11
+ initial_data << { content: formated_number(sum.total), align: :right }
12
+ end
13
+ end
14
+ initial_data
15
+ end
16
+
17
+ def buys_entry(tickets, counts, total_sums, data, period_date)
18
+ buys = tickets.where(operation_type: "compras")
19
+ title = "COMPRAS DEL PERIODO"
20
+ return unless buys.count.positive?
21
+ # buys entry
22
+ buys_sum = get_row_sums(buys, counts, total_sums)
23
+ data << [period_date, title, buys_sum].flatten
24
+ end
25
+
26
+ def sales_entry(tickets, counts, total_sums, data, period_date)
27
+ sales = tickets.where(operation_type: "ventas")
28
+ title = "VENTAS DEL PERIODO"
29
+ return unless sales.count.positive?
30
+ sales_sum = get_row_sums(sales, counts, total_sums)
31
+ data << [period_date, title, sales_sum].flatten
32
+ end
33
+
34
+ def other_entry(tickets, counts, total_sums, data)
35
+ # other entries
36
+ others = tickets.where(operation_type: "otros")
37
+ # others_row = get_row_sums(others, counts, total_sums)
38
+ others&.each do |ticket|
39
+ ticket_data = []
40
+ counts.each_with_index do |count, i|
41
+ value = mother_count?(count, ticket) ? get_value(ticket, count) : 0
42
+ increase_value(ticket_data, total_sums, i, value)
43
+ end
44
+ ref = ticket.reference
45
+ data << [parse_day(ticket.operation_date), ref, ticket_data].flatten
46
+ end
47
+ end
48
+
49
+ def close_entry(tickets, counts, total_sums, data)
50
+ close = tickets.where(operation_type: "cierre")
51
+ close.each do |ticket|
52
+ ticket_data = []
53
+ counts.each_with_index do |count, i|
54
+ value = mother_count?(count, ticket) ? get_value(ticket, count) : 0
55
+ increase_value(ticket_data, total_sums, i, value)
56
+ end
57
+ ref = ticket.reference
58
+ data << [parse_day(ticket.operation_date), ref, ticket_data].flatten
59
+ end
60
+ end
61
+
62
+ def total_entry(total_sums, data)
63
+ # totals
64
+ total_data = []
65
+ total_sums.map do |sum|
66
+ total_data << { content: formated_number(sum.total), align: :right }
67
+ end
68
+ data << [{ content: "TOTALES", colspan: 2 }, total_data].flatten
69
+ end
70
+
71
+ def mother_count?(count, ticket)
72
+ ticket.uniq_mother_counts.include?(count)
73
+ end
74
+
75
+ def calculate_totals(tickets, count_sums)
76
+ # get totals
77
+ tickets.each do |ticket|
78
+ count_sums.each do |count_sum|
79
+ count_sum.add get_value(ticket, count_sum.count)
80
+ end
81
+ end
82
+ end
83
+
84
+ def current_sum_count(count_sums, count)
85
+ sum_count = nil
86
+ count_sums.each do |count_sum|
87
+ sum_count = count_sum if count_sum.count == count
88
+ end
89
+ sum_count
90
+ end
91
+
92
+ def get_row_sums(tickets, counts, total_sums)
93
+ # given an array of counts and tickets get sums by each count
94
+ row_counts = get_mother_counts tickets
95
+ count_sums = row_counts.map { |count| Books::CountSum.new(count) }
96
+
97
+ calculate_totals(tickets, count_sums)
98
+ # get ordered row
99
+ row_data = []
100
+ counts.each_with_index do |count, i|
101
+ sum_count = current_sum_count(count_sums, count)
102
+ value = sum_count ? sum_count.total : 0
103
+ increase_value(row_data, total_sums, i, value)
104
+ end
105
+ row_data
106
+ end
107
+
108
+ def increase_value(row_data, total_sums, i, value)
109
+ total_sums[i].add value
110
+ row_data << { content: formated_number(value), align: :right }
111
+ end
112
+ end
@@ -11,7 +11,7 @@ headers:
11
11
  - client_document_number
12
12
  - client_name
13
13
  - export_value
14
- - taxable_bi #- bi_taxable_operation
14
+ - taxable_bi
15
15
  - sale_non_taxable:
16
16
  - exo
17
17
  - inaf
@@ -21,7 +21,7 @@ headers:
21
21
  - total_operation_sales
22
22
  - exchange_rate
23
23
  - credit_origina_document:
24
- - credit_original_document_date #
24
+ - credit_original_document_date
25
25
  - credit_original_document_type
26
26
  - credit_original_document_serial
27
27
  - credit_original_document_number
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "i18n"
4
+
5
+ I18n.load_path << "#{File.dirname(__FILE__)}/locales/es.yml"
6
+ I18n.default_locale = :es
@@ -0,0 +1,65 @@
1
+ es:
2
+ books:
3
+ buys:
4
+ correlative: "Nro"
5
+ operation_date: "Fecha de Emisión"
6
+ pay_date: "Fecha de Venc"
7
+ document: "Documento"
8
+ doc_type: "T"
9
+ document_serial: "Serie"
10
+ year_emition: "AÑO DUA DSI"
11
+ document_number: "N° documen"
12
+ supplier: "Proveedor"
13
+ supplier_document_type: "t"
14
+ supplier_document_number: "N° documen"
15
+ supplier_name: "Nombre o razón social"
16
+ taxable_to_taxable_export: "adquisiciones grav. dest. a oper. gravadas y/o de exportac."
17
+ taxable_to_taxable_export_bi: "bi"
18
+ taxable_to_taxable_export_igv: "igv"
19
+ taxable_to_taxable_export_non_taxable: "adquisiciones gravadas dest. a oper. grav. y/o exportac. y a oper. no gravadas"
20
+ taxable_to_taxable_export_non_taxable_bi: "bi"
21
+ taxable_to_taxable_export_non_taxable_igv: "igv"
22
+ taxable_to_non_taxable: "adquisiciones gravadas destinadas a operaciones no gravadas"
23
+ taxable_to_non_taxable_bi: "bi"
24
+ taxable_to_non_taxable_igv: "igv"
25
+ non_taxable: "adquisiciones no gravadas"
26
+ isc: "isc"
27
+ other_taxs: "otros tributos y cargos"
28
+ total_operation_buys: "importe total"
29
+ foreign_pay_document_number: "n° comprobante pago emitido por no domiciliado"
30
+ detraction: "detracción"
31
+ detraction_number: "número"
32
+ detraction_date: "fech emis"
33
+ exchange_rate: "tipo de cambio"
34
+ debit_original_document: "referencia del comprobante de pago que se modifica"
35
+ debit_original_document_date: "Fecha"
36
+ debit_original_document_type: "t"
37
+ debit_original_document_serial: "serie"
38
+ debit_original_document_number: "n° doc"
39
+ sales:
40
+ correlative: "nro"
41
+ operation_date: "Fecha de Emisión"
42
+ pay_date: "Fecha de Venc"
43
+ document: "Documento"
44
+ doc_type: "T"
45
+ document_serial: "Serie"
46
+ document_number: "N° documen"
47
+ client: "Cliente"
48
+ client_document_type: "t"
49
+ client_document_number: "N° documen"
50
+ client_name: "Nombre o razón social"
51
+ export_value: "Valor exportac"
52
+ taxable_bi: "BI operac gravadas"
53
+ sale_non_taxable: "operacion. exoneradas o inafectas"
54
+ exo: "Exo"
55
+ inaf: "Inaf"
56
+ isc: "ISC"
57
+ igv: "IGV"
58
+ other_taxs: "Otros tributos"
59
+ total_operation_sales: "importe total"
60
+ exchange_rate: "tipo de cambio"
61
+ credit_origina_document: "referencia de documento original que se modifica"
62
+ credit_original_document_date: "Fec"
63
+ credit_original_document_type: "t"
64
+ credit_original_document_serial: "serie"
65
+ credit_original_document_number: "n° doc"
data/lib/books/page.rb ADDED
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Books
6
+ class Page < Base
7
+ attr_accessor :length, :bi_sum, :igv_sum, :total_sum, :non_taxable, :data
8
+
9
+ def initialize(page_number, length)
10
+ @page_number = page_number
11
+ @length = length
12
+ @bi_sum = BigDecimal(0)
13
+ @igv_sum = BigDecimal(0)
14
+ @total_sum = BigDecimal(0)
15
+ @non_taxable = BigDecimal(0)
16
+ @data = []
17
+ end
18
+
19
+ def update_data_buys(ticket)
20
+ @bi_sum += ticket.taxable_to_taxable_export_bi.round(2)
21
+ @igv_sum += ticket.taxable_to_taxable_export_igv.round(2)
22
+ @total_sum += ticket.total_operation_buys.round(2)
23
+ @non_taxable += ticket.non_taxable unless ticket.non_taxable.nil?
24
+ end
25
+
26
+ def update_data_sales(ticket)
27
+ @bi_sum += ticket.taxable_bi.round(2)
28
+ @igv_sum += ticket.igv.round(2)
29
+ @total_sum += ticket.total_operation_sales.round(2)
30
+ end
31
+
32
+ def update_fields(fields = nil, source = nil)
33
+ # update fields from a given source
34
+ return if source.nil?
35
+ fields&.each do |field|
36
+ begin
37
+ send("#{field}=", source.send(field))
38
+ rescue
39
+ return nil
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "page"
4
+
5
+ module PagesUtils
6
+ def page_not_full(last_page, pages, page_max, &block)
7
+ if last_page.length < page_max
8
+ last_page.length += 1
9
+ last_page
10
+ else
11
+ yield if block
12
+ new_page = setup_new_page(pages, last_page, 2)
13
+ new_page
14
+ end
15
+ end
16
+
17
+ def setup_pages(pages, length, page_max, index = 1)
18
+ pages_num = (length / page_max.to_f).ceil
19
+ last_index = index.zero? ? pages_num - 1 : pages_num
20
+ (index..last_index).each do |i|
21
+ pages[i] = Books::Page.new(i, 0)
22
+ end
23
+ end
24
+
25
+ def setup_new_page(pages, last_page, length)
26
+ return if last_page.page_number == pages.count
27
+ new_page = pages[last_page.page_number + 1]
28
+ fields = %w[bi_sum igv_sum total_sum non_taxable]
29
+ new_page.update_fields(fields, last_page)
30
+ new_page.length += length
31
+ new_page
32
+ end
33
+
34
+ def page_index(i, page_max)
35
+ i.zero? ? 1 : (i / page_max.to_f).ceil
36
+ end
37
+
38
+ def not_moviment_page(data)
39
+ data << [content: "SIN MOVIMIENTO EN EL PERIODO", colspan: 5]
40
+ end
41
+
42
+ def setup_final_row_data(page, ticket, data)
43
+ if page.length == @page_max && @tickets.last != ticket
44
+ data << final_row("VAN", page)
45
+ elsif @tickets.last == ticket
46
+ data << final_row("TOTAL", page)
47
+ end
48
+ end
49
+
50
+ def row_data(data, widths, aligns, fields, operation)
51
+ @tickets.each_with_index do |ticket, i|
52
+ last_page = @pages[page_index(i, @page_max)]
53
+ page = page_not_full(last_page, @pages, @page_max) do
54
+ data << final_row("VIENEN", last_page)
55
+ end
56
+ data << table_body(fields, ticket, widths, aligns)
57
+ page.send("update_data_#{operation}", ticket)
58
+ setup_final_row_data(page, ticket, data)
59
+ end
60
+ end
61
+
62
+ # for diary
63
+ def split_data(data, max_column)
64
+ # split rows data in pages according max_column
65
+ pages = []
66
+ setup_pages(pages, data.first.count, max_column, 0)
67
+ data&.each_with_index do |row, i|
68
+ if i == data.length - 1
69
+ setup_row_pages(pages, row, max_column - 1, 1)
70
+ else
71
+ setup_row_pages(pages, row, max_column)
72
+ end
73
+ end
74
+ pages
75
+ end
76
+
77
+ def setup_row_pages(pages, row, max_column, first_rows = 2)
78
+ initial_rows = row.first(first_rows)
79
+ batches_length = max_column - first_rows
80
+ left_data = row[first_rows..row.length].in_groups_of(batches_length, false)
81
+ pages.each_with_index do |page, i|
82
+ page.data << (initial_rows + left_data[i])
83
+ end
84
+ end
85
+ end
data/lib/books/sales.rb CHANGED
@@ -1,114 +1,73 @@
1
- require 'books/base'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "pages_utils"
2
5
 
3
6
  module Books
4
7
  class Sales < Base
8
+ include PagesUtils
9
+
5
10
  def initialize(company, tickets, view, month, year)
11
+ # company => an object that respond to ruc and name methods
12
+ # tickets => an array of objects that respond to a layout's methods
13
+ # view => a view context
14
+ # month => a number that represent a month
15
+ # year => a number that represent a year
6
16
  super(page_layout: :landscape, margin: [5], page_size: "A4")
7
17
  @view = view
8
18
  @company = company
9
19
  @period = get_period(month, year)
10
- @pages = {}
11
20
  @tickets = tickets
12
21
  @book_name = self.class.name.downcase.sub("books::", "")
13
22
  dir = File.dirname(__FILE__)
14
23
  @blayout = YAML.load_file("#{dir}/layouts/#{@book_name}.yml")
15
24
  @page_max = 29
16
25
 
17
- repeat(:all) do
18
- canvas do
19
- bounding_box([bounds.left + 10, bounds.top - 10], width: 800) do
20
- # book_title "REGISTRO DE VENTAS"
21
- book_header @period, @company.ruc, @company.name, "REGISTRO DE VENTAS"
22
- end
23
- end
24
- end
26
+ prawn_book
27
+ end
25
28
 
26
- bounding_box([bounds.left + 3, bounds.top - 45], width: 800, height: 530) do
27
- book_body
28
- end
29
+ def prawn_book
30
+ prawn_header "REGISTRO DE VENTAS", @period, @company
31
+ @pages = []
29
32
 
30
- repeat(:all, dynamic: true) do
31
- canvas do
32
- bounding_box([235, 50], width: 700) do
33
- # book_footer
34
- end
35
- end
33
+ bounding_box([bounds.left + 3, bounds.top - 45], width: 800,
34
+ height: 530) do
35
+ setup_pages(@pages, @tickets.length, @page_max)
36
+ book_body
36
37
  end
37
38
  end
38
39
 
39
40
  def book_body
40
- length = @tickets.length
41
- page_num = (length / 29.0).ceil
42
- page_num.times do |i|
43
- @pages[i + 1] = {
44
- page_number: i + 1,
45
- length: 0,
46
- bi_sum: BigDecimal(0)
47
- }
48
- end
49
-
50
41
  move_down 5
51
- fields = @blayout["headers"]
52
- widths = @blayout["widths"]
53
- aligns = @blayout["align"]
54
42
  data = []
43
+ fields = @blayout["headers"]
55
44
  data << table_head(fields, @book_name, @blayout)
56
45
 
57
- n = 1
58
- bi_sum = BigDecimal(0)
59
- igv_sum = BigDecimal(0)
60
- total_sum = BigDecimal(0)
61
- non_taxable = BigDecimal(0)
62
-
63
- if length > 0
64
- @tickets.each do |ticket|
65
-
66
- if @pages[n][:length] < @page_max
67
- page = @pages[n]
68
- page[:length] += 1
69
- else
70
- data << final_row('VIENEN', @pages[n])
71
- page = @pages[n + 1]
72
- n += 1
73
- page[:length] += 2
74
- end
75
-
76
- data << table_body(fields, ticket, widths, aligns)
77
-
78
- bi_sum += ticket.taxable_bi
79
- igv_sum += ticket.igv
80
- total_sum += ticket.total_operation_sales
81
- page[:bi_sum] = bi_sum.round(2)
82
- page[:igv_sum] = igv_sum.round(2)
83
- page[:total_sum] = total_sum.round(2)
84
- if page[:length] == @page_max && @tickets.last != ticket
85
- data << final_row('VAN', page)
86
- elsif @tickets.last == ticket
87
- data << final_row('TOTAL', page)
88
- end
89
- end
46
+ if @tickets.length.positive?
47
+ row_data(data, @blayout["widths"], @blayout["align"], fields, "sales")
90
48
  else
91
- data << [content: 'SIN MOVIMIENTO EN EL PERIODO', colspan: 5]
92
- @pages[n] = {}
93
- page = @pages[n]
94
- page[:bi_sum] = zero
95
- page[:igv_sum] = zero
96
- page[:total_sum] = zero
49
+ not_moviment_page(data)
97
50
  end
98
51
 
99
- table(data, header: true, cell_style: { borders: [], size: 5,
100
- align: :right },
101
- column_widths: {0 => 22, 1 => 35, 2 => 30, 5 => 27, 6 => 37,
102
- 8 => 20, 9 => 33, 10 => 27, 11 => 35, 12 => 29}) do
103
- row(0).borders = [:bottom, :top]
52
+ render_prawn_table(data)
53
+ end
54
+
55
+ def render_prawn_table(data)
56
+ widths_columns = { 0 => 22, 1 => 35, 2 => 30, 5 => 27, 6 => 37, 8 => 20,
57
+ 9 => 33, 10 => 27, 11 => 35, 12 => 29 }
58
+
59
+ table(data, header: true,
60
+ cell_style: { borders: [], size: 5, align: :right },
61
+ column_widths: widths_columns) do
62
+ row(0).borders = %i[bottom top]
104
63
  end
105
64
  end
106
65
 
107
- def final_row foot_line_text, page
108
- [ {content: foot_line_text, colspan: 5}, zero,
109
- formated_number(page[:bi_sum]), make_sub_table([zero, zero], 22), zero,
110
- formated_number(page[:igv_sum]), zero,
111
- formated_number(page[:total_sum])]
66
+ def final_row(foot_line_text, page)
67
+ [{ content: foot_line_text, colspan: 5 }, zero,
68
+ formated_number(page.bi_sum), make_sub_table([zero, zero], 22), zero,
69
+ formated_number(page.igv_sum), zero,
70
+ formated_number(page.total_sum)]
112
71
  end
113
72
  end
114
73
  end