Develop and Download Open Source Software

Browse Subversion Repository

Contents of /aoiro/trunk/src/main/java/net/osdn/aoiro/report/BalanceSheet.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 120 - (show annotations) (download) (as text)
Sat Mar 4 02:37:28 2023 UTC (12 months, 2 weeks ago) by hirukawa_ryo
File MIME type: text/x-java
File size: 54817 byte(s)
aoiro 1.1.2
次年度の元入金に繰り越す勘定科目の金額がすべて0円の場合は、先頭の勘定科目1つを次年度の元入金として繰り越すようにしました。これによって、現金 0 / 元入金 0 が次年度にも繰り越されるようになりました。従来は次年度は 元入金 0 / 元入金 0 となっていました。
1 package net.osdn.aoiro.report;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.io.OutputStream;
8 import java.nio.charset.StandardCharsets;
9 import java.nio.file.AccessDeniedException;
10 import java.nio.file.AtomicMoveNotSupportedException;
11 import java.nio.file.Files;
12 import java.nio.file.Path;
13 import java.nio.file.StandardCopyOption;
14 import java.nio.file.StandardOpenOption;
15 import java.text.NumberFormat;
16 import java.time.LocalDate;
17 import java.time.chrono.JapaneseChronology;
18 import java.time.format.DateTimeFormatter;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26
27 import net.osdn.aoiro.AccountSettlement;
28 import net.osdn.aoiro.Util;
29 import net.osdn.aoiro.loader.yaml.YamlBeansUtil;
30 import net.osdn.aoiro.model.Account;
31 import net.osdn.aoiro.model.AccountTitle;
32 import net.osdn.aoiro.model.AccountType;
33 import net.osdn.aoiro.model.Amount;
34 import net.osdn.aoiro.model.Creditor;
35 import net.osdn.aoiro.model.Debtor;
36 import net.osdn.aoiro.model.JournalEntry;
37 import net.osdn.aoiro.model.Node;
38 import net.osdn.aoiro.report.layout.BalanceSheetLayout;
39 import net.osdn.pdf_brewer.BrewerData;
40 import net.osdn.pdf_brewer.FontLoader;
41 import net.osdn.pdf_brewer.PdfBrewer;
42
43 /** ���������������
44 *
45 */
46 public class BalanceSheet {
47
48 public static String MINUS_SIGN = "���";
49 private static final int ROWS = 40;
50 private static final double ROW_HEIGHT = 6.0;
51
52 private BalanceSheetLayout bsLayout;
53 private List<JournalEntry> journalEntries;
54 private boolean isSoloProprietorship;
55
56 private LocalDate openingDate;
57 private LocalDate closingDate;
58 private Map<AccountTitle, Amount> openingBalances = new HashMap<AccountTitle, Amount>();
59 private Map<AccountTitle, Amount> closingBalances = new HashMap<AccountTitle, Amount>();
60 private List<Node<Entry<List<AccountTitle>, Amount[]>>> assetsList;
61 private List<Node<Entry<List<AccountTitle>, Amount[]>>> liabilitiesList;
62 private List<Node<Entry<List<AccountTitle>, Amount[]>>> equityList;
63
64 private List<String> pageData = new ArrayList<String>();
65 private List<String> printData;
66 private FontLoader fontLoader;
67 private boolean bindingMarginEnabled = true;
68
69 private List<String> warnings = new ArrayList<String>();
70
71 public BalanceSheet(BalanceSheetLayout bsLayout, List<JournalEntry> journalEntries, boolean isSoloProprietorship) throws IOException {
72 this.bsLayout = bsLayout;
73 this.journalEntries = journalEntries;
74 this.isSoloProprietorship = isSoloProprietorship;
75
76 this.openingDate = AccountSettlement.getOpeningDate(journalEntries, isSoloProprietorship);
77 this.closingDate = AccountSettlement.getClosingDate(journalEntries, isSoloProprietorship);
78
79 InputStream in = getClass().getResourceAsStream("/templates/���������������.pb");
80 BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
81 String line;
82 while((line = r.readLine()) != null) {
83 pageData.add(line);
84 }
85 r.close();
86
87 //������������(���������)������������������������
88 for(JournalEntry entry : journalEntries) {
89 //������������(���������)
90 if(entry.isOpening(isSoloProprietorship, openingDate)) {
91 for(Debtor debtor : entry.getDebtors()) {
92 Amount amount = openingBalances.get(debtor.getAccountTitle());
93 if(amount == null) {
94 amount = new Amount(debtor.getAccountTitle().getType().getNormalBalance(), 0);
95 openingBalances.put(debtor.getAccountTitle(), amount);
96 }
97 if(debtor.getAccountTitle().getType().getNormalBalance() == Debtor.class) {
98 amount.increase(debtor.getAmount());
99 } else {
100 amount.decrease(debtor.getAmount());
101 }
102 }
103 for(Creditor creditor : entry.getCreditors()) {
104 Amount amount = openingBalances.get(creditor.getAccountTitle());
105 if(amount == null) {
106 amount = new Amount(creditor.getAccountTitle().getType().getNormalBalance(), 0);
107 openingBalances.put(creditor.getAccountTitle(), amount);
108 }
109 if(creditor.getAccountTitle().getType().getNormalBalance() == Creditor.class) {
110 amount.increase(creditor.getAmount());
111 } else {
112 amount.decrease(creditor.getAmount());
113 }
114 }
115 }
116 //������������
117 if(entry.isBalance()) {
118 for(Debtor debtor : entry.getDebtors()) {
119 if(!debtor.getAccountTitle().equals(AccountTitle.BALANCE)) {
120 Amount amount = closingBalances.get(debtor.getAccountTitle());
121 if(amount == null) {
122 amount = new Amount(debtor.getAccountTitle().getType().getNormalBalance(), 0);
123 closingBalances.put(debtor.getAccountTitle(), amount);
124 }
125 if(debtor.getAccountTitle().getType().getNormalBalance() != Debtor.class) {
126 amount.increase(debtor.getAmount());
127 } else {
128 amount.decrease(debtor.getAmount());
129 }
130 }
131 }
132 for(Creditor creditor : entry.getCreditors()) {
133 if(!creditor.getAccountTitle().equals(AccountTitle.BALANCE)) {
134 Amount amount = closingBalances.get(creditor.getAccountTitle());
135 if(amount == null) {
136 amount = new Amount(creditor.getAccountTitle().getType().getNormalBalance(), 0);
137 closingBalances.put(creditor.getAccountTitle(), amount);
138 }
139 if(creditor.getAccountTitle().getType().getNormalBalance() != Creditor.class) {
140 amount.increase(creditor.getAmount());
141 } else {
142 amount.decrease(creditor.getAmount());
143 }
144 }
145 }
146 }
147 }
148
149 /*
150 for(Entry<AccountTitle, Amount> e : openingBalances.entrySet()) {
151 AccountTitle at = e.getKey();
152 Amount a = e.getValue();
153 System.out.println("#OPEN# " + at + ", " + a);
154
155 }
156 */
157 /*
158 for(Entry<AccountTitle, Amount> e : closingBalances.entrySet()) {
159 AccountTitle at = e.getKey();
160 Amount a = e.getValue();
161 System.out.println("#CLOSE# " + at + ", " + a);
162 }
163 */
164
165 //������������
166 retrieve(null, bsLayout.getRoot(), journalEntries);
167 //dump(bsRoot);
168
169 //���������
170 for(Node<Entry<List<AccountTitle>, Amount[]>> child : bsLayout.getRoot().getChildren()) {
171 if(child.getName().equals("������")) {
172 assetsList = getList(child);
173 } else if(child.getName().equals("������")) {
174 liabilitiesList = getList(child);
175 } else if(child.getName().equals("������") || child.getName().equals("���������")) {
176 equityList = getList(child);
177 }
178 }
179 if(assetsList == null) {
180 assetsList = new ArrayList<Node<Entry<List<AccountTitle>, Amount[]>>>();
181 }
182 if(liabilitiesList == null) {
183 liabilitiesList = new ArrayList<Node<Entry<List<AccountTitle>, Amount[]>>>();
184 }
185 if(equityList == null) {
186 equityList = new ArrayList<Node<Entry<List<AccountTitle>, Amount[]>>>();
187 }
188
189 //
190 // ���������������������������������������������������������������������������������������������������
191 // ���������������������������������������������������������������������������������������������������������������������������������������������������������������
192 // ������������������������������������������������������������������������������������������������������������������������������������������������
193 //
194 for(Entry<AccountTitle, Amount> entry : openingBalances.entrySet()) {
195 AccountTitle accountTitle = entry.getKey();
196 Amount amount = entry.getValue();
197 NumberFormat.getNumberInstance();
198 int sign = bsLayout.isSignReversed(accountTitle.getDisplayName()) ? -1 : 1;
199 if(sign * amount.getValue() < 0
200 && (accountTitle.getType() == AccountType.Assets || accountTitle.getType() == AccountType.Liabilities)) {
201 String msg = " [������] ���������������������"
202 + accountTitle.getDisplayName()
203 + "������������������������������������������������������("
204 + accountTitle.getDisplayName()
205 + " "
206 + NumberFormat.getNumberInstance().format(amount.getValue())
207 + ")";
208 warnings.add(msg);
209 }
210 }
211 //
212 // ���������������������������������������������������������������������������������������������������
213 // ���������������������������������������������������������������������������������������������������������������������������������������������������������������
214 // ������������������������������������������������������������������������������������������������������������������������������������������������
215 //
216 for(Entry<AccountTitle, Amount> entry : closingBalances.entrySet()) {
217 AccountTitle accountTitle = entry.getKey();
218 Amount amount = entry.getValue();
219 NumberFormat.getNumberInstance();
220 int sign = bsLayout.isSignReversed(accountTitle.getDisplayName()) ? -1 : 1;
221 if(sign * amount.getValue() < 0
222 && (accountTitle.getType() == AccountType.Assets || accountTitle.getType() == AccountType.Liabilities)) {
223 String msg = " [������] ���������������������"
224 + accountTitle.getDisplayName()
225 + "������������������������������������������������������("
226 + accountTitle.getDisplayName()
227 + " "
228 + NumberFormat.getNumberInstance().format(amount.getValue())
229 + ")";
230 warnings.add(msg);
231 }
232 }
233 }
234
235 public List<JournalEntry> getJournalEntries() {
236 return journalEntries;
237 }
238
239 public Map<AccountTitle, Amount> getOpeningBalances() {
240 return openingBalances;
241 }
242
243 public Map<AccountTitle, Amount> getClosingBalances() {
244 return closingBalances;
245 }
246
247 // PDF���������������������������������������������������������
248 // ���������������������������������������������PDF���������������������������������������������������������������
249 public List<Node<Entry<List<AccountTitle>, Amount[]>>> getAssetsList() {
250 return assetsList;
251 }
252
253 // PDF���������������������������������������������������������
254 // ���������������������������������������������PDF���������������������������������������������������������������
255 public List<Node<Entry<List<AccountTitle>, Amount[]>>> getLiabilitiesList() {
256 return liabilitiesList;
257 }
258
259 // PDF������������������������������������������������������������������������
260 // ���������������������������������������������PDF���������������������������������������������������������������
261 public List<Node<Entry<List<AccountTitle>, Amount[]>>> getEquityList() {
262 return equityList;
263 }
264
265 public List<String> getWarnings() {
266 return warnings;
267 }
268
269 private Amount[] retrieve(Class<? extends Account> normalBalance, Node<Entry<List<AccountTitle>, Amount[]>> node, List<JournalEntry> journalEntries) {
270 if(normalBalance == null && node.getLevel() == 1) {
271 if(node.getName().equals("������")) {
272 normalBalance = Debtor.class;
273 } else if(node.getName().equals("������") || node.getName().equals("������") || node.getName().equals("���������")) {
274 normalBalance = Creditor.class;
275 }
276 }
277
278 Amount openingBalance = null;
279 Amount closingBalance = null;
280 for(Node<Entry<List<AccountTitle>, Amount[]>> child : node.getChildren()) {
281 Amount[] a = retrieve(normalBalance, child, journalEntries);
282 if(a[0] != null) {
283 if(openingBalance == null) {
284 openingBalance = new Amount(normalBalance != null ? normalBalance : a[0].getNormalBalance(), 0);
285 }
286 openingBalance.increase(a[0]);
287 }
288 if(a[1] != null) {
289 if(closingBalance == null) {
290 closingBalance = new Amount(normalBalance != null ? normalBalance : a[1].getNormalBalance(), 0);
291 }
292 closingBalance.increase(a[1]);
293 }
294 }
295 if(node.getValue().getKey() != null) {
296 for(AccountTitle accountTitle : node.getValue().getKey()) {
297 Amount o = openingBalances.get(accountTitle);
298 if(o != null) {
299 if(openingBalance == null) {
300 openingBalance = new Amount(normalBalance != null ? normalBalance : o.getNormalBalance(), 0);
301 }
302 openingBalance.increase(o);
303 }
304 Amount c = closingBalances.get(accountTitle);
305 if(c != null) {
306 if(closingBalance == null) {
307 closingBalance = new Amount(normalBalance != null ? normalBalance : o.getNormalBalance(), 0);
308 }
309 closingBalance.increase(c);
310 }
311 }
312 }
313 Amount[] amounts = new Amount[2];
314 amounts[0] = openingBalance;
315 amounts[1] = closingBalance;
316 node.getValue().setValue(amounts);
317 return amounts;
318 }
319
320 protected List<Node<Entry<List<AccountTitle>, Amount[]>>> getList(Node<Entry<List<AccountTitle>, Amount[]>> node) {
321 List<Node<Entry<List<AccountTitle>, Amount[]>>> list = new ArrayList<Node<Entry<List<AccountTitle>, Amount[]>>>();
322 list.add(node);
323 for(Node<Entry<List<AccountTitle>, Amount[]>> child : node.getChildren()) {
324 list.addAll(getList(child));
325 }
326 return list;
327 }
328
329 protected void prepare() {
330 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("GGGG y ��� M ��� d ���").withChronology(JapaneseChronology.INSTANCE);
331 String openingDate = dtf.format(this.openingDate).replace(" 1 ���", "������");
332 String openingMonth = Integer.toString(this.openingDate.getMonthValue());
333 String openingDay = Integer.toString(this.openingDate.getDayOfMonth());
334 String closingDate = dtf.format(this.closingDate).replace(" 1 ���", "������");
335 String closingMonth = Integer.toString(this.closingDate.getMonthValue());
336 String closingDay = Integer.toString(this.closingDate.getDayOfMonth());
337
338 printData = new ArrayList<String>();
339 if(bindingMarginEnabled) {
340 printData.add("\\media A4");
341
342 //������������������������������������������������������������������������������������������������������
343 printData.add("\\line-style thin dot");
344 printData.add("\\line 0 148.5 5 148.5");
345
346 printData.add("\\box 15 0 0 0");
347 printData.add("\\line-style thin dot");
348 printData.add("\\line 0 0 0 -0");
349 printData.add("\\box 25 0 -10 -10");
350 } else {
351 // ���������������������������15mm������������������������������195mm���������������(A4������������������210mm)
352 // ���������������������������������������������������������
353 printData.add("\\media 195 297");
354
355 printData.add("\\box 10 0 -10 -10");
356 }
357
358 printData.addAll(pageData);
359
360 //������
361 printData.add("\t\\box 0 16 -0 7");
362 printData.add("\t\\font serif 10");
363 printData.add("\t\\align center");
364 printData.add("\t\\text " + openingDate + " ��� " + closingDate);
365 printData.add("\t\\box 0 31 -0 6");
366 printData.add("\t\\align center center");
367 printData.add("\t\t\\box 37.0 0 5 -0");
368 printData.add("\t\t\\text " + openingMonth);
369 printData.add("\t\t\\box 44.7 0 5 -0");
370 printData.add("\t\t\\text " + openingDay);
371 printData.add("\t\t\\box 124.5 0 5 -0");
372 printData.add("\t\t\\text " + openingMonth);
373 printData.add("\t\t\\box 132.2 0 5 -0");
374 printData.add("\t\t\\text " + openingDay);
375 printData.add("\t\t\\box 63.0 0 5 -0");
376 printData.add("\t\t\\text " + closingMonth);
377 printData.add("\t\t\\box 70.7 0 5 -0");
378 printData.add("\t\t\\text " + closingDay);
379 printData.add("\t\t\\box 150.5 0 5 -0");
380 printData.add("\t\t\\text " + closingMonth);
381 printData.add("\t\t\\box 158.2 0 5 -0");
382 printData.add("\t\t\\text " + closingDay);
383
384 //������������������������������������������
385 //2006���������������������������������������������������������������������������������������������������������������
386 //���������������������������������������������������������������������������������������������������������������������������������������������������������������������������
387 //������������������������������������������������������������������������������������������������
388 //aoiro���������������������������������������������������������������������������������������������������������������������������������������������������
389 printData.add("\t\\box 0 25 -0 6");
390 printData.add("\t\t\\font sans-serif 9");
391 printData.add("\t\t\\align center");
392 printData.add("\t\t\\box 87.5 0 87.5 -0");
393 if(isSoloProprietorship) {
394 printData.add("\t\t\\text ���������������������������������������");
395 } else {
396 printData.add("\t\t\\text ���������������������������������������������");
397 }
398
399 // ������������������������������������������������������������������������������������������������������������������������������������������������������������
400 long maxAmount = 0;
401 if(assetsList.size() > 0) {
402 Node<Entry<List<AccountTitle>, Amount[]>> node = assetsList.get(0);
403 Amount openingAmount = node.getValue().getValue()[0];
404 Amount closingAmount = node.getValue().getValue()[1];
405 if(openingAmount != null) {
406 long v = Math.abs(openingAmount.getValue());
407 if(v > maxAmount) {
408 maxAmount = v;
409 }
410 }
411 if(closingAmount != null) {
412 long v = Math.abs(closingAmount.getValue());
413 if(v > maxAmount) {
414 maxAmount = v;
415 }
416 }
417 }
418 if(liabilitiesList.size() > 0) {
419 Node<Entry<List<AccountTitle>, Amount[]>> node = liabilitiesList.get(0);
420 Amount openingAmount = node.getValue().getValue()[0];
421 Amount closingAmount = node.getValue().getValue()[1];
422 if(openingAmount != null) {
423 long v = Math.abs(openingAmount.getValue());
424 if(v > maxAmount) {
425 maxAmount = v;
426 }
427 }
428 if(closingAmount != null) {
429 long v = Math.abs(closingAmount.getValue());
430 if(v > maxAmount) {
431 maxAmount = v;
432 }
433 }
434 }
435 if(equityList.size() > 0) {
436 Node<Entry<List<AccountTitle>, Amount[]>> node = liabilitiesList.get(0);
437 Amount openingAmount = node.getValue().getValue()[0];
438 Amount closingAmount = node.getValue().getValue()[1];
439 if(openingAmount != null) {
440 long v = Math.abs(openingAmount.getValue());
441 if(v > maxAmount) {
442 maxAmount = v;
443 }
444 }
445 if(closingAmount != null) {
446 long v = Math.abs(closingAmount.getValue());
447 if(v > maxAmount) {
448 maxAmount = v;
449 }
450 }
451 }
452
453 //���������������������
454 int assetsRows = 1;
455 for(int i = 1; i < assetsList.size(); i++) {
456 Node<Entry<List<AccountTitle>, Amount[]>> node = assetsList.get(i);
457 String displayName = node.getName();
458 Amount openingAmount = node.getValue().getValue()[0];
459 Amount closingAmount = node.getValue().getValue()[1];
460 if(openingAmount != null) {
461 long v = Math.abs(openingAmount.getValue());
462 if(v > maxAmount) {
463 maxAmount = v;
464 }
465 }
466 if(closingAmount != null) {
467 long v = Math.abs(closingAmount.getValue());
468 if(v > maxAmount) {
469 maxAmount = v;
470 }
471 }
472 //������������������������������������������������������������������������������������������������������������������������������������������������������������������
473 if(openingAmount == null && closingAmount == null && !bsLayout.isAlwaysShown(displayName)) {
474 continue;
475 }
476 //���������������������������������������������������������������������������������������������������������������������������
477 if((openingAmount == null || openingAmount.getValue() == 0)
478 && (closingAmount == null || closingAmount.getValue() == 0) && bsLayout.isHidden(displayName)) {
479 continue;
480 }
481 assetsRows++;
482 }
483 int liabilitiesRows = 1;
484 for(int i = 1; i < liabilitiesList.size(); i++) {
485 Node<Entry<List<AccountTitle>, Amount[]>> node = liabilitiesList.get(i);
486 String displayName = node.getName();
487 Amount openingAmount = node.getValue().getValue()[0];
488 Amount closingAmount = node.getValue().getValue()[1];
489 if(openingAmount != null) {
490 long v = Math.abs(openingAmount.getValue());
491 if(v > maxAmount) {
492 maxAmount = v;
493 }
494 }
495 if(closingAmount != null) {
496 long v = Math.abs(closingAmount.getValue());
497 if(v > maxAmount) {
498 maxAmount = v;
499 }
500 }
501 //������������������������������������������������������������������������������������������������������������������������������������������������������������������
502 if(openingAmount == null && closingAmount == null && !bsLayout.isAlwaysShown(displayName)) {
503 continue;
504 }
505 //���������������������������������������������������������������������������������������������������������������������������
506 if((openingAmount == null || openingAmount.getValue() == 0)
507 && (closingAmount == null || closingAmount.getValue() == 0) && bsLayout.isHidden(displayName)) {
508 continue;
509 }
510 liabilitiesRows++;
511 }
512 int equityRows = 1;
513 for(int i = 1; i < equityList.size(); i++) {
514 Node<Entry<List<AccountTitle>, Amount[]>> node = equityList.get(i);
515 String displayName = node.getName();
516 Amount openingAmount = node.getValue().getValue()[0];
517 Amount closingAmount = node.getValue().getValue()[1];
518 if(openingAmount != null) {
519 long v = Math.abs(openingAmount.getValue());
520 if(v > maxAmount) {
521 maxAmount = v;
522 }
523 }
524 if(closingAmount != null) {
525 long v = Math.abs(closingAmount.getValue());
526 if(v > maxAmount) {
527 maxAmount = v;
528 }
529 }
530 //������������������������������������������������������������������������������������������������������������������������������������������������������������������
531 if(openingAmount == null && closingAmount == null && !bsLayout.isAlwaysShown(displayName)) {
532 continue;
533 }
534 //���������������������������������������������������������������������������������������������������������������������������
535 if((openingAmount == null || openingAmount.getValue() == 0)
536 && (closingAmount == null || closingAmount.getValue() == 0) && bsLayout.isHidden(displayName)) {
537 continue;
538 }
539 equityRows++;
540 }
541
542 // ���������������������������������������������22mm������������������ 99999999999���11���������������������������26mm���
543 // 9999999999���10���������������������������25mm���999999999���9���������������������������24mm ���������������
544 double amountPrintWidth = 22;
545 if(maxAmount > 99999999999L) {
546 amountPrintWidth = 26;
547 } else if(maxAmount > 9999999999L) {
548 amountPrintWidth = 25;
549 } else if(maxAmount > 999999999L) {
550 amountPrintWidth = 24;
551 }
552
553 int rows = Math.max(assetsRows, liabilitiesRows + equityRows);
554 printData.add("\t\\box 0 0 -0 -0");
555 printData.add("\t\\line-style thin solid");
556 printData.add("\t\\line " + String.format("87.3 %.2f 87.3 %.2f", 25.2, 37.0 + rows * ROW_HEIGHT));
557 printData.add("\t\\line " + String.format("87.7 %.2f 87.7 %.2f", 25.2, 37.0 + rows * ROW_HEIGHT));
558 printData.add("\t\\line " + String.format("35.5 %.2f 35.5 %.2f", 31.0, 37.0 + rows * ROW_HEIGHT));
559 printData.add("\t\\line " + String.format("61.5 %.2f 61.5 %.2f", 31.0, 37.0 + rows * ROW_HEIGHT));
560 printData.add("\t\\line " + String.format("123 %.2f 123 %.2f", 31.0, 37.0 + rows * ROW_HEIGHT));
561 printData.add("\t\\line " + String.format("149 %.2f 149 %.2f", 31.0, 37.0 + rows * ROW_HEIGHT));
562
563 printData.add("\t\\box 0 37 -0 -0");
564 printData.add("\t\\font serif 10");
565 printData.add("\t\\line-style thin dot");
566
567 double y = 0.0;
568 for(int i = 1; i < rows; i++) {
569 printData.add("\t\\line " + String.format("0 %.2f -0 %.2f", y, y));
570 y += ROW_HEIGHT;
571 }
572 printData.add("\t\\line-style thin solid");
573 printData.add("\t\\line " + String.format("0 %.2f -0 %.2f", y, y));
574 y += ROW_HEIGHT;
575 printData.add("\t\\line " + String.format("0 %.2f -0 %.2f", y, y));
576 printData.add("\t\\line " + String.format("0 %.2f -0 %.2f", y + 0.4, y + 0.4));
577
578 //������
579 y = 0.0;
580 for(int i = 1; i < assetsList.size(); i++) {
581 Node<Entry<List<AccountTitle>, Amount[]>> node = assetsList.get(i);
582 String displayName = node.getName();
583 Amount openingAmount = node.getValue().getValue()[0];
584 Amount closingAmount = node.getValue().getValue()[1];
585 int sign = bsLayout.isSignReversed(node.getName()) ? -1 : 1;
586
587 // ������������������������������������������������������
588 if("������������".equals(node.getName())) {
589 printData.add("\t\t\\box " + String.format("35.5 %.2f 26 %.2f", y, ROW_HEIGHT));
590 printData.add("\t\t\\line-style thin dot");
591 printData.add("\t\t\\line -0 0.15 0 -0.15");
592 }
593 //������������������������������������������������������������������������������������������������������������������������������������������������������������������
594 if(openingAmount == null && closingAmount == null && !bsLayout.isAlwaysShown(displayName)) {
595 continue;
596 }
597 //���������������������������������������������������������������������������������������������������������������������������
598 if((openingAmount == null || openingAmount.getValue() == 0)
599 && (closingAmount == null || closingAmount.getValue() == 0) && bsLayout.isHidden(displayName)) {
600 continue;
601 }
602 printData.add("\t\t\\box " + String.format("2 %.2f 35.5 %.2f", y, ROW_HEIGHT));
603 printData.add("\t\t\\align center left");
604 printData.add("\t\t\\text " + displayName);
605 printData.add("\t\t\\align center right");
606 if(openingAmount != null) {
607 printData.add("\t\t\\box " + String.format("35.5 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
608 printData.add("\t\t\\text " + formatMoney(sign * openingAmount.getValue()));
609 }
610 if(closingAmount != null) {
611 printData.add("\t\t\\box " + String.format("61.5 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
612 printData.add("\t\t\\text " + formatMoney(sign * closingAmount.getValue()));
613 }
614 y += ROW_HEIGHT;
615 }
616 //������
617 y = 0.0;
618 for(int i = 1; i < liabilitiesList.size(); i++) {
619 Node<Entry<List<AccountTitle>, Amount[]>> node = liabilitiesList.get(i);
620 String displayName = node.getName();
621 Amount openingAmount = node.getValue().getValue()[0];
622 Amount closingAmount = node.getValue().getValue()[1];
623 int sign = bsLayout.isSignReversed(node.getName()) ? -1 : 1;
624
625 //������������������������������������������������������������������������������������������������������������������������������������������������������������������
626 if(openingAmount == null && closingAmount == null && !bsLayout.isAlwaysShown(displayName)) {
627 continue;
628 }
629 //���������������������������������������������������������������������������������������������������������������������������
630 if((openingAmount == null || openingAmount.getValue() == 0)
631 && (closingAmount == null || closingAmount.getValue() == 0) && bsLayout.isHidden(displayName)) {
632 continue;
633 }
634 printData.add("\t\t\\box " + String.format("89.5 %.2f 35.5 %.2f", y, ROW_HEIGHT));
635 printData.add("\t\t\\align center left");
636 printData.add("\t\t\\text " + displayName);
637 printData.add("\t\t\\align center right");
638 if(openingAmount != null) {
639 printData.add("\t\t\\box " + String.format("123 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
640 printData.add("\t\t\\text " + formatMoney(sign * openingAmount.getValue()));
641 }
642 if(closingAmount != null) {
643 printData.add("\t\t\\box " + String.format("149 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
644 printData.add("\t\t\\text " + formatMoney(sign * closingAmount.getValue()));
645 }
646 y += ROW_HEIGHT;
647 }
648 //���������������������
649 y = (rows - equityList.size()) * ROW_HEIGHT;
650 printData.add("\t\\line " + String.format("87.7 %.2f -0 %.2f", y, y));
651 for(int i = 1; i < equityList.size(); i++) {
652 Node<Entry<List<AccountTitle>, Amount[]>> node = equityList.get(i);
653 String displayName = node.getName();
654 Amount openingAmount = node.getValue().getValue()[0];
655 Amount closingAmount = node.getValue().getValue()[1];
656 int sign = bsLayout.isSignReversed(node.getName()) ? -1 : 1;
657
658 // ���������������������������������������������������������������������������������������
659 if("������������".equals(node.getName()) || "������������������������".equals(node.getName())) {
660 printData.add("\t\t\\box " + String.format("123 %.2f 26 %.2f", y, ROW_HEIGHT));
661 printData.add("\t\t\\line-style thin dot");
662 printData.add("\t\t\\line -0 0.15 0 -0.15");
663 }
664 //������������������������������������������������������������������������������������������������������������������������������������������������������������������
665 if(openingAmount == null && closingAmount == null && !bsLayout.isAlwaysShown(displayName)) {
666 continue;
667 }
668 //���������������������������������������������������������������������������������������������������������������������������
669 if((openingAmount == null || openingAmount.getValue() == 0)
670 && (closingAmount == null || closingAmount.getValue() == 0) && bsLayout.isHidden(displayName)) {
671 continue;
672 }
673 printData.add("\t\t\\box " + String.format("89.5 %.2f 35.5 %.2f", y, ROW_HEIGHT));
674 printData.add("\t\t\\align center left");
675 printData.add("\t\t\\text " + displayName);
676 printData.add("\t\t\\align center right");
677 if(openingAmount != null) {
678 printData.add("\t\t\\box " + String.format("123 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
679 printData.add("\t\t\\text " + formatMoney(sign * openingAmount.getValue()));
680 }
681 if(closingAmount != null) {
682 printData.add("\t\t\\box " + String.format("149 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
683 printData.add("\t\t\\text " + formatMoney(sign * closingAmount.getValue()));
684 }
685 y += ROW_HEIGHT;
686 }
687
688 //������
689 y = (rows - 1) * ROW_HEIGHT;
690 if(assetsList.size() > 0) {
691 //������(������)
692 Node<Entry<List<AccountTitle>, Amount[]>> node = assetsList.get(0);
693 String displayName = "������";
694 Amount openingAmount = node.getValue().getValue()[0];
695 Amount closingAmount = node.getValue().getValue()[1];
696 printData.add("\t\t\\font serif 10 bold");
697 printData.add("\t\t\\box " + String.format("2 %.2f 35.5 %.2f", y, ROW_HEIGHT));
698 printData.add("\t\t\\align center left");
699 printData.add("\t\t\\text " + displayName);
700 printData.add("\t\t\\align center right");
701 printData.add("\t\t\\box " + String.format("35.5 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
702 printData.add("\t\t\\text " + formatMoney(openingAmount != null ? openingAmount.getValue() : 0));
703 printData.add("\t\t\\box " + String.format("61.5 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
704 printData.add("\t\t\\text " + formatMoney(closingAmount != null ? closingAmount.getValue() : 0));
705 }
706 if(liabilitiesList.size() > 0 || equityList.size() > 0) {
707 //���������������������������
708 String displayName = "������";
709 int openingAmount = 0;
710 int closingAmount = 0;
711 if(liabilitiesList.size() > 0) {
712 Amount o = liabilitiesList.get(0).getValue().getValue()[0];
713 if(o != null) {
714 openingAmount += o.getValue();
715 }
716 Amount c = liabilitiesList.get(0).getValue().getValue()[1];
717 if(c != null) {
718 closingAmount += c.getValue();
719 }
720 }
721 if(equityList.size() > 0) {
722 Amount o = equityList.get(0).getValue().getValue()[0];
723 if(o != null) {
724 openingAmount += o.getValue();
725 }
726 Amount c = equityList.get(0).getValue().getValue()[1];
727 if(c != null) {
728 closingAmount += c.getValue();
729 }
730 }
731 printData.add("\t\t\\font serif 10 bold");
732 printData.add("\t\t\\box " + String.format("89.5 %.2f 35.5 %.2f", y, ROW_HEIGHT));
733 printData.add("\t\t\\align center left");
734 printData.add("\t\t\\text " + displayName);
735 printData.add("\t\t\\align center right");
736 printData.add("\t\t\\box " + String.format("123 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
737 printData.add("\t\t\\text " + formatMoney(openingAmount));
738 printData.add("\t\t\\box " + String.format("149 %.2f %.2f %.2f", y, amountPrintWidth, ROW_HEIGHT));
739 printData.add("\t\t\\text " + formatMoney(closingAmount));
740 }
741 }
742
743 public void setFontLoader(FontLoader fontLoader) {
744 this.fontLoader = fontLoader;
745 }
746
747 public void setBindingMarginEnabled(boolean enabled) {
748 this.bindingMarginEnabled = enabled;
749 }
750
751 public void writeTo(Path path) throws IOException {
752 prepare();
753
754 PdfBrewer brewer;
755 if(fontLoader != null) {
756 brewer = new PdfBrewer(fontLoader);
757 } else {
758 brewer = new PdfBrewer();
759 }
760 brewer.setCreator(Util.getPdfCreator());
761 BrewerData pb = new BrewerData(printData, brewer.getFontLoader());
762 brewer.setTitle("���������������");
763 brewer.process(pb);
764 brewer.save(path);
765 brewer.close();
766 }
767
768 public void writeTo(OutputStream out) throws IOException {
769 prepare();
770
771 PdfBrewer brewer;
772 if(fontLoader != null) {
773 brewer = new PdfBrewer(fontLoader);
774 } else {
775 brewer = new PdfBrewer();
776 }
777 brewer.setCreator(Util.getPdfCreator());
778 BrewerData pb = new BrewerData(printData, brewer.getFontLoader());
779 brewer.setTitle("���������������");
780 brewer.process(pb);
781 brewer.save(out);
782 brewer.close();
783 }
784
785 /** ���������������������������������������������
786 * ���������������������JSON������������������������������������������
787 *
788 * @param path ������������������������������������������������������null���������������������������������������������������������������������
789 * @return ���������������������������YAML���������
790 * @throws IOException
791 */
792 public String createNextOpeningJournalEntries(List<AccountTitle> accountTitles, Path path) throws IOException {
793 List<Entry<AccountTitle, Amount>> debtors = new ArrayList<>();
794 long debtorsTotal = 0;
795 List<Entry<AccountTitle, Amount>> creditors = new ArrayList<>();
796 long creditorsTotal = 0;
797
798 StringBuilder sb = new StringBuilder();
799 String nextOpeningDate = null;
800 if(this.closingDate != null) {
801 nextOpeningDate = DateTimeFormatter.ISO_LOCAL_DATE.format(this.closingDate.plusDays(1));
802 }
803
804 if(isSoloProprietorship) {
805 //���������������������������������������������������������������������������������������������������������������������������������������������������������
806 //���������������������������������������������������������������������������������������������������������
807 //���������������������������������������������������������
808
809 List<Entry<AccountTitle, Amount>> list = new ArrayList<>(closingBalances.entrySet());
810 Collections.sort(list, (o1, o2) -> {
811 return accountTitles.indexOf(o1.getKey()) - accountTitles.indexOf(o2.getKey());
812 });
813 Entry<AccountTitle, Amount> reserved = null;
814 for(Entry<AccountTitle, Amount> e : list) {
815 AccountTitle accountTitle = e.getKey();
816 Amount amount = e.getValue();
817 // ��������������������������������������� ���������������������������
818 if(accountTitle.getDisplayName().equals("������������") || accountTitle.getDisplayName().equals("������������") || accountTitle.getDisplayName().equals("���������")) {
819 continue;
820 }
821 // ������������������������ ���������������������������
822 if(accountTitle.equals(AccountTitle.PRETAX_INCOME)) {
823 continue;
824 }
825 if(accountTitle.getType() == AccountType.Assets) {
826 if(amount.getValue() == 0) {
827 if(reserved == null) {
828 reserved = e;
829 }
830 continue;
831 } else if(amount.getValue() > 0) {
832 debtors.add(e);
833 debtorsTotal += amount.getValue();
834 } else {
835 creditors.add(e);
836 creditorsTotal -= amount.getValue();
837 }
838 } else if(accountTitle.getType() == AccountType.Liabilities || accountTitle.getType() == AccountType.Equity) {
839 if(amount.getValue() == 0) {
840 if(reserved == null) {
841 reserved = e;
842 }
843 continue;
844 } else if(amount.getValue() > 0) {
845 creditors.add(e);
846 creditorsTotal += amount.getValue();
847 } else {
848 debtors.add(e);
849 debtorsTotal -= amount.getValue();
850 }
851 }
852 }
853 AccountTitle capital = AccountTitle.getByDisplayName(new HashSet<>(accountTitles), "���������");
854 // ������������ 0 ������������������������������������������������������������������
855 // ��������������������������� 1���������������������������������������������������������������������������������������������
856 if(creditors.size() == 0 && debtors.size() == 0 && reserved != null && capital != null) {
857 Map.Entry<AccountTitle, Amount> e = Map.entry(capital, new Amount(Creditor.class, 0));
858 if(reserved.getKey().getType().getNormalBalance() == Debtor.class) {
859 debtors.add(reserved);
860 creditors.add(e);
861 } else {
862 debtors.add(e);
863 creditors.add(reserved);
864 }
865 } else if(capital != null) {
866 // ������������������������������������������������������������������
867 Map.Entry<AccountTitle, Amount> e = Map.entry(capital, new Amount(Creditor.class, (debtorsTotal - creditorsTotal)));
868 if(debtorsTotal >= creditorsTotal) {
869 creditors.add(e);
870 } else {
871 debtors.add(e);
872 }
873 }
874 if(debtors.size() > 0 && creditors.size() > 0) {
875 sb.append("- \"������\" : \"" + nextOpeningDate + "\"\r\n");
876 sb.append(" \"������\" : \"���������\"\r\n");
877 sb.append(" \"������\" : [ ");
878 for(int i = 0; i < debtors.size(); i++) {
879 AccountTitle accountTitle = debtors.get(i).getKey();
880 Amount amount = debtors.get(i).getValue();
881 sb.append("{ \"������������\" : \"" + YamlBeansUtil.escape(accountTitle.getDisplayName()) + "\", \"������\" : " + Math.abs(amount.getValue()) + " }");
882 if(i + 1 < debtors.size()) {
883 sb.append(", ");
884 }
885 }
886 sb.append(" ]\r\n");
887 sb.append(" \"������\" : [ ");
888 for(int i = 0; i < creditors.size(); i++) {
889 AccountTitle accountTitle = creditors.get(i).getKey();
890 Amount amount = creditors.get(i).getValue();
891 sb.append("{ \"������������\" : \"" + YamlBeansUtil.escape(accountTitle.getDisplayName()) + "\", \"������\" : " + Math.abs(amount.getValue()) + " }");
892 if(i + 1 < creditors.size()) {
893 sb.append(", ");
894 }
895 }
896 sb.append(" ]\r\n");
897 sb.append("\r\n");
898 }
899 } else {
900 //������������������������������������������������������������������������������
901 List<Entry<AccountTitle, Amount>> list = new ArrayList<>(closingBalances.entrySet());
902 Collections.sort(list, (o1, o2) -> {
903 return accountTitles.indexOf(o1.getKey()) - accountTitles.indexOf(o2.getKey());
904 });
905 for(Entry<AccountTitle, Amount> e : list) {
906 AccountTitle accountTitle = e.getKey();
907 Amount amount = e.getValue();
908 if(accountTitle.getType() == AccountType.Assets) {
909 if(amount.getValue() == 0) {
910 continue;
911 } else if(amount.getValue() > 0) {
912 debtors.add(e);
913 } else {
914 creditors.add(e);
915 }
916 } else if(accountTitle.getType() == AccountType.Liabilities || accountTitle.getType() == AccountType.Equity) {
917 if(amount.getValue() == 0) {
918 continue;
919 } else if(amount.getValue() > 0) {
920 creditors.add(e);
921 } else {
922 debtors.add(e);
923 }
924 }
925 }
926
927 if(debtors.size() > 0 && creditors.size() > 0) {
928 sb.append("- \"������\" : \"" + nextOpeningDate + "\"\r\n");
929 sb.append(" \"������\" : \"������������\"\r\n");
930 sb.append(" \"������\" : [ ");
931 for(int i = 0; i < debtors.size(); i++) {
932 AccountTitle accountTitle = debtors.get(i).getKey();
933 Amount amount = debtors.get(i).getValue();
934 sb.append("{ \"������������\" : \"" + YamlBeansUtil.escape(accountTitle.getDisplayName()) + "\", \"������\" : " + Math.abs(amount.getValue()) + " }");
935 if(i + 1 < debtors.size()) {
936 sb.append(", ");
937 }
938 }
939 sb.append(" ]\r\n");
940 sb.append(" \"������\" : [ ");
941 for(int i = 0; i < creditors.size(); i++) {
942 AccountTitle accountTitle = creditors.get(i).getKey();
943 Amount amount = creditors.get(i).getValue();
944 sb.append("{ \"������������\" : \"" + YamlBeansUtil.escape(accountTitle.getDisplayName()) + "\", \"������\" : " + Math.abs(amount.getValue()) + " }");
945 if(i + 1 < creditors.size()) {
946 sb.append(", ");
947 }
948 }
949 sb.append(" ]\r\n");
950 sb.append("\r\n");
951 }
952 }
953
954 //��������������������� ��� ���������������������������������������������������������������
955 // ������������������������������������������������������������������������������������������������������������������������isOpening���false���������������������
956 for(JournalEntry entry : journalEntries) {
957 if(entry.isClosing()) {
958 continue;
959 }
960 for(Creditor creditor : entry.getCreditors()) {
961 if(creditor.getAccountTitle().getDisplayName().equals("���������������������")) {
962 sb.append("- \"������\" : \"" + nextOpeningDate + "\"\r\n");
963 sb.append(" \"������\" : \"������������\"\r\n");
964 sb.append(" \"������\" : [ { \"������������\" : \"���������������������\", \"������\" : " + creditor.getAmount() + " } ]\r\n");
965 sb.append(" \"������\" : [ ");
966 for(int i = 0; i < entry.getDebtors().size(); i++) {
967 Debtor debtor = entry.getDebtors().get(i);
968 sb.append("{ \"������������\" : \"" + YamlBeansUtil.escape(debtor.getAccountTitle().getDisplayName()) + "\", \"������\": " + debtor.getAmount() + " }");
969 if(i + 1 < entry.getDebtors().size()) {
970 sb.append(", ");
971 }
972 }
973 sb.append(" ]\r\n");
974 sb.append("\r\n");
975 break;
976 }
977 }
978 for(Debtor debtor : entry.getDebtors()) {
979 if(debtor.getAccountTitle().getDisplayName().equals("���������������������")) {
980 sb.append("- \"������\" : \"" + nextOpeningDate + "\"\r\n");
981 sb.append(" \"������\" : \"������������\"\r\n");
982 sb.append(" \"������\" : [ ");
983 for(int i = 0; i < entry.getCreditors().size(); i++) {
984 Creditor creditor = entry.getCreditors().get(i);
985 sb.append("{ \"������������\" : \"" + YamlBeansUtil.escape(creditor.getAccountTitle().getDisplayName()) + "\", \"������\" : " + creditor.getAmount() + " }");
986 if(i + 1 < entry.getCreditors().size()) {
987 sb.append(", ");
988 }
989 }
990 sb.append(" ]\r\n");
991 sb.append("\r\n");
992 break;
993 }
994 }
995 }
996
997
998 String s = sb.toString();
999
1000 if(path != null && Files.isDirectory(path.getParent())) {
1001 Path tmpFile = null;
1002 try {
1003 Path dir = path.getParent();
1004 // ���������������������������������������������������������������������������������������������������
1005 tmpFile = dir.resolve("������������������������.tmp");
1006 try {
1007 Files.writeString(tmpFile, s, StandardCharsets.UTF_8,
1008 StandardOpenOption.CREATE,
1009 StandardOpenOption.TRUNCATE_EXISTING,
1010 StandardOpenOption.WRITE,
1011 StandardOpenOption.SYNC);
1012 } catch(AccessDeniedException e) {
1013 Util.unsetDosAttributes(tmpFile);
1014 Files.writeString(tmpFile, s, StandardCharsets.UTF_8,
1015 StandardOpenOption.CREATE,
1016 StandardOpenOption.TRUNCATE_EXISTING,
1017 StandardOpenOption.WRITE,
1018 StandardOpenOption.SYNC);
1019 }
1020
1021 try {
1022 try {
1023 Files.move(tmpFile, path,
1024 StandardCopyOption.ATOMIC_MOVE,
1025 StandardCopyOption.REPLACE_EXISTING);
1026 } catch(AccessDeniedException e) {
1027 Util.unsetDosAttributes(tmpFile, path);
1028 Files.move(tmpFile, path,
1029 StandardCopyOption.ATOMIC_MOVE,
1030 StandardCopyOption.REPLACE_EXISTING);
1031 }
1032 } catch(AtomicMoveNotSupportedException e) {
1033 // ���������������������������������������������������������������������������������������������������������������
1034 // AtomicMoveNotSupportedException ���������������������������������������������������
1035 // AtomicMoveNotSupportedException ������������������������������ATOMIC_MOVE ���������������������������������
1036 try {
1037 Files.move(tmpFile, path,
1038 StandardCopyOption.REPLACE_EXISTING);
1039 } catch(AccessDeniedException e2) {
1040 Util.unsetDosAttributes(tmpFile, path);
1041 Files.move(tmpFile, path,
1042 StandardCopyOption.REPLACE_EXISTING);
1043 }
1044 }
1045 } finally {
1046 if(tmpFile != null) {
1047 try { Files.deleteIfExists(tmpFile); } catch(Exception ignore) {}
1048 }
1049 }
1050 }
1051
1052 return s;
1053 }
1054
1055 /** ������������������������������������������������������������
1056 * ���������������������������������������������������������������JSON���������������������������������������������
1057 * ���������������������CUI���������������������
1058 *
1059 * @param path ������������������������������������������������������null���������������������������������������������������������������������
1060 * @return ���������������������������������YAML���������
1061 * @throws IOException
1062 */
1063 public String createNextOpeningJournalEntriesCompat(List<AccountTitle> accountTitles, Path path) throws IOException {
1064 List<Entry<AccountTitle, Amount>> debtors = new ArrayList<>();
1065 long debtorsTotal = 0;
1066 List<Entry<AccountTitle, Amount>> creditors = new ArrayList<>();
1067 long creditorsTotal = 0;
1068
1069 StringBuilder sb = new StringBuilder();
1070 String nextOpeningDate = null;
1071 if(this.closingDate != null) {
1072 nextOpeningDate = DateTimeFormatter.ISO_LOCAL_DATE.format(this.closingDate.plusDays(1));
1073 }
1074
1075 if(isSoloProprietorship) {
1076 //���������������������������������������������������������������������������������������������������������������������������������������������������������
1077 //���������������������������������������������������������������������������������������������������������
1078 //���������������������������������������������������������
1079
1080 List<Entry<AccountTitle, Amount>> list = new ArrayList<>(closingBalances.entrySet());
1081 Collections.sort(list, (o1, o2) -> {
1082 return accountTitles.indexOf(o1.getKey()) - accountTitles.indexOf(o2.getKey());
1083 });
1084 for(Entry<AccountTitle, Amount> e : list) {
1085 AccountTitle accountTitle = e.getKey();
1086 Amount amount = e.getValue();
1087 // ��������������������������������������� ���������������������������
1088 if(accountTitle.getDisplayName().equals("������������") || accountTitle.getDisplayName().equals("������������") || accountTitle.getDisplayName().equals("���������")) {
1089 continue;
1090 }
1091 // ������������������������ ���������������������������
1092 if(accountTitle.equals(AccountTitle.PRETAX_INCOME)) {
1093 continue;
1094 }
1095 if(accountTitle.getType() == AccountType.Assets) {
1096 if(amount.getValue() == 0) {
1097 continue;
1098 } else if(amount.getValue() > 0) {
1099 debtors.add(e);
1100 debtorsTotal += amount.getValue();
1101 } else {
1102 creditors.add(e);
1103 creditorsTotal -= amount.getValue();
1104 }
1105 } else if(accountTitle.getType() == AccountType.Liabilities || accountTitle.getType() == AccountType.Equity) {
1106 if(amount.getValue() == 0) {
1107 continue;
1108 } else if(amount.getValue() > 0) {
1109 creditors.add(e);
1110 creditorsTotal += amount.getValue();
1111 } else {
1112 debtors.add(e);
1113 debtorsTotal -= amount.getValue();
1114 }
1115 }
1116 }
1117 AccountTitle capital = AccountTitle.getByDisplayName(new HashSet<>(accountTitles), "���������");
1118 if(capital != null) {
1119 Map.Entry<AccountTitle, Amount> e = Map.entry(capital, new Amount(Creditor.class, (debtorsTotal - creditorsTotal)));
1120 if(debtorsTotal >= creditorsTotal) {
1121 creditors.add(e);
1122 } else {
1123 debtors.add(e);
1124 }
1125 }
1126 if(debtors.size() > 0 && creditors.size() > 0) {
1127 sb.append("- ������: " + nextOpeningDate + "\r\n");
1128 sb.append(" ������: ���������\r\n");
1129 sb.append(" ������: [ ");
1130 for(int i = 0; i < debtors.size(); i++) {
1131 AccountTitle accountTitle = debtors.get(i).getKey();
1132 Amount amount = debtors.get(i).getValue();
1133 sb.append("{������������: " + accountTitle.getDisplayName() + ", ������: " + Math.abs(amount.getValue()) + "}");
1134 if(i + 1 < debtors.size()) {
1135 sb.append(", ");
1136 }
1137 }
1138 sb.append(" ]\r\n");
1139 sb.append(" ������: [ ");
1140 for(int i = 0; i < creditors.size(); i++) {
1141 AccountTitle accountTitle = creditors.get(i).getKey();
1142 Amount amount = creditors.get(i).getValue();
1143 sb.append("{������������: " + accountTitle.getDisplayName() + ", ������: " + Math.abs(amount.getValue()) + "}");
1144 if(i + 1 < creditors.size()) {
1145 sb.append(", ");
1146 }
1147 }
1148 sb.append(" ]\r\n");
1149 sb.append("\r\n");
1150 }
1151 } else {
1152 //������������������������������������������������������������������������������
1153 List<Entry<AccountTitle, Amount>> list = new ArrayList<>(closingBalances.entrySet());
1154 Collections.sort(list, (o1, o2) -> {
1155 return accountTitles.indexOf(o1.getKey()) - accountTitles.indexOf(o2.getKey());
1156 });
1157 for(Entry<AccountTitle, Amount> e : list) {
1158 AccountTitle accountTitle = e.getKey();
1159 Amount amount = e.getValue();
1160 if(accountTitle.getType() == AccountType.Assets) {
1161 if(amount.getValue() == 0) {
1162 continue;
1163 } else if(amount.getValue() > 0) {
1164 debtors.add(e);
1165 } else {
1166 creditors.add(e);
1167 }
1168 } else if(accountTitle.getType() == AccountType.Liabilities || accountTitle.getType() == AccountType.Equity) {
1169 if(amount.getValue() == 0) {
1170 continue;
1171 } else if(amount.getValue() > 0) {
1172 creditors.add(e);
1173 } else {
1174 debtors.add(e);
1175 }
1176 }
1177 }
1178
1179 if(debtors.size() > 0 && creditors.size() > 0) {
1180 sb.append("- ������: " + nextOpeningDate + "\r\n");
1181 sb.append(" ������: ������������\r\n");
1182 sb.append(" ������: [ ");
1183 for(int i = 0; i < debtors.size(); i++) {
1184 AccountTitle accountTitle = debtors.get(i).getKey();
1185 Amount amount = debtors.get(i).getValue();
1186 sb.append("{������������: " + accountTitle.getDisplayName() + ", ������: " + Math.abs(amount.getValue()) + "}");
1187 if(i + 1 < debtors.size()) {
1188 sb.append(", ");
1189 }
1190 }
1191 sb.append(" ]\r\n");
1192 sb.append(" ������: [ ");
1193 for(int i = 0; i < creditors.size(); i++) {
1194 AccountTitle accountTitle = creditors.get(i).getKey();
1195 Amount amount = creditors.get(i).getValue();
1196 sb.append("{������������: " + accountTitle.getDisplayName() + ", ������: " + Math.abs(amount.getValue()) + "}");
1197 if(i + 1 < creditors.size()) {
1198 sb.append(", ");
1199 }
1200 }
1201 sb.append(" ]\r\n");
1202 sb.append("\r\n");
1203 }
1204 }
1205
1206 //��������������������� ��� ���������������������������������������������������������������
1207 // ������������������������������������������������������������������������������������������������������������������������isOpening���false���������������������
1208 for(JournalEntry entry : journalEntries) {
1209 if(entry.isClosing()) {
1210 continue;
1211 }
1212 for(Creditor creditor : entry.getCreditors()) {
1213 if(creditor.getAccountTitle().getDisplayName().equals("���������������������")) {
1214 sb.append("- ������: " + nextOpeningDate + "\r\n");
1215 sb.append(" ������: ������������\r\n");
1216 sb.append(" ������: [ {������������: ���������������������, ������: " + creditor.getAmount() + "} ]\r\n");
1217 sb.append(" ������: [ ");
1218 for(int i = 0; i < entry.getDebtors().size(); i++) {
1219 Debtor debtor = entry.getDebtors().get(i);
1220 sb.append("{������������: " + debtor.getAccountTitle().getDisplayName() + ", ������: " + debtor.getAmount() + "}");
1221 if(i + 1 < entry.getDebtors().size()) {
1222 sb.append(", ");
1223 }
1224 }
1225 sb.append(" ]\r\n");
1226 sb.append("\r\n");
1227 break;
1228 }
1229 }
1230 for(Debtor debtor : entry.getDebtors()) {
1231 if(debtor.getAccountTitle().getDisplayName().equals("���������������������")) {
1232 sb.append("- ������: " + nextOpeningDate + "\r\n");
1233 sb.append(" ������: ������������\r\n");
1234 sb.append(" ������: [ ");
1235 for(int i = 0; i < entry.getCreditors().size(); i++) {
1236 Creditor creditor = entry.getCreditors().get(i);
1237 sb.append("{������������: " + creditor.getAccountTitle().getDisplayName() + ", ������: " + creditor.getAmount() + "}");
1238 if(i + 1 < entry.getCreditors().size()) {
1239 sb.append(", ");
1240 }
1241 }
1242 sb.append(" ]\r\n");
1243 sb.append("\r\n");
1244 break;
1245 }
1246 }
1247 }
1248
1249
1250 String s = sb.toString();
1251
1252 if(path != null && Files.isDirectory(path.getParent())) {
1253 Path tmpFile = null;
1254 try {
1255 Path dir = path.getParent();
1256 // ���������������������������������������������������������������������������������������������������
1257 tmpFile = dir.resolve("������������������������.tmp");
1258 try {
1259 Files.writeString(tmpFile, s, StandardCharsets.UTF_8,
1260 StandardOpenOption.CREATE,
1261 StandardOpenOption.TRUNCATE_EXISTING,
1262 StandardOpenOption.WRITE,
1263 StandardOpenOption.SYNC);
1264 } catch(AccessDeniedException e) {
1265 Util.unsetDosAttributes(tmpFile);
1266 Files.writeString(tmpFile, s, StandardCharsets.UTF_8,
1267 StandardOpenOption.CREATE,
1268 StandardOpenOption.TRUNCATE_EXISTING,
1269 StandardOpenOption.WRITE,
1270 StandardOpenOption.SYNC);
1271 }
1272
1273 try {
1274 try {
1275 Files.move(tmpFile, path,
1276 StandardCopyOption.ATOMIC_MOVE,
1277 StandardCopyOption.REPLACE_EXISTING);
1278 } catch(AccessDeniedException e) {
1279 Util.unsetDosAttributes(tmpFile, path);
1280 Files.move(tmpFile, path,
1281 StandardCopyOption.ATOMIC_MOVE,
1282 StandardCopyOption.REPLACE_EXISTING);
1283 }
1284 } catch(AtomicMoveNotSupportedException e) {
1285 // ���������������������������������������������������������������������������������������������������������������
1286 // AtomicMoveNotSupportedException ���������������������������������������������������
1287 // AtomicMoveNotSupportedException ������������������������������ATOMIC_MOVE ���������������������������������
1288 try {
1289 Files.move(tmpFile, path,
1290 StandardCopyOption.REPLACE_EXISTING);
1291 } catch(AccessDeniedException e2) {
1292 Util.unsetDosAttributes(tmpFile, path);
1293 Files.move(tmpFile, path,
1294 StandardCopyOption.REPLACE_EXISTING);
1295 }
1296 }
1297 } finally {
1298 if(tmpFile != null) {
1299 try { Files.deleteIfExists(tmpFile); } catch(Exception ignore) {}
1300 }
1301 }
1302 }
1303
1304 return s;
1305 }
1306
1307 private static String formatMoney(long amount) {
1308 if(MINUS_SIGN != null && amount < 0) {
1309 return MINUS_SIGN + String.format("%,d", -amount);
1310 }
1311 return String.format("%,d", amount);
1312 }
1313
1314 private void dump(Node<Entry<List<AccountTitle>, Amount[]>> node) {
1315 StringBuilder sb = new StringBuilder();
1316 for(int i = 0; i < node.getLevel(); i++) {
1317 sb.append(" - ");
1318 }
1319 sb.append(node.getName());
1320 Amount[] amounts = node.getValue().getValue();
1321 sb.append("{ " + amounts[0] + ", " + amounts[1] + " } ");
1322 if(node.getValue().getKey() != null) {
1323 sb.append(": [");
1324 for(int i = 0; i < node.getValue().getKey().size(); i++) {
1325 sb.append(node.getValue().getKey().get(i).getDisplayName());
1326 if(i + 1 < node.getValue().getKey().size()) {
1327 sb.append(", ");
1328 }
1329 }
1330 sb.append("]");
1331 }
1332 System.out.println(sb.toString());
1333 for(Node<Entry<List<AccountTitle>, Amount[]>> child : node.getChildren()) {
1334 dump(child);
1335 }
1336 }
1337 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26