Compare commits
2 Commits
0bbaa78d0e
...
b8bd3f288b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8bd3f288b | ||
|
|
6f1120c8b4 |
10
.idea/freelance_invoice.iml
generated
10
.idea/freelance_invoice.iml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@@ -1,6 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
7
.idea/misc.xml
generated
7
.idea/misc.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.10 (freelance_invoice)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (freelance_invoice)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/freelance_invoice.iml" filepath="$PROJECT_DIR$/.idea/freelance_invoice.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
132
.idea/workspace.xml
generated
132
.idea/workspace.xml
generated
@@ -1,132 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AutoImportSettings">
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="7672063a-a324-4a9c-a8d3-c38955c8d763" name="Changes" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/freelance_invoice.iml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/setup.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/invoice_generator/__init__.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/invoice_generator/html_generator.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main.py" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/test_data/RG004711.yaml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/test_data/envelope.yaml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/test_data/templates/invoice.html" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ChangesViewManager">
|
||||
<option name="groupingKeys">
|
||||
<option value="directory" />
|
||||
</option>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Python Script" />
|
||||
<option value="HTML File" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="MarkdownSettingsMigration">
|
||||
<option name="stateVersion" value="1" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 1
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="2c21ZczAqxeYNrytEGCIucesn9A" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"DefaultHtmlFileTemplate": "HTML File",
|
||||
"Python.main.executor": "Run",
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"git-widget-placeholder": "master",
|
||||
"last_opened_file_path": "/home/torsten/PycharmProjects/freelance_invoice/test_data",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/test_data" />
|
||||
</key>
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$/src" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="main" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
||||
<module name="freelance_invoice" />
|
||||
<option name="ENV_FILES" value="" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/src/main.py" />
|
||||
<option name="PARAMETERS" value="--invoice RG004711 --base test_data/ --template ./test_data/templates/" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-python-sdk-5a2391486177-2887949eec09-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-233.13763.11" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="7672063a-a324-4a9c-a8d3-c38955c8d763" name="Changes" comment="" />
|
||||
<created>1707294915620</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1707294915620</updated>
|
||||
<workItem from="1707294917219" duration="20842000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||
<SUITE FILE_PATH="coverage/freelance_invoice$main.coverage" NAME="main Coverage Results" MODIFIED="1707321806053" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -32,8 +32,7 @@ class HtmlTemplate:
|
||||
|
||||
@staticmethod
|
||||
def calculate_total(invoice_data):
|
||||
return sum(
|
||||
(pos['Quantity'] * (pos['PricePerUnit'] or invoice_data.PricePerUnit)) for pos in invoice_data.Positions)
|
||||
return sum((pos['Quantity'] * pos['PricePerUnit']) for pos in invoice_data.Positions)
|
||||
|
||||
@staticmethod
|
||||
def named_replace(value, **replacements):
|
||||
|
||||
20
src/main.py
20
src/main.py
@@ -86,13 +86,16 @@ def main():
|
||||
|
||||
print('Envelope data:')
|
||||
envelope_data = DataObject(**envelope)
|
||||
print(envelope_data.__dict__)
|
||||
print('<--->')
|
||||
print(yaml.dump(envelope_data))
|
||||
print('</--->')
|
||||
|
||||
print('Invoice data:')
|
||||
invoice_data = DataObject(**invoice)
|
||||
merge_envelope_data_into_invoice_data(invoice_data, envelope_data.Invoice)
|
||||
|
||||
selected_customer = next((x for x in envelope_data.Customers if x['CustomerId'] == invoice_data.CustomerId), None)
|
||||
selected_customer = next((x for x in envelope_data.Customers if x['CustomerId'] == invoice_data.CustomerId),
|
||||
None)
|
||||
merge_envelope_data_into_invoice_data(invoice_data, selected_customer)
|
||||
|
||||
if not hasattr(invoice_data, 'InvoiceDate'):
|
||||
@@ -103,8 +106,17 @@ def main():
|
||||
if not hasattr(invoice_data, 'Id'):
|
||||
invoice_data.Id = None
|
||||
|
||||
if not hasattr(invoice_data, 'Positions'):
|
||||
invoice_data.Positions = []
|
||||
|
||||
for position in invoice_data.Positions:
|
||||
if 'PricePerUnit' not in position or position['PricePerUnit'] is None:
|
||||
position['PricePerUnit'] = invoice_data.PricePerUnit
|
||||
|
||||
invoice_data.Id = invoice_data.Id or invoice_file.stem
|
||||
print(invoice_data.__dict__)
|
||||
print('<--->')
|
||||
print(yaml.dump(invoice_data))
|
||||
print('</--->')
|
||||
|
||||
except FileNotFoundError as e:
|
||||
print(f'Error: {e}')
|
||||
@@ -119,8 +131,6 @@ def main():
|
||||
generator = html_generator.HtmlTemplate(args.template)
|
||||
template = generator.prepare_template(invoice_data, envelope_data)
|
||||
|
||||
print(template)
|
||||
|
||||
try:
|
||||
print('Generating invoice...')
|
||||
invoice_pdf = Path(invoice_data.Id).with_suffix('.pdf')
|
||||
|
||||
@@ -15,7 +15,6 @@ Positions:
|
||||
|
||||
- Title: "Aschkriechen"
|
||||
SubTitle: "Leistungszeitraum: 10/2022"
|
||||
PricePerUnit: 77.88
|
||||
Quantity: 3
|
||||
|
||||
|
||||
|
||||
@@ -112,6 +112,10 @@
|
||||
border-top: .1pt solid black;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.head_data {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
@@ -136,7 +140,7 @@
|
||||
<body>
|
||||
<!-- Content for Static Frame 'header_frame' -->
|
||||
<div id="address_frame_content">
|
||||
<p class="underline">{{ envelope.AddressContent.AddressBoxSender }}</p>
|
||||
<p class="underline small center">{{ envelope.AddressContent.AddressBoxSender }}</p>
|
||||
<address>
|
||||
{{ invoice.AddressField | markdown_to_html }}
|
||||
</address>
|
||||
@@ -188,20 +192,17 @@
|
||||
{% endfor %}
|
||||
<tr class="summe">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="rechts">Nettosumme:</td>
|
||||
<td colspan="2" class="rechts">Nettosumme:</td>
|
||||
<td class="rechts">{{ format_float(calculate_total(invoice)) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="rechts">USt. ({{ format_float(invoice.Vat) }}%):</td>
|
||||
<td colspan="2" class="rechts">USt. ({{ format_float(invoice.Vat) }}%):</td>
|
||||
<td class="rechts">{{ format_float(calculate_total(invoice) * ((invoice.Vat / 100))) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="rechts bold overline">Gesamt Summe:</td>
|
||||
<td colspan="2" class="rechts bold overline">Gesamt Summe:</td>
|
||||
<td class="rechts bold overline">{{ format_float(calculate_total(invoice) * ((invoice.Vat / 100)+1)) }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Reference in New Issue
Block a user