Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.61% |
1 / 164 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
Installer | |
0.61% |
1 / 164 |
|
0.00% |
0 / 5 |
1102.20 | |
0.00% |
0 / 1 |
install | |
4.00% |
1 / 25 |
|
0.00% |
0 / 1 |
50.35 | |||
createBillAttributeTypes | |
0.00% |
0 / 33 |
|
0.00% |
0 / 1 |
42 | |||
createBillAttributeValues | |
0.00% |
0 / 36 |
|
0.00% |
0 / 1 |
90 | |||
createTaxCombination | |
0.00% |
0 / 35 |
|
0.00% |
0 / 1 |
30 | |||
createBillTypes | |
0.00% |
0 / 35 |
|
0.00% |
0 / 1 |
42 |
1 | <?php |
2 | /** |
3 | * Jingga |
4 | * |
5 | * PHP Version 8.1 |
6 | * |
7 | * @package Modules\Billing\Admin |
8 | * @copyright Dennis Eichhorn |
9 | * @license OMS License 2.0 |
10 | * @version 1.0.0 |
11 | * @link https://jingga.app |
12 | */ |
13 | declare(strict_types=1); |
14 | |
15 | namespace Modules\Billing\Admin; |
16 | |
17 | use Modules\Billing\Models\BillTransferType; |
18 | use Modules\ClientManagement\Models\Attribute\ClientAttributeTypeMapper; |
19 | use Modules\ItemManagement\Models\Attribute\ItemAttributeTypeMapper; |
20 | use Modules\SupplierManagement\Models\SupplierAttributeTypeMapper; |
21 | use phpOMS\Application\ApplicationAbstract; |
22 | use phpOMS\Config\SettingsInterface; |
23 | use phpOMS\Message\Http\HttpRequest; |
24 | use phpOMS\Message\Http\HttpResponse; |
25 | use phpOMS\Module\InstallerAbstract; |
26 | use phpOMS\Module\ModuleInfo; |
27 | use phpOMS\Uri\HttpUri; |
28 | |
29 | /** |
30 | * Installer class. |
31 | * |
32 | * @package Modules\Billing\Admin |
33 | * @license OMS License 2.0 |
34 | * @link https://jingga.app |
35 | * @since 1.0.0 |
36 | */ |
37 | final class Installer extends InstallerAbstract |
38 | { |
39 | /** |
40 | * Path of the file |
41 | * |
42 | * @var string |
43 | * @since 1.0.0 |
44 | */ |
45 | public const PATH = __DIR__; |
46 | |
47 | /** |
48 | * {@inheritdoc} |
49 | */ |
50 | public static function install(ApplicationAbstract $app, ModuleInfo $info, SettingsInterface $cfgHandler) : void |
51 | { |
52 | parent::install($app, $info, $cfgHandler); |
53 | |
54 | // Install bill type templates |
55 | $media = \Modules\Media\Admin\Installer::installExternal($app, ['path' => __DIR__ . '/Install/Media2.install.json']); |
56 | |
57 | /** @var int $defaultTemplate */ |
58 | $defaultTemplate = (int) \reset($media['upload'][0]); |
59 | |
60 | /* Bill types */ |
61 | $fileContent = \file_get_contents(__DIR__ . '/Install/types.json'); |
62 | if ($fileContent === false) { |
63 | return; |
64 | } |
65 | |
66 | /** @var array $types */ |
67 | $types = \json_decode($fileContent, true); |
68 | if ($types === false) { |
69 | return; |
70 | } |
71 | |
72 | self::createBillTypes($app, $types, $defaultTemplate); |
73 | |
74 | /* Tax types */ |
75 | $fileContent = \file_get_contents(__DIR__ . '/Install/Taxes/taxes.json'); |
76 | if ($fileContent === false) { |
77 | return; |
78 | } |
79 | |
80 | /** @var array $taxes */ |
81 | $taxes = \json_decode($fileContent, true); |
82 | if ($taxes === false) { |
83 | return; |
84 | } |
85 | |
86 | self::createTaxCombination($app, $taxes); |
87 | |
88 | /* Attributes */ |
89 | $fileContent = \file_get_contents(__DIR__ . '/Install/attributes.json'); |
90 | if ($fileContent === false) { |
91 | return; |
92 | } |
93 | |
94 | /** @var array $attributes */ |
95 | $attributes = \json_decode($fileContent, true); |
96 | if ($attributes === false) { |
97 | return; |
98 | } |
99 | |
100 | $attrTypes = self::createBillAttributeTypes($app, $attributes); |
101 | $attrValues = self::createBillAttributeValues($app, $attrTypes, $attributes); |
102 | } |
103 | |
104 | /** |
105 | * Install default attribute types |
106 | * |
107 | * @param ApplicationAbstract $app Application |
108 | * @param array $attributes Attribute definition |
109 | * |
110 | * @return array |
111 | * |
112 | * @since 1.0.0 |
113 | */ |
114 | private static function createBillAttributeTypes(ApplicationAbstract $app, array $attributes) : array |
115 | { |
116 | /** @var array $billAttrType */ |
117 | $billAttrType = []; |
118 | |
119 | /** @var \Modules\Billing\Controller\ApiController $module */ |
120 | $module = $app->moduleManager->getModuleInstance('Billing'); |
121 | |
122 | /** @var array $attribute */ |
123 | foreach ($attributes as $attribute) { |
124 | $response = new HttpResponse(); |
125 | $request = new HttpRequest(new HttpUri('')); |
126 | |
127 | $request->header->account = 1; |
128 | $request->setData('name', $attribute['name'] ?? ''); |
129 | $request->setData('title', \reset($attribute['l11n'])); |
130 | $request->setData('language', \array_keys($attribute['l11n'])[0] ?? 'en'); |
131 | $request->setData('is_required', $attribute['is_required'] ?? false); |
132 | $request->setData('custom', $attribute['is_custom_allowed'] ?? false); |
133 | $request->setData('validation_pattern', $attribute['validation_pattern'] ?? ''); |
134 | $request->setData('datatype', (int) $attribute['value_type']); |
135 | |
136 | $module->apiBillAttributeTypeCreate($request, $response); |
137 | |
138 | $responseData = $response->get(''); |
139 | |
140 | if (!\is_array($responseData)) { |
141 | continue; |
142 | } |
143 | |
144 | $billAttrType[$attribute['name']] = \is_array($responseData['response']) |
145 | ? $responseData['response'] |
146 | : $responseData['response']->toArray(); |
147 | |
148 | $isFirst = true; |
149 | foreach ($attribute['l11n'] as $language => $l11n) { |
150 | if ($isFirst) { |
151 | $isFirst = false; |
152 | continue; |
153 | } |
154 | |
155 | $response = new HttpResponse(); |
156 | $request = new HttpRequest(new HttpUri('')); |
157 | |
158 | $request->header->account = 1; |
159 | $request->setData('title', $l11n); |
160 | $request->setData('language', $language); |
161 | $request->setData('type', $billAttrType[$attribute['name']]['id']); |
162 | |
163 | $module->apiBillAttributeTypeL11nCreate($request, $response); |
164 | } |
165 | } |
166 | |
167 | return $billAttrType; |
168 | } |
169 | |
170 | /** |
171 | * Create default attribute values for types |
172 | * |
173 | * @param ApplicationAbstract $app Application |
174 | * @param array $billAttrType Attribute types |
175 | * @param array<array{name:string, l11n?:array<string, string>, is_required?:bool, is_custom_allowed?:bool, validation_pattern?:string, value_type?:string, values?:array<string, mixed>}> $attributes Attribute definition |
176 | * |
177 | * @return array<string, array> |
178 | * |
179 | * @since 1.0.0 |
180 | */ |
181 | private static function createBillAttributeValues(ApplicationAbstract $app, array $billAttrType, array $attributes) : array |
182 | { |
183 | /** @var array<string, array> $billAttrValue */ |
184 | $billAttrValue = []; |
185 | |
186 | /** @var \Modules\Billing\Controller\ApiController $module */ |
187 | $module = $app->moduleManager->getModuleInstance('Billing'); |
188 | |
189 | foreach ($attributes as $attribute) { |
190 | $billAttrValue[$attribute['name']] = []; |
191 | |
192 | /** @var array $value */ |
193 | foreach ($attribute['values'] as $value) { |
194 | $response = new HttpResponse(); |
195 | $request = new HttpRequest(new HttpUri('')); |
196 | |
197 | $request->header->account = 1; |
198 | $request->setData('value', $value['value'] ?? ''); |
199 | $request->setData('unit', $value['unit'] ?? ''); |
200 | $request->setData('default', true); // always true since all defined values are possible default values |
201 | $request->setData('type', $billAttrType[$attribute['name']]['id']); |
202 | |
203 | if (isset($value['l11n']) && !empty($value['l11n'])) { |
204 | $request->setData('title', \reset($value['l11n'])); |
205 | $request->setData('language', \array_keys($value['l11n'])[0] ?? 'en'); |
206 | } |
207 | |
208 | $module->apiBillAttributeValueCreate($request, $response); |
209 | |
210 | $responseData = $response->get(''); |
211 | if (!\is_array($responseData)) { |
212 | continue; |
213 | } |
214 | |
215 | $attrValue = \is_array($responseData['response']) |
216 | ? $responseData['response'] |
217 | : $responseData['response']->toArray(); |
218 | |
219 | $billAttrValue[$attribute['name']][] = $attrValue; |
220 | |
221 | $isFirst = true; |
222 | foreach (($value['l11n'] ?? []) as $language => $l11n) { |
223 | if ($isFirst) { |
224 | $isFirst = false; |
225 | continue; |
226 | } |
227 | |
228 | $response = new HttpResponse(); |
229 | $request = new HttpRequest(new HttpUri('')); |
230 | |
231 | $request->header->account = 1; |
232 | $request->setData('title', $l11n); |
233 | $request->setData('language', $language); |
234 | $request->setData('value', $attrValue['id']); |
235 | |
236 | $module->apiBillAttributeValueL11nCreate($request, $response); |
237 | } |
238 | } |
239 | } |
240 | |
241 | return $billAttrValue; |
242 | } |
243 | |
244 | /** |
245 | * Create tax combinations (item & client/supplier) |
246 | * |
247 | * @param ApplicationAbstract $app Application |
248 | * @param array $taxes Tax data |
249 | * |
250 | * @return array<string, array> |
251 | * |
252 | * @since 1.0.0 |
253 | */ |
254 | private static function createTaxCombination(ApplicationAbstract $app, array $taxes) : array |
255 | { |
256 | $result = []; |
257 | |
258 | /** @var \Modules\Billing\Controller\ApiController $module */ |
259 | $module = $app->moduleManager->getModuleInstance('Billing'); |
260 | |
261 | /** @var \Modules\Attribute\Models\AttributeType $itemAttributeSales */ |
262 | $itemAttributeSales = ItemAttributeTypeMapper::get() |
263 | ->with('defaults') |
264 | ->where('name', 'sales_tax_code') |
265 | ->execute(); |
266 | |
267 | /** @var \Modules\Attribute\Models\AttributeType $clientAttributeSales */ |
268 | $clientAttributeSales = ClientAttributeTypeMapper::get() |
269 | ->with('defaults') |
270 | ->where('name', 'sales_tax_code') |
271 | ->execute(); |
272 | |
273 | /** @var \Modules\Attribute\Models\AttributeType $supplierAttributeSales */ |
274 | $supplierAttributeSales = SupplierAttributeTypeMapper::get() |
275 | ->with('defaults') |
276 | ->where('name', 'purchase_tax_code') |
277 | ->execute(); |
278 | |
279 | foreach ($taxes as $tax) { |
280 | $itemValue = $itemAttributeSales->getDefaultByValue($tax['item_code']); |
281 | $accountValue = $tax['type'] === 1 |
282 | ? $clientAttributeSales->getDefaultByValue($tax['account_code']) |
283 | : $supplierAttributeSales->getDefaultByValue($tax['account_code']); |
284 | |
285 | $response = new HttpResponse(); |
286 | $request = new HttpRequest(new HttpUri('')); |
287 | |
288 | $request->header->account = 1; |
289 | $request->setData('tax_type', $tax['type']); |
290 | $request->setData('tax_code', $tax['tax_code']); |
291 | $request->setData('item_code', $itemValue->id); |
292 | $request->setData('account_code', $accountValue->id); |
293 | |
294 | $module->apiTaxCombinationCreate($request, $response); |
295 | |
296 | $responseData = $response->get(''); |
297 | if (!\is_array($responseData)) { |
298 | continue; |
299 | } |
300 | |
301 | $result = \is_array($responseData['response']) |
302 | ? $responseData['response'] |
303 | : $responseData['response']->toArray(); |
304 | |
305 | $results[] = $result; |
306 | } |
307 | |
308 | return $result; |
309 | } |
310 | |
311 | /** |
312 | * Install default bill types |
313 | * |
314 | * @param ApplicationAbstract $app Application |
315 | * @param array $types Bill types |
316 | * @param int $template Default template |
317 | * |
318 | * @return array |
319 | * |
320 | * @since 1.0.0 |
321 | */ |
322 | private static function createBillTypes(ApplicationAbstract $app, array $types, int $template) : array |
323 | { |
324 | $billTypes = []; |
325 | |
326 | /** @var \Modules\Billing\Controller\ApiController $module */ |
327 | $module = $app->moduleManager->getModuleInstance('Billing'); |
328 | |
329 | // @todo: allow multiple alternative bill templates |
330 | // @todo: implement ordering of templates |
331 | |
332 | foreach ($types as $type) { |
333 | $response = new HttpResponse(); |
334 | $request = new HttpRequest(new HttpUri('')); |
335 | |
336 | $request->header->account = 1; |
337 | $request->setData('name', $type['name'] ?? ''); |
338 | $request->setData('title', \reset($type['l11n'])); |
339 | $request->setData('language', \array_keys($type['l11n'])[0] ?? 'en'); |
340 | $request->setData('number_format', $type['numberFormat'] ?? '{id}'); |
341 | $request->setData('transfer_stock', $type['transferStock'] ?? false); |
342 | $request->setData('is_template', $type['isTemplate'] ?? false); |
343 | $request->setData('transfer_type', $type['transferType'] ?? BillTransferType::SALES); |
344 | $request->setData('template', $template); |
345 | |
346 | $module->apiBillTypeCreate($request, $response); |
347 | |
348 | $responseData = $response->get(''); |
349 | if (!\is_array($responseData)) { |
350 | continue; |
351 | } |
352 | |
353 | $billType = \is_array($responseData['response']) |
354 | ? $responseData['response'] |
355 | : $responseData['response']->toArray(); |
356 | |
357 | $billTypes[] = $billType; |
358 | |
359 | $isFirst = true; |
360 | foreach ($type['l11n'] as $language => $l11n) { |
361 | if ($isFirst) { |
362 | $isFirst = false; |
363 | continue; |
364 | } |
365 | |
366 | $response = new HttpResponse(); |
367 | $request = new HttpRequest(new HttpUri('')); |
368 | |
369 | $request->header->account = 1; |
370 | $request->setData('title', $l11n); |
371 | $request->setData('language', $language); |
372 | $request->setData('type', $billType['id']); |
373 | |
374 | $module->apiBillTypeL11nCreate($request, $response); |
375 | } |
376 | } |
377 | |
378 | return $billTypes; |
379 | } |
380 | } |