Revision 37a9413b
Von Sven Schöling vor mehr als 9 Jahren hinzugefügt
scripts/migrate_icons.pl | ||
---|---|---|
1 |
|
|
2 |
use strict; |
|
3 |
use warnings; |
|
4 |
|
|
5 |
my %icons = ( |
|
6 |
'AP--Add Purchase Order.png' => 'purchase_order_add.png', |
|
7 |
'AP--Add RFQ.png' => 'rfq_add.png', |
|
8 |
'AP.png' => 'ap.png', |
|
9 |
'AP--Reports.png' => 'ap_report.png', |
|
10 |
'AP--Reports--Purchase Orders.png' => 'purchase_order_report.png', |
|
11 |
'AP--Reports--RFQs.png' => 'rfq_report.png', |
|
12 |
'AR--Add Credit Note.png' => 'credit_note_add.png', |
|
13 |
'AR--Add Delivery Order.png' => 'delivery_oder_add.png', # symlink to MDI-Txt_editor |
|
14 |
'AR--Add Dunning.png' => 'dunning_add.png', |
|
15 |
'AR--Add Quotation.png' => 'quotation_add.png', |
|
16 |
'AR--Add Sales Invoice.png' => 'sales_invoice_add.png', |
|
17 |
'AR--Add Sales Order.png' => 'sales_order_add.png', |
|
18 |
'AR.png' => 'ar.png', |
|
19 |
'AR--Reports--Delivery Orders.png' => 'delivery_order_report.png', # symlink to MDI-Text_editor |
|
20 |
'AR--Reports--Dunnings.png' => 'dunnings_report.png', |
|
21 |
'AR--Reports--Invoices, Credit Notes & AR Transactions.png' => 'invoices_report.png', |
|
22 |
'AR--Reports.png' => 'ar_report.png', |
|
23 |
'AR--Reports--Quotations.png' => 'report_quotations.png', |
|
24 |
'AR--Reports--Sales Orders.png' => 'report_sales_orders.png', |
|
25 |
'Batch Printing--Packing Lists.png' => 'package_lists.png', |
|
26 |
'Batch Printing.png' => 'printing.png', |
|
27 |
'Batch Printing--Purchase Orders.png' => 'purchase_order_printing.png', |
|
28 |
'Batch Printing--Quotations.png' => 'quotation_printing.png', |
|
29 |
'Batch Printing--Receipts.png' => 'receipt_printing.png', |
|
30 |
'Batch Printing--RFQs.png' => 'rfq_printing.png', |
|
31 |
'Batch Printing--Sales Invoices.png' => 'sales_invoice_printing.png', |
|
32 |
'Batch Printing--Sales Orders.png' => 'sales_order_printing.png', |
|
33 |
'Cash--Payment.png' => 'payment.png', |
|
34 |
'Cash.png' => 'cash.png', |
|
35 |
'Cash--Receipt.png' => 'receipt.png', |
|
36 |
'Cash--Reconciliation.png' => 'reconcilliation.png', |
|
37 |
'Cash--Reports--Payments.png' => 'payment_report.png', |
|
38 |
'Cash--Reports.png' => 'cash_report.png', |
|
39 |
'Cash--Reports--Receipts.png' => 'receipt_report.png', |
|
40 |
'CRM--Add--Customer.png' => 'customer.png', |
|
41 |
'CRM--Add--Person.png' => 'contact.png', |
|
42 |
'CRM--Add--Vendor.png' => 'vendor.png', |
|
43 |
'CRM--Admin--Document Template.png' => 'document_template.png', |
|
44 |
'CRM--Admin--Label.png' => 'label.png', |
|
45 |
'CRM--Admin--Message.png' => 'message.png', |
|
46 |
'CRM--Admin.png' => 'admin.png', |
|
47 |
'CRM--Admin--Status.png' => 'status.png', |
|
48 |
'CRM--Admin--User Groups.png' => 'user_group.png', |
|
49 |
'CRM--Admin--User.png' => 'user.png', |
|
50 |
'CRM--Appointments.png' => 'appointment.png', |
|
51 |
'CRM--E-mail.png' => 'email.png', |
|
52 |
'CRM--Follow-Up.png' => 'follow_up.png', |
|
53 |
'CRM--Help.png' => 'help.png', |
|
54 |
'CRM--Knowledge.png' => 'knowledge.png', |
|
55 |
'CRM--Memo.png' => 'memo.png', |
|
56 |
'CRM--Opportunity.png' => 'opportunity.png', |
|
57 |
'CRM.png' => 'crm.png', |
|
58 |
'CRM--Search.png' => 'search.png', |
|
59 |
'CRM--Service.png' => 'service.png', |
|
60 |
'General Ledger--Add AP Transaction.png' => 'ap_transaction_add.png', |
|
61 |
'General Ledger--Add AR Transaction.png' => 'ar_transaction_add.png', |
|
62 |
'General Ledger--Add Transaction.png' => 'transaction_add.png', |
|
63 |
'General Ledger--DATEV - Export Assistent.png' => 'datev.png', |
|
64 |
'General Ledger.png' => 'gl.png', |
|
65 |
'General Ledger--Reports--AP Aging.png' => 'ap_aging.png', |
|
66 |
'General Ledger--Reports--AR Aging.png' => 'ar_aging.png', |
|
67 |
'General Ledger--Reports--Journal.png' => 'journal.png', |
|
68 |
'General Ledger--Reports.png' => 'gl_report.png', |
|
69 |
'Master Data--Add Assembly.png' => 'assembly_add.png', |
|
70 |
'Master Data--Add Customer.png' => 'customer_add.png', |
|
71 |
'Master Data--Add License.png' => 'license_add.png', |
|
72 |
'Master Data--Add Part.png' => 'part_add.png', |
|
73 |
'Master Data--Add Project.png' => 'project_add.png', |
|
74 |
'Master Data--Add Service.png' => 'service_add.png', |
|
75 |
'Master Data--Add Vendor.png' => 'vendor_add.png', |
|
76 |
'Master Data.png' => 'master_data.png', |
|
77 |
'Master Data--Reports--Assemblies.png' => 'assembly_report.png', |
|
78 |
'Master Data--Reports--Customers.png' => 'customer_report.png', |
|
79 |
'Master Data--Reports--Licenses.png' => 'license_report.png', |
|
80 |
'Master Data--Reports--Parts.png' => 'part_report.png', |
|
81 |
'Master Data--Reports.png' => 'master_data_report.png', |
|
82 |
'Master Data--Reports--Projects.png' => 'project_report.png', |
|
83 |
'Master Data--Reports--Projecttransactions.png' => 'project_transaction_report.png', |
|
84 |
'Master Data--Reports--Services.png' => 'service_report.png', |
|
85 |
'Master Data--Reports--Vendors.png' => 'vendor_report.png', |
|
86 |
'Master Data--Update Prices.png' => 'prices_update.png', |
|
87 |
'Neues Fenster.png' => 'window_new.png', |
|
88 |
'phone.png' => 'phone.png', |
|
89 |
'Program--Logout.png' => 'logout.png', |
|
90 |
'Program.png' => 'program.png', |
|
91 |
'Program--Preferences.png' => 'preferences.png', |
|
92 |
'Program--Version.png' => 'version.png', |
|
93 |
'Reports--Balance Sheet.png' => 'balance_sheet.png', |
|
94 |
'Reports--Chart of Accounts.png' => 'chart_of_accounts.png', |
|
95 |
'Reports--Income Statement.png' => 'income_statement.png', |
|
96 |
'Reports.png' => 'report.png', |
|
97 |
'Reports--UStVa.png' => 'ustva.png', |
|
98 |
'System.png' => 'system.png', |
|
99 |
'Warehouse.png' => 'warehouse.png', |
|
100 |
'Warehouse--Produce Assembly.png' => 'assembly_produce.png', |
|
101 |
'MDI-Text-Editor-16x16.png' => 'mdi_text_editor.png', |
|
102 |
'Productivity' => 'productivity.png', |
|
103 |
); |
|
104 |
|
|
105 |
my %symlinks = ( |
|
106 |
'mdi_text_editor.png' => 'delivery_order_add.png', # symlink to MDI-Txt_editor |
|
107 |
'mdi_text_editor.png' => 'delivery_order_report.png', # symlink to MDI-Txt_editor |
|
108 |
); |
|
109 |
|
|
110 |
sub checks { |
|
111 |
# check 1: no duplicate targets |
|
112 |
my %seen; |
|
113 |
for (values %icons) { |
|
114 |
next unless defined $_; |
|
115 |
die "duplicate target: $_" if $seen{$_}++; |
|
116 |
} |
|
117 |
|
|
118 |
# check2: all targets should end in .png, otherwise there's a typo |
|
119 |
for (values %icons) { |
|
120 |
next unless defined $_; |
|
121 |
die "target does not end in .png: $_" unless /\.png$/; |
|
122 |
} |
|
123 |
|
|
124 |
# check 3: all sources need to be real files in this dir |
|
125 |
for (keys %icons) { |
|
126 |
next unless defined $_; |
|
127 |
die "key $_ is not a file!" unless -f $_; |
|
128 |
} |
|
129 |
|
|
130 |
# check 4: all keys in symlinks need to be a target in icons |
|
131 |
for (keys %symlinks) { |
|
132 |
no warnings 'uninitialized'; |
|
133 |
die "can't symlink this, because it's not a target of renaming: $_" unless { reverse %icons }->{$_}; |
|
134 |
} |
|
135 |
} |
|
136 |
|
|
137 |
sub make_icons { |
|
138 |
# now do the actual renaming |
|
139 |
while (my ($from, $to) = each(%icons)) { |
|
140 |
if (defined $to) { |
|
141 |
# rename |
|
142 |
system("git mv '$from' '$to'"); |
|
143 |
} else { |
|
144 |
# delete |
|
145 |
system("git rm '$from'"); |
|
146 |
} |
|
147 |
} |
|
148 |
|
|
149 |
# and do some symlinking |
|
150 |
while (my ($from, $to) = each(%symlinks)) { |
|
151 |
system("ln -s '$from' '$to'"); |
|
152 |
system("git add '$to'"); |
|
153 |
} |
|
154 |
} |
|
155 |
|
|
156 |
sub translate_menu { |
|
157 |
my ($menu_file) = @_; |
|
158 |
|
|
159 |
my $new_file = $menu_file; |
|
160 |
$new_file =~ s/\./_new\./; |
|
161 |
|
|
162 |
open my $in, "<", $menu_file or die "error opening $menu_file: $!"; |
|
163 |
open my $out, ">", $new_file or die "error opening $new_file: $!"; |
|
164 |
|
|
165 |
while (<$in>) { |
|
166 |
print $out $_; |
|
167 |
if (/^\[(.*)\]$/) { |
|
168 |
my $name = $1; |
|
169 |
# look if we got this in %icons |
|
170 |
if ($icons{ $name . '.png' }) { |
|
171 |
my $new_name = $icons{ $name . '.png' }; |
|
172 |
$new_name =~ s/\.png$//; |
|
173 |
print $out "ICON=$new_name\n"; |
|
174 |
} else { |
|
175 |
warn "don't know what '$name' is in $menu_file"; |
|
176 |
} |
|
177 |
} |
|
178 |
} |
|
179 |
system("mv $new_file $menu_file"); |
|
180 |
} |
|
181 |
|
|
182 |
# checks(); |
|
183 |
# make_icons(); |
|
184 |
|
|
185 |
translate_menu('menus/erp.ini'); |
|
186 |
translate_menu('menus/admin.ini'); |
|
187 |
translate_menu('menus/crm.ini'); |
scripts/migrate_menu.pl | ||
---|---|---|
1 |
#!/usr/bin/perl |
|
2 |
|
|
3 |
use strict; |
|
4 |
use SL::Dispatcher; |
|
5 |
use SL::Inifile; |
|
6 |
use SL::LXDebug; |
|
7 |
use Data::Dumper; |
|
8 |
use JSON; |
|
9 |
use YAML; |
|
10 |
use Cwd; |
|
11 |
|
|
12 |
$::lxdebug = LXDebug->new; |
|
13 |
|
|
14 |
my %menu_files = ( |
|
15 |
'menus/erp.ini' => 'menus/user/00-erp.yaml', |
|
16 |
'menus/crm.ini' => 'menus/user/10-crm.yaml', |
|
17 |
'menus/admin.ini' => 'menus/admin/00-admin.yaml', |
|
18 |
); |
|
19 |
|
|
20 |
my %known_arguments = ( |
|
21 |
ICON => 'icon', |
|
22 |
ACCESS => 'access', |
|
23 |
INSTANCE_CONF => 'INSTANCE_CONF', |
|
24 |
module => 'module', |
|
25 |
submenu => 'submenu', |
|
26 |
target => 'target', |
|
27 |
href => 'href', |
|
28 |
); |
|
29 |
|
|
30 |
sub translate_to_yaml { |
|
31 |
my ($menu_file, $new_file) = @_; |
|
32 |
|
|
33 |
my %counter; |
|
34 |
|
|
35 |
my $menu = Inifile->new($menu_file); |
|
36 |
my @menu_items = map { +{ %{ $menu->{$_} }, ID => $_ } } @{ delete $menu->{ORDER} }; |
|
37 |
|
|
38 |
for my $item (@menu_items) { |
|
39 |
# parse id |
|
40 |
my @tokens = split /--/, delete $item->{ID}; |
|
41 |
my $name = pop @tokens; |
|
42 |
my $parent = join '_', map { lc $_ } @tokens; |
|
43 |
my $id = join '_', grep $_, $parent, lc $name; |
|
44 |
|
|
45 |
# move unknown arguments to param subhash |
|
46 |
my @keys = keys %$item; |
|
47 |
my %params; |
|
48 |
for (@keys) { |
|
49 |
next if $known_arguments{$_}; |
|
50 |
$params{$_} = delete $item->{$_}; |
|
51 |
} |
|
52 |
|
|
53 |
$item->{params} = \%params if keys %params; |
|
54 |
|
|
55 |
# sanitize keys |
|
56 |
for (keys %known_arguments) { |
|
57 |
next unless exists $item->{$_}; |
|
58 |
my $val = delete $item->{$_}; |
|
59 |
$item->{ $known_arguments{$_} } = $val; |
|
60 |
} |
|
61 |
|
|
62 |
# sanitize submenu |
|
63 |
if ($item->{submenu}) { |
|
64 |
delete $item->{submenu}; |
|
65 |
} |
|
66 |
|
|
67 |
#sanitize those stupid menu inlinks |
|
68 |
if ($item->{module} eq 'menu.pl') { |
|
69 |
delete $item->{module}; |
|
70 |
delete $item->{action}; |
|
71 |
delete $item->{target}; |
|
72 |
} |
|
73 |
|
|
74 |
# sanitize INSTANCE_CONF |
|
75 |
if ($item->{INSTANCE_CONF}) { |
|
76 |
my $instance_conf = delete $item->{INSTANCE_CONF}; |
|
77 |
if ($item->{access}) { |
|
78 |
if ($item->{access} =~ /\W/) { |
|
79 |
$item->{access} = "client/$instance_conf & ( $item->{access} )"; |
|
80 |
} else { |
|
81 |
$item->{access} = "client/$instance_conf & $item->{access}"; |
|
82 |
} |
|
83 |
} else { |
|
84 |
$item->{access} = "client/$instance_conf"; |
|
85 |
} |
|
86 |
} |
|
87 |
|
|
88 |
# make controller.pl implicit |
|
89 |
if ($item->{module} && $item->{module} eq 'controller.pl') { |
|
90 |
delete $item->{module}; |
|
91 |
} |
|
92 |
|
|
93 |
# add id |
|
94 |
$item->{id} = $id; |
|
95 |
$item->{id} =~ s/[^\w]+/_/g; |
|
96 |
|
|
97 |
# add to name |
|
98 |
$item->{name} = $name; |
|
99 |
|
|
100 |
# add parent |
|
101 |
if ($parent) { |
|
102 |
$item->{parent} = $parent; |
|
103 |
$item->{parent} =~ s/[^\w]+/_/g if $item->{parent}; |
|
104 |
} |
|
105 |
|
|
106 |
# add order |
|
107 |
$item->{order} = 100 * ++$counter{ $item->{parent} }; |
|
108 |
} |
|
109 |
|
|
110 |
if ($menu_file =~ /crm/) { |
|
111 |
$menu_items[0]{order} = 50; # crm first |
|
112 |
} |
|
113 |
|
|
114 |
open my $out_file, '>:utf8', $new_file or die $!; |
|
115 |
print $out_file yaml_dump(\@menu_items); |
|
116 |
} |
|
117 |
|
|
118 |
sub yaml_dump { |
|
119 |
my ($ary_ref) = @_; |
|
120 |
# YAML dumps keys lexically sorted, which isn't what we want. |
|
121 |
# we want this order: |
|
122 |
my @order = qw( |
|
123 |
parent |
|
124 |
id |
|
125 |
name |
|
126 |
icon |
|
127 |
order |
|
128 |
access |
|
129 |
href |
|
130 |
module |
|
131 |
target |
|
132 |
params |
|
133 |
); |
|
134 |
|
|
135 |
# ...oh and we want action in params first |
|
136 |
# |
|
137 |
# why this? because: |
|
138 |
# 1. parent is what is used to anchor. one could argue that id should be |
|
139 |
# first, but parent is easier for understanding structure. |
|
140 |
# 2. after parent the logical structure is |
|
141 |
# 1. id |
|
142 |
# 2. stuff related to vidual presentation (name/icon) |
|
143 |
# 3. stuff needed for logical presentaion (order/access) |
|
144 |
# 4. stuff related to the action after clicking it |
|
145 |
# 3. without parent and href (the second is pretty rare) the keys are nicely |
|
146 |
# ascending in length, which is very easy to parse visually. |
|
147 |
|
|
148 |
my $yaml = "---\n"; |
|
149 |
for my $node (@$ary_ref) { |
|
150 |
my $first = 0; |
|
151 |
for my $key (@order) { |
|
152 |
next unless exists $node->{$key}; |
|
153 |
$yaml .= ($first++ ? ' ' : '- ') . $key . ":"; |
|
154 |
if (!ref $node->{$key}) { |
|
155 |
$yaml .= ' ' . $node->{$key} . "\n"; |
|
156 |
} else { |
|
157 |
$yaml .= "\n"; |
|
158 |
for ('action', grep !/^action$/, keys %{ $node->{$key} }) { |
|
159 |
next unless exists $node->{$key}{$_}; |
|
160 |
$yaml .= " $_: $node->{$key}{$_}\n"; |
|
161 |
} |
|
162 |
} |
|
163 |
|
|
164 |
} |
|
165 |
} |
|
166 |
|
|
167 |
$yaml; |
|
168 |
} |
|
169 |
|
|
170 |
while (my ($in, $out) = each(%menu_files)) { |
|
171 |
translate_to_yaml($in, $out); |
|
172 |
} |
|
173 |
|
Auch abrufbar als: Unified diff
Migrationsscripte löschen