rails_finance 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.
Files changed (190) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +20 -0
  4. data/Rakefile +32 -0
  5. data/app/controllers/finance/admin/assessments_controller.rb +55 -0
  6. data/app/controllers/finance/admin/base_controller.rb +4 -0
  7. data/app/controllers/finance/admin/budgets_controller.rb +83 -0
  8. data/app/controllers/finance/admin/expense_members_controller.rb +59 -0
  9. data/app/controllers/finance/admin/expenses_controller.rb +71 -0
  10. data/app/controllers/finance/admin/financial_taxons_controller.rb +67 -0
  11. data/app/controllers/finance/admin/fund_incomes_controller.rb +59 -0
  12. data/app/controllers/finance/admin/funds_controller.rb +58 -0
  13. data/app/controllers/finance/admin/home_controller.rb +8 -0
  14. data/app/controllers/finance/admin/stocks_controller.rb +60 -0
  15. data/app/controllers/finance/me/base_controller.rb +4 -0
  16. data/app/controllers/finance/me/budgets_controller.rb +111 -0
  17. data/app/controllers/finance/me/expense_members_controller.rb +73 -0
  18. data/app/controllers/finance/me/expenses_controller.rb +129 -0
  19. data/app/controllers/finance_controller/me.rb +14 -0
  20. data/app/models/budget/finance/fund_budget.rb +5 -0
  21. data/app/models/budget/finance/stock_budget.rb +5 -0
  22. data/app/models/expense/finance/payable_expense.rb +5 -0
  23. data/app/models/expense/finance/prepay_expense.rb +5 -0
  24. data/app/models/finance/application_record.rb +5 -0
  25. data/app/models/finance/assessment.rb +5 -0
  26. data/app/models/finance/budget.rb +7 -0
  27. data/app/models/finance/expense.rb +7 -0
  28. data/app/models/finance/expense_item.rb +5 -0
  29. data/app/models/finance/expense_member.rb +6 -0
  30. data/app/models/finance/ext/financial.rb +24 -0
  31. data/app/models/finance/ext/member.rb +13 -0
  32. data/app/models/finance/financial_taxon.rb +7 -0
  33. data/app/models/finance/fund.rb +6 -0
  34. data/app/models/finance/fund_income.rb +5 -0
  35. data/app/models/finance/model/assessment.rb +26 -0
  36. data/app/models/finance/model/budget/fund_budget.rb +5 -0
  37. data/app/models/finance/model/budget/stock_budget.rb +10 -0
  38. data/app/models/finance/model/budget.rb +152 -0
  39. data/app/models/finance/model/expense/payable_expense.rb +5 -0
  40. data/app/models/finance/model/expense/prepay_expense.rb +5 -0
  41. data/app/models/finance/model/expense.rb +168 -0
  42. data/app/models/finance/model/expense_item.rb +36 -0
  43. data/app/models/finance/model/expense_member.rb +130 -0
  44. data/app/models/finance/model/financial_taxon.rb +27 -0
  45. data/app/models/finance/model/fund.rb +36 -0
  46. data/app/models/finance/model/fund_income.rb +30 -0
  47. data/app/models/finance/model/stock.rb +33 -0
  48. data/app/models/finance/stock.rb +5 -0
  49. data/app/models/finance.rb +12 -0
  50. data/app/pdfs/borrow_expense_pdf.rb +70 -0
  51. data/app/pdfs/payout_expense_pdf.rb +70 -0
  52. data/app/pdfs/prepay_expense_pdf.rb +70 -0
  53. data/app/records/borrow_expense_record.rb +10 -0
  54. data/app/records/prepay_expense_record.rb +16 -0
  55. data/app/views/admin/_finance_nav.html.erb +14 -0
  56. data/app/views/admin/_nav_expense.html.erb +4 -0
  57. data/app/views/finance/admin/assessments/_edit_form.html.erb +4 -0
  58. data/app/views/finance/admin/assessments/_filter_form.html.erb +9 -0
  59. data/app/views/finance/admin/assessments/_form.html.erb +2 -0
  60. data/app/views/finance/admin/assessments/_index_tbody.html.erb +2 -0
  61. data/app/views/finance/admin/assessments/_index_thead.html.erb +3 -0
  62. data/app/views/finance/admin/assessments/_index_tr.html.erb +19 -0
  63. data/app/views/finance/admin/assessments/_new_form.html.erb +4 -0
  64. data/app/views/finance/admin/assessments/_show_table.html.erb +4 -0
  65. data/app/views/finance/admin/assessments/index.html.erb +5 -0
  66. data/app/views/finance/admin/base/_nav.html.erb +3 -0
  67. data/app/views/finance/admin/budgets/_breadcrumb.html.erb +9 -0
  68. data/app/views/finance/admin/budgets/_edit_form.html.erb +4 -0
  69. data/app/views/finance/admin/budgets/_filter_form.html.erb +10 -0
  70. data/app/views/finance/admin/budgets/_filter_table.html.erb +11 -0
  71. data/app/views/finance/admin/budgets/_form.html.erb +7 -0
  72. data/app/views/finance/admin/budgets/_index_tbody.html.erb +13 -0
  73. data/app/views/finance/admin/budgets/_index_thead.html.erb +6 -0
  74. data/app/views/finance/admin/budgets/_item_form.html.erb +17 -0
  75. data/app/views/finance/admin/budgets/_items.html.erb +16 -0
  76. data/app/views/finance/admin/budgets/_new_form.html.erb +4 -0
  77. data/app/views/finance/admin/budgets/_show/_breadcrumb.html.erb +6 -0
  78. data/app/views/finance/admin/budgets/_show_table.html.erb +62 -0
  79. data/app/views/finance/admin/budgets/index.html.erb +5 -0
  80. data/app/views/finance/admin/budgets/next.turbo_stream.erb +1 -0
  81. data/app/views/finance/admin/budgets/show.htmlx.erb +35 -0
  82. data/app/views/finance/admin/budgets/trigger.js.erb +1 -0
  83. data/app/views/finance/admin/expense_members/_edit_form.html.erb +3 -0
  84. data/app/views/finance/admin/expense_members/_form.html.erb +5 -0
  85. data/app/views/finance/admin/expense_members/_index_tbody.html.erb +53 -0
  86. data/app/views/finance/admin/expense_members/_index_thead.html.erb +12 -0
  87. data/app/views/finance/admin/expense_members/index.html.erb +8 -0
  88. data/app/views/finance/admin/expenses/_breadcrumb.html.erb +9 -0
  89. data/app/views/finance/admin/expenses/_edit_form.html.erb +4 -0
  90. data/app/views/finance/admin/expenses/_filter_form.html.erb +10 -0
  91. data/app/views/finance/admin/expenses/_filter_table.html.erb +11 -0
  92. data/app/views/finance/admin/expenses/_form.html.erb +12 -0
  93. data/app/views/finance/admin/expenses/_index_tbody.html.erb +13 -0
  94. data/app/views/finance/admin/expenses/_index_thead.html.erb +6 -0
  95. data/app/views/finance/admin/expenses/_item_form.html.erb +18 -0
  96. data/app/views/finance/admin/expenses/_items.html.erb +20 -0
  97. data/app/views/finance/admin/expenses/_member_form.html.erb +16 -0
  98. data/app/views/finance/admin/expenses/_new_form.html.erb +4 -0
  99. data/app/views/finance/admin/expenses/index.html.erb +5 -0
  100. data/app/views/finance/admin/expenses/next.turbo_stream.erb +1 -0
  101. data/app/views/finance/admin/expenses/show.html.erb +121 -0
  102. data/app/views/finance/admin/expenses/trigger.turbo_stream.erb +1 -0
  103. data/app/views/finance/admin/financial_taxons/_edit_form.html.erb +4 -0
  104. data/app/views/finance/admin/financial_taxons/_filter_form.html.erb +10 -0
  105. data/app/views/finance/admin/financial_taxons/_form.html.erb +5 -0
  106. data/app/views/finance/admin/financial_taxons/_index_tbody.html.erb +36 -0
  107. data/app/views/finance/admin/financial_taxons/_index_thead.html.erb +5 -0
  108. data/app/views/finance/admin/financial_taxons/_index_tr.html.erb +13 -0
  109. data/app/views/finance/admin/financial_taxons/_new_form.html.erb +4 -0
  110. data/app/views/finance/admin/financial_taxons/index.html.erb +6 -0
  111. data/app/views/finance/admin/fund_incomes/_breadcrumb.html.erb +7 -0
  112. data/app/views/finance/admin/fund_incomes/_edit_form.html.erb +4 -0
  113. data/app/views/finance/admin/fund_incomes/_filter_form.html.erb +9 -0
  114. data/app/views/finance/admin/fund_incomes/_form.html.erb +4 -0
  115. data/app/views/finance/admin/fund_incomes/_index_tbody.html.erb +5 -0
  116. data/app/views/finance/admin/fund_incomes/_index_thead.html.erb +4 -0
  117. data/app/views/finance/admin/fund_incomes/_new_form.html.erb +4 -0
  118. data/app/views/finance/admin/fund_incomes/_show_table.html.erb +12 -0
  119. data/app/views/finance/admin/fund_incomes/index.html.erb +5 -0
  120. data/app/views/finance/admin/funds/_edit_form.html.erb +3 -0
  121. data/app/views/finance/admin/funds/_filter_form.html.erb +9 -0
  122. data/app/views/finance/admin/funds/_form.html.erb +5 -0
  123. data/app/views/finance/admin/funds/_index_tbody.html.erb +14 -0
  124. data/app/views/finance/admin/funds/_index_thead.html.erb +8 -0
  125. data/app/views/finance/admin/funds/_new_form.html.erb +3 -0
  126. data/app/views/finance/admin/funds/_show_table.html.erb +16 -0
  127. data/app/views/finance/admin/funds/index.html.erb +5 -0
  128. data/app/views/finance/admin/home/index.html.erb +6 -0
  129. data/app/views/finance/admin/stocks/_breadcrumb.html.erb +7 -0
  130. data/app/views/finance/admin/stocks/_edit_form.html.erb +4 -0
  131. data/app/views/finance/admin/stocks/_filter_form.html.erb +9 -0
  132. data/app/views/finance/admin/stocks/_form.html.erb +4 -0
  133. data/app/views/finance/admin/stocks/_index_tbody.html.erb +6 -0
  134. data/app/views/finance/admin/stocks/_index_thead.html.erb +7 -0
  135. data/app/views/finance/admin/stocks/_new_form.html.erb +4 -0
  136. data/app/views/finance/admin/stocks/_show_table.html.erb +16 -0
  137. data/app/views/finance/admin/stocks/index.html.erb +5 -0
  138. data/app/views/finance/me/budgets/_breadcrumb.html.erb +6 -0
  139. data/app/views/finance/me/budgets/_filter_form.html.erb +8 -0
  140. data/app/views/finance/me/budgets/_filter_table.html.erb +11 -0
  141. data/app/views/finance/me/budgets/_index_tbody.html.erb +23 -0
  142. data/app/views/finance/me/budgets/_index_thead.html.erb +4 -0
  143. data/app/views/finance/me/budgets/_items.html.erb +22 -0
  144. data/app/views/finance/me/budgets/_show/_breadcrumb.html.erb +6 -0
  145. data/app/views/finance/me/budgets/admin.html.erb +5 -0
  146. data/app/views/finance/me/budgets/financial_taxons.js.erb +7 -0
  147. data/app/views/finance/me/budgets/index.html.erb +5 -0
  148. data/app/views/finance/me/budgets/index.js +45 -0
  149. data/app/views/finance/me/budgets/submit.turbo_stream.erb +1 -0
  150. data/app/views/finance/me/budgets/transfer.turbo_stream.erb +1 -0
  151. data/app/views/finance/me/expense_members/_breadcrumb.html.erb +6 -0
  152. data/app/views/finance/me/expense_members/_button.html.erb +0 -0
  153. data/app/views/finance/me/expense_members/_filter_form.html.erb +10 -0
  154. data/app/views/finance/me/expense_members/_form.html.erb +9 -0
  155. data/app/views/finance/me/expense_members/_index_tbody.html.erb +8 -0
  156. data/app/views/finance/me/expense_members/_index_thead.html.erb +7 -0
  157. data/app/views/finance/me/expense_members/_show_items.html.erb +1 -0
  158. data/app/views/finance/me/expense_members/admin.html.erb +3 -0
  159. data/app/views/finance/me/expense_members/index.html.erb +6 -0
  160. data/app/views/finance/me/expense_members/items.js.erb +1 -0
  161. data/app/views/finance/me/expense_members/show.html.erb +62 -0
  162. data/app/views/finance/me/expenses/_breadcrumb.html.erb +7 -0
  163. data/app/views/finance/me/expenses/_edit_form.html.erb +3 -0
  164. data/app/views/finance/me/expenses/_filter_form.html.erb +8 -0
  165. data/app/views/finance/me/expenses/_filter_table.html.erb +11 -0
  166. data/app/views/finance/me/expenses/_index_tbody.html.erb +16 -0
  167. data/app/views/finance/me/expenses/_index_thead.html.erb +6 -0
  168. data/app/views/finance/me/expenses/_index_tr.html.erb +14 -0
  169. data/app/views/finance/me/expenses/_new_form.html.erb +4 -0
  170. data/app/views/finance/me/expenses/_show/_breadcrumb.html.erb +6 -0
  171. data/app/views/finance/me/expenses/_show_table.html.erb +124 -0
  172. data/app/views/finance/me/expenses/admin.html.erb +5 -0
  173. data/app/views/finance/me/expenses/confirm.html.erb +27 -0
  174. data/app/views/finance/me/expenses/financial_taxons.js.erb +44 -0
  175. data/app/views/finance/me/expenses/index.html.erb +5 -0
  176. data/app/views/finance/me/expenses/index.js +42 -0
  177. data/app/views/finance/me/expenses/show.html.erb +3 -0
  178. data/app/views/me/_finance_nav.html.erb +11 -0
  179. data/config/locales/en.attributes.yml +6 -0
  180. data/config/locales/en.controller.yml +21 -0
  181. data/config/locales/en.enum.yml +18 -0
  182. data/config/locales/zh.attributes.yml +65 -0
  183. data/config/locales/zh.controller.yml +57 -0
  184. data/config/locales/zh.enum.yml +38 -0
  185. data/config/routes.rb +63 -0
  186. data/lib/rails_finance/config.rb +11 -0
  187. data/lib/rails_finance/engine.rb +26 -0
  188. data/lib/rails_finance/version.rb +3 -0
  189. data/lib/rails_finance.rb +2 -0
  190. metadata +259 -0
@@ -0,0 +1,36 @@
1
+ module Finance
2
+ module Model::ExpenseItem
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :budget_amount, :decimal
7
+ attribute :amount, :decimal
8
+ attribute :note, :string
9
+ attribute :state, :string
10
+ attribute :quantity, :integer, default: 1
11
+ attribute :price, :decimal
12
+
13
+ belongs_to :expense, optional: true
14
+ belongs_to :budget, optional: true
15
+ belongs_to :financial_taxon, optional: true
16
+
17
+ before_save :ensure_amount, if: -> { budget_amount_changed? }
18
+ after_save :sync_budget_amount, if: -> { saved_change_to_budget_amount? }
19
+ after_update_commit :sync_member_amount, if: -> { saved_change_to_amount? }
20
+ end
21
+
22
+ def sync_budget_amount
23
+ budget.amount = budget.expense_items.sum(&:budget_amount)
24
+ budget.save
25
+ end
26
+
27
+ def ensure_amount
28
+ self.amount = budget_amount if budget
29
+ end
30
+
31
+ def sync_member_amount
32
+ self.expense.update(amount: self.expense.expense_items.sum(:amount)) if expense
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,130 @@
1
+ module Finance
2
+ module Model::ExpenseMember
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :amount, :decimal
7
+ attribute :advance, :decimal
8
+ attribute :state, :string
9
+ attribute :note, :string
10
+
11
+ belongs_to :member, class_name: 'Org::Member'
12
+
13
+ belongs_to :expense
14
+ belongs_to :payment_method, optional: true
15
+
16
+ has_many :expense_items, ->(o){ where(member_id: o.member_id) }, foreign_key: :expense_id, primary_key: :expense_id
17
+
18
+ validates :member_id, uniqueness: { scope: [:expense_id] }
19
+
20
+ enum state: {
21
+ pending_borrow: 'pending_borrow',
22
+ advance_pay: 'advance_pay',
23
+ advance_paid: 'advance_paid',
24
+ pending_reimburse: 'pending_reimburse',
25
+ to_pay: 'to_pay',
26
+ paid: 'paid'
27
+ }, _default: 'pending_borrow'
28
+
29
+ acts_as_notify(
30
+ :default,
31
+ only: [:amount, :advance],
32
+ methods: [:expense_subject, :state_i18n]
33
+ )
34
+ acts_as_notify(
35
+ :request,
36
+ only: [:amount, :advance],
37
+ methods: [:member_name, :expense_subject]
38
+ )
39
+
40
+ delegate :subject, to: :expense, prefix: true
41
+ delegate :name, to: :member, prefix: true
42
+ end
43
+
44
+ def approve_config
45
+ {
46
+ pending_borrow: advance_verifier,
47
+ advance_pay: member.cashier,
48
+ advance_paid: member,
49
+ pending_reimburse: verifier,
50
+ to_pay: member.cashier,
51
+ paid: member
52
+ }
53
+ end
54
+
55
+ def next_operator
56
+ approve_config[next_state(:state)]
57
+ end
58
+
59
+ def advance_verifier
60
+ if self.advance <= 5000
61
+ member.office.leader
62
+ elsif self.advance > 5000
63
+ Member.find_by(email: SETTING['cfo_email'])
64
+ end
65
+ end
66
+
67
+ def verifier
68
+ if self.amount <= 5000
69
+ member.office.leader
70
+ elsif self.amount > 5000
71
+ Member.find_by(email: SETTING['cfo_email'])
72
+ end
73
+ end
74
+
75
+ def can_operate?(member)
76
+ return true if member.admin?
77
+ self.next_operator == current_member && !['paid'].include?(self.state)
78
+ end
79
+
80
+ def amount_cn
81
+ NumHelper.to_rmb amount.to_f
82
+ end
83
+
84
+ def advance_cn
85
+ NumHelper.to_rmb advance.to_f
86
+ end
87
+
88
+ def payout_amount
89
+ self.amount.to_d - self.advance.to_d
90
+ end
91
+
92
+ def do_trigger(params = {})
93
+ self.trigger_to(state: params[:state])
94
+
95
+ # case state_was
96
+ # when 'pending_borrow'
97
+ # self.to_advance_payout
98
+ # when 'pending_reimburse'
99
+ # self.to_payout
100
+ # end
101
+
102
+ self.class.transaction do
103
+ self.save!
104
+ if next_operator
105
+ to_notification(
106
+ member: next_operator,
107
+ link: url_helpers.finance_expense_url(self.expense_id),
108
+ code: :request,
109
+ verbose: true
110
+ )
111
+ end
112
+ end
113
+ end
114
+
115
+ def details
116
+ text = ''
117
+ items = expense_items.limit(4).map do |item|
118
+ "#{item.financial_taxon&.name} #{item.note} #{item.amount}"
119
+ end.join("\n")
120
+
121
+ if expense.note.present?
122
+ text << expense.note
123
+ else
124
+ text << '详情请查看附件'
125
+ end
126
+ text
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,27 @@
1
+ module Finance
2
+ module Model::FinancialTaxon
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :name, :string
7
+ attribute :position, :integer
8
+ attribute :take_stock, :boolean, default: false, comment: '是否有库存'
9
+ attribute :individual, :boolean, default: false, comment: '是否可盘点'
10
+
11
+ belongs_to :organ, class_name: 'Org::Organ', optional: true
12
+
13
+ has_many :expense_items, dependent: :nullify
14
+
15
+ before_save :sync_verifier, if: -> { parent_id_changed? && parent }
16
+
17
+ acts_as_list
18
+ end
19
+
20
+ private
21
+ def sync_verifier
22
+ self.individual ||= self.parent.individual
23
+ self.take_stock ||= self.parent.take_stock
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,36 @@
1
+ module Finance
2
+ module Model::Fund
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :name, :string
7
+ attribute :amount, :decimal, default: 0
8
+ attribute :budget_amount, :decimal, default: 0
9
+ attribute :budget_detail, :json, default: {}
10
+ attribute :expense_amount, :decimal, default: 0
11
+ attribute :expense_detail, :json, default: {}
12
+ attribute :note, :string
13
+
14
+ belongs_to :organ, class_name: 'Org::Organ'
15
+
16
+ has_many :fund_incomes, dependent: :destroy
17
+ has_many :budgets, dependent: :destroy
18
+ has_many :expenses, dependent: :destroy
19
+
20
+ has_one_attached :proof
21
+ end
22
+
23
+ def sum_budget_amount(financial_type)
24
+ self.budget_detail.merge! financial_type => fund_budgets.where(financial_type: financial_type).sum(:amount)
25
+ end
26
+
27
+ def sum_income_amount
28
+ self.amount = fund_incomes.sum(:amount)
29
+ end
30
+
31
+ def sum_expense_amount(financial_type)
32
+ self.expense_detail.merge! financial_type => fund_expenses.where(financial_type: financial_type).sum(:amount)
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ module Finance
2
+ module Model::FundIncome
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attribute :amount, :decimal
7
+ attribute :visible, :boolean, default: false
8
+ attribute :note, :string
9
+
10
+ enum state: {
11
+ init: 'init',
12
+ done: 'done'
13
+ }, _default: 'init'
14
+
15
+ belongs_to :fund
16
+ belongs_to :user, optional: true
17
+ belongs_to :financial, polymorphic: true, optional: true
18
+
19
+ has_one_attached :proof
20
+
21
+ after_save :sum_fund_amount, if: -> { saved_change_to_amount? }
22
+ end
23
+
24
+ def sum_fund_amount
25
+ fund.sum_income_amount
26
+ fund.save
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ module Finance
2
+
3
+ # 股权
4
+ module Model::Stock
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attribute :ratio, :decimal, precision: 4, scale: 2
9
+ attribute :assess_amount, :decimal
10
+ attribute :amount, :integer, default: 0, comment: '发行量'
11
+ attribute :expense_amount, :integer, default: 0
12
+ attribute :expense_detail, :json, default: {}
13
+ attribute :note, :string
14
+
15
+ belongs_to :member, class_name: 'Org::Member' # 托管股东
16
+ belongs_to :organ, class_name: 'Org::Organ'
17
+
18
+ belongs_to :assessment
19
+
20
+ before_validation :compute_assess_amount, if: -> { ratio_changed? }
21
+ before_validation :sync_organ, if: -> { assessment_id_changed? }
22
+ end
23
+
24
+ def compute_assess_amount
25
+ self.assess_amount = assessment.amount * ratio
26
+ end
27
+
28
+ def sync_organ
29
+ self.organ = assessment.organ
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ module Finance
2
+ class Stock < ApplicationRecord
3
+ include Model::Stock
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ module Finance
2
+
3
+ def self.use_relative_model_naming?
4
+ true
5
+ end
6
+
7
+ def self.table_name_prefix
8
+ 'finance_'
9
+ end
10
+
11
+ end
12
+
@@ -0,0 +1,70 @@
1
+ require 'prawn'
2
+ class BorrowExpensePdf
3
+ include Prawn::View
4
+ include PdfTextHelper
5
+ include PdfTableHelper
6
+
7
+ attr_reader :document, :expense_member
8
+
9
+ def initialize(expense_member_id = nil)
10
+ @document = RailsDataPdf.new
11
+ @expense_member = ExpenseMember.find expense_member_id
12
+ write_content
13
+ end
14
+
15
+ def render
16
+ @document.render
17
+ end
18
+
19
+ def write_content
20
+ stroke do
21
+ dash [8, 4]
22
+ horizontal_line -36, (margin_box.width + 36), at: (160.mm - 36)
23
+ horizontal_line -36, (margin_box.width + 36), at: (99.mm - 36)
24
+ end
25
+ write_header
26
+ write_table_header
27
+ write_content_table
28
+ write_table_footer
29
+ end
30
+
31
+ def write_header
32
+ undash
33
+ text "<u>借 支 单</u>", header_style.merge(inline_format: true)
34
+ move_down 10
35
+ end
36
+
37
+ def write_table_header
38
+ grid_table(
39
+ [
40
+ ["单位:#{expense_member.member.office.company_name}", { rowspan: 2, content: expense_member.created_at.to_date.strftime('%Y 年 %m 月 %d 日') }],
41
+ ["部门:#{expense_member.member.department.full_name}"]
42
+ ]
43
+ )
44
+ move_down 10
45
+ end
46
+
47
+ def write_content_table
48
+ content_table(
49
+ [
50
+ ['摘要', { colspan: 3, content: expense_member.expense.subject }],
51
+ ['费用说明', { colspan: 3, content: expense_member.details }],
52
+ [ { content: '金额' }, { content: "¥#{expense_member.advance}" }, { colspan: 2, content: expense_member.advance_cn } ],
53
+ [ { content: '领款人签章' }, { colspan: 3, content:'' } ]
54
+ ]
55
+ ) do
56
+ row(0).style PdfTableHelper::NORMAL_TD
57
+ row(1).style PdfTableHelper::NORMAL_TD.merge height: 90
58
+ row(2..-1).style PdfTableHelper::NORMAL_TD
59
+ end
60
+ end
61
+
62
+ def write_table_footer
63
+ footer_table(
64
+ [
65
+ ['审批人', '审核', '出纳', "借支人: #{expense_member.member.name}"]
66
+ ]
67
+ )
68
+ end
69
+
70
+ end
@@ -0,0 +1,70 @@
1
+ require 'prawn'
2
+ class PayoutExpensePdf
3
+ include Prawn::View
4
+ include PdfTextHelper
5
+ include PdfTableHelper
6
+
7
+ attr_reader :document, :expense
8
+
9
+ def initialize(expense_id)
10
+ @document = RailsDataPdf.new
11
+ @expense = Expense.find(expense_id)
12
+ write_content
13
+ end
14
+
15
+ def render
16
+ @document.render
17
+ end
18
+
19
+ def write_content
20
+ stroke do
21
+ dash [8, 4]
22
+ horizontal_line -36, (margin_box.width + 36), at: (160.mm - 36)
23
+ horizontal_line -36, (margin_box.width + 36), at: (99.mm - 36)
24
+ end
25
+ write_header
26
+ write_table_header
27
+ write_content_table
28
+ write_table_footer
29
+ end
30
+
31
+ def write_header
32
+ undash
33
+ text "<u>付 款 申 请 单</u>", header_style.merge(inline_format: true)
34
+ move_down 10
35
+ end
36
+
37
+ def write_table_header
38
+ grid_table(
39
+ [
40
+ ["单位:#{expense.creator.office.company_name}", { rowspan: 2, content: expense.created_at.to_date.strftime('%Y 年 %m 月 %d 日') }],
41
+ ["部门:#{expense.creator.department.full_name}"]
42
+ ]
43
+ )
44
+ move_down 10
45
+ end
46
+
47
+ def write_content_table
48
+ content_table(
49
+ [
50
+ ['摘要', { colspan: 3, content: expense.subject }],
51
+ ['费用说明', { colspan: 3, content: expense.note }],
52
+ [ { content: '金额' }, { content: "¥#{expense.amount}" }, { colspan: 2, content: expense.amount_cn } ],
53
+ [ { content: '附单据张数', colspan: 2 }, { colspan: 2, content: expense.invoices_count.to_s } ]
54
+ ]
55
+ ) do
56
+ row(0).style PdfTableHelper::NORMAL_TD
57
+ row(1).style PdfTableHelper::NORMAL_TD.merge height: 90
58
+ row(2..-1).style PdfTableHelper::NORMAL_TD
59
+ end
60
+ end
61
+
62
+ def write_table_footer
63
+ footer_table(
64
+ [
65
+ ['审批人', '审核', '出纳', "申请人: #{expense.creator.name}"]
66
+ ]
67
+ )
68
+ end
69
+
70
+ end