devZenaight commited on
Commit
d5e836f
·
1 Parent(s): d734bf7

SOC is now in same state as HF Planify

Browse files
.gitignore ADDED
@@ -0,0 +1,345 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.pyo
6
+ *.pyd
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ share/python-wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+ MANIFEST
30
+
31
+ # PyInstaller
32
+ # Usually these files are written by a python script from a template
33
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
34
+ *.manifest
35
+ *.spec
36
+
37
+ # Installer logs
38
+ pip-log.txt
39
+ pip-delete-this-directory.txt
40
+
41
+ # Unit test / coverage reports
42
+ htmlcov/
43
+ .tox/
44
+ .nox/
45
+ .coverage
46
+ .coverage.*
47
+ .cache
48
+ nosetests.xml
49
+ coverage.xml
50
+ *.cover
51
+ *.py,cover
52
+ .hypothesis/
53
+ .pytest_cache/
54
+ cover/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ .pybuilder/
78
+ target/
79
+
80
+ # Jupyter Notebook
81
+ .ipynb_checkpoints
82
+
83
+ # IPython
84
+ profile_default/
85
+ ipython_config.py
86
+
87
+ # pyenv
88
+ # For a library or package, you might want to ignore these files since the code is
89
+ # intended to run in multiple environments; otherwise, check them in:
90
+ # .python-version
91
+
92
+ # pipenv
93
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
94
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
95
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
96
+ # install all needed dependencies.
97
+ #Pipfile.lock
98
+
99
+ # poetry
100
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
101
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
102
+ # commonly ignored for libraries.
103
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
104
+ #poetry.lock
105
+
106
+ # pdm
107
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
108
+ #pdm.lock
109
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
110
+ # in version control.
111
+ # https://pdm.fming.dev/#use-with-ide
112
+ .pdm.toml
113
+
114
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
115
+ __pypackages__/
116
+
117
+ # Celery stuff
118
+ celerybeat-schedule
119
+ celerybeat.pid
120
+
121
+ # SageMath parsed files
122
+ *.sage.py
123
+
124
+ # Environments
125
+ .env
126
+ .venv
127
+ env/
128
+ venv/
129
+ ENV/
130
+ env.bak/
131
+ venv.bak/
132
+
133
+ # Spyder project settings
134
+ .spyderproject
135
+ .spyproject
136
+
137
+ # Rope project settings
138
+ .ropeproject
139
+
140
+ # mkdocs documentation
141
+ /site
142
+
143
+ # mypy
144
+ .mypy_cache/
145
+ .dmypy.json
146
+ dmypy.json
147
+
148
+ # Pyre type checker
149
+ .pyre/
150
+
151
+ # pytype static type analyzer
152
+ .pytype/
153
+
154
+ # Cython debug symbols
155
+ cython_debug/
156
+
157
+ # PyCharm
158
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
159
+ # be added to the global gitignore or merged into this project gitignore. For a PyCharm
160
+ # project, it is recommended to include the following files:
161
+ # .idea/
162
+ # *.iml
163
+ # *.ipr
164
+ # *.iws
165
+ .idea/
166
+ *.iml
167
+ *.ipr
168
+ *.iws
169
+
170
+ # VS Code
171
+ .vscode/
172
+
173
+ # Node.js (for frontend)
174
+ node_modules/
175
+ npm-debug.log*
176
+ yarn-debug.log*
177
+ yarn-error.log*
178
+ lerna-debug.log*
179
+
180
+ # Runtime data
181
+ pids
182
+ *.pid
183
+ *.seed
184
+ *.pid.lock
185
+
186
+ # Coverage directory used by tools like istanbul
187
+ coverage/
188
+ *.lcov
189
+
190
+ # nyc test coverage
191
+ .nyc_output
192
+
193
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
194
+ .grunt
195
+
196
+ # Bower dependency directory (https://bower.io/)
197
+ bower_components
198
+
199
+ # node-waf configuration
200
+ .lock-wscript
201
+
202
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
203
+ build/Release
204
+
205
+ # Dependency directories
206
+ jspm_packages/
207
+
208
+ # TypeScript v1 declaration files
209
+ typings/
210
+
211
+ # TypeScript cache
212
+ *.tsbuildinfo
213
+
214
+ # Optional npm cache directory
215
+ .npm
216
+
217
+ # Optional eslint cache
218
+ .eslintcache
219
+
220
+ # Optional stylelint cache
221
+ .stylelintcache
222
+
223
+ # Microbundle cache
224
+ .rpt2_cache/
225
+ .rts2_cache_cjs/
226
+ .rts2_cache_es/
227
+ .rts2_cache_umd/
228
+
229
+ # Optional REPL history
230
+ .node_repl_history
231
+
232
+ # Output of 'npm pack'
233
+ *.tgz
234
+
235
+ # Yarn Integrity file
236
+ .yarn-integrity
237
+
238
+ # dotenv environment variable files
239
+ .env.development.local
240
+ .env.test.local
241
+ .env.production.local
242
+ .env.local
243
+
244
+ # parcel-bundler cache (https://parceljs.org/)
245
+ .cache
246
+ .parcel-cache
247
+
248
+ # Next.js build output
249
+ .next
250
+ out
251
+
252
+ # Nuxt.js build / generate output
253
+ .nuxt
254
+ dist
255
+
256
+ # Gatsby files
257
+ .cache/
258
+ # Comment in the public line in if your project uses Gatsby and not Next.js
259
+ # https://nextjs.org/blog/next-9-1#public-directory-support
260
+ # public
261
+
262
+ # vuepress build output
263
+ .vuepress/dist
264
+
265
+ # vuepress v2.x temp and cache directory
266
+ .temp
267
+ .cache
268
+
269
+ # Docusaurus cache and generated files
270
+ .docusaurus
271
+
272
+ # Serverless directories
273
+ .serverless/
274
+
275
+ # FuseBox cache
276
+ .fusebox/
277
+
278
+ # DynamoDB Local files
279
+ .dynamodb/
280
+
281
+ # TernJS port file
282
+ .tern-port
283
+
284
+ # Stores VSCode versions used for testing VSCode extensions
285
+ .vscode-test
286
+
287
+ # yarn v2
288
+ .yarn/cache
289
+ .yarn/unplugged
290
+ .yarn/build-state.yml
291
+ .yarn/install-state.gz
292
+ .pnp.*
293
+
294
+ # OS generated files
295
+ .DS_Store
296
+ .DS_Store?
297
+ ._*
298
+ .Spotlight-V100
299
+ .Trashes
300
+ ehthumbs.db
301
+ Thumbs.db
302
+
303
+ # Temporary files
304
+ *.tmp
305
+ *.temp
306
+ temp_exports/
307
+
308
+ # Logs
309
+ *.log
310
+ logs/
311
+
312
+ # Database files
313
+ *.db
314
+ *.sqlite
315
+ *.sqlite3
316
+
317
+ # Configuration files with sensitive data
318
+ config.ini
319
+ secrets.json
320
+ .env.local
321
+ .env.production
322
+
323
+ # Docker
324
+ .dockerignore
325
+
326
+ # Backup files
327
+ *.bak
328
+ *.backup
329
+ *~
330
+
331
+ # IDE and editor files
332
+ .vscode/
333
+ .idea/
334
+ *.swp
335
+ *.swo
336
+ *~
337
+
338
+ # FastAPI specific
339
+ .pytest_cache/
340
+ .coverage
341
+ htmlcov/
342
+
343
+ # Hugging Face specific
344
+ .cache/
345
+ transformers_cache/
README.md CHANGED
@@ -10,3 +10,223 @@ short_description: Fast API Business Plan Generator
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
13
+
14
+ # Planify - Live PDF Generator
15
+
16
+ A real-time PDF generation system that updates automatically as content changes, providing an interactive experience for business plan creation.
17
+
18
+ ## 🚀 Quick Start
19
+
20
+ ### 1. Install Dependencies
21
+
22
+ ```bash
23
+ pip install -r requirements.txt
24
+ ```
25
+
26
+ ### 2. Set Up Environment Variables
27
+
28
+ Create a `.env` file in the root directory with your API keys:
29
+
30
+ ```env
31
+ OPENAI_API_KEY=your_openai_api_key_here
32
+ SUPABASE_URL=your_supabase_url_here
33
+ SUPABASE_KEY=your_supabase_key_here
34
+ ```
35
+
36
+ ### 3. Start the Server
37
+
38
+ ```bash
39
+ cd app
40
+ python main.py
41
+ ```
42
+
43
+ The server will start on `http://127.0.0.1:8000`
44
+
45
+ ### 4. Open the Live PDF Viewer
46
+
47
+ #### Option A: Use the HTML Example (Recommended)
48
+ 1. Open `live_pdf_example.html` in your web browser
49
+ 2. Click "Start Live Session" to begin
50
+ 3. Type in the content editor and watch the PDF update in real-time
51
+
52
+ #### Option B: Use the API Directly
53
+ The live PDF viewer exposes these endpoints:
54
+
55
+ - `POST /live-pdf/start` - Start a new live session
56
+ - `POST /live-pdf/update/{session_id}` - Update content
57
+ - `GET /live-pdf/stream/{session_id}` - Stream PDF updates
58
+ - `DELETE /live-pdf/close/{session_id}` - Close session
59
+
60
+ ## 🎯 Features
61
+
62
+ - **Real-time Updates**: PDFs update automatically as you type
63
+ - **Server-Sent Events (SSE)**: Efficient streaming updates without polling
64
+ - **Session Management**: Multiple concurrent live sessions supported
65
+ - **Auto-save**: Content changes trigger automatic PDF regeneration
66
+ - **Download Support**: Download the latest PDF version at any time
67
+ - **Error Handling**: Graceful error handling and recovery
68
+
69
+ ## 📋 How to Use
70
+
71
+ ### Using the HTML Interface
72
+
73
+ 1. **Start the Server**
74
+ ```bash
75
+ cd app
76
+ python main.py
77
+ ```
78
+
79
+ 2. **Open the HTML File**
80
+ - Navigate to the project root directory
81
+ - Double-click `live_pdf_example.html` or open it in your browser
82
+ - Or open: `file:///path/to/your/project/live_pdf_example.html`
83
+
84
+ 3. **Start a Live Session**
85
+ - Click the "Start Live Session" button
86
+ - Wait for the "Session started successfully" message
87
+
88
+ 4. **Edit Content**
89
+ - Type your business plan content in the text area
90
+ - The PDF will update automatically as you type
91
+ - Use Markdown formatting for better structure
92
+
93
+ 5. **Download PDF**
94
+ - Click "Download PDF" to save the current version
95
+ - The PDF will contain your latest changes
96
+
97
+ 6. **Stop Session**
98
+ - Click "Stop Session" when you're done
99
+ - This will clean up the server resources
100
+
101
+ ### Using the API Directly
102
+
103
+ #### Start a Live Session
104
+ ```bash
105
+ curl -X POST http://127.0.0.1:8000/live-pdf/start \
106
+ -H "Content-Type: application/json" \
107
+ -d '{
108
+ "businessPlanId": "test-plan-123",
109
+ "format": "pdf",
110
+ "sections": [
111
+ {
112
+ "key": "prompt_ExecutiveSummary",
113
+ "title": "Executive Summary",
114
+ "content": "# Executive Summary\n\nYour content here..."
115
+ }
116
+ ],
117
+ "chartImages": []
118
+ }'
119
+ ```
120
+
121
+ #### Stream PDF Updates
122
+ ```bash
123
+ curl -N http://127.0.0.1:8000/live-pdf/stream/{session_id}
124
+ ```
125
+
126
+ #### Update Content
127
+ ```bash
128
+ curl -X POST http://127.0.0.1:8000/live-pdf/update/{session_id} \
129
+ -H "Content-Type: application/json" \
130
+ -d '{
131
+ "businessPlanId": "test-plan-123",
132
+ "format": "pdf",
133
+ "sections": [
134
+ {
135
+ "key": "prompt_ExecutiveSummary",
136
+ "title": "Executive Summary",
137
+ "content": "# Updated Content\n\nNew content here..."
138
+ }
139
+ ],
140
+ "chartImages": []
141
+ }'
142
+ ```
143
+
144
+ ## 🔧 Configuration
145
+
146
+ ### Environment Variables
147
+
148
+ | Variable | Description | Required |
149
+ |----------|-------------|----------|
150
+ | `OPENAI_API_KEY` | Your OpenAI API key | Yes |
151
+ | `SUPABASE_URL` | Your Supabase project URL | Yes |
152
+ | `SUPABASE_KEY` | Your Supabase API key | Yes |
153
+
154
+ ### Server Configuration
155
+
156
+ The server runs on `http://127.0.0.1:8000` by default. You can modify the port in `app/main.py`:
157
+
158
+ ```python
159
+ if __name__ == "__main__":
160
+ import uvicorn
161
+ uvicorn.run(app, host="127.0.0.1", port=8000)
162
+ ```
163
+
164
+ ## 📁 Project Structure
165
+
166
+ ```
167
+ planify/
168
+ ├── app/
169
+ │ ├── main.py # FastAPI server with live PDF endpoints
170
+ │ ├── models.py # Data models
171
+ │ ├── utils.py # Utility functions
172
+ │ ├── constants.py # Constants and configurations
173
+ │ ├── CurrencyMapping/ # Currency mapping functionality
174
+ │ └── DocumentGeneration/ # PDF generation modules
175
+ ├── frontend/ # Frontend components
176
+ ├── live_pdf_example.html # Live PDF viewer interface
177
+ ├── LIVE_PDF_README.md # Detailed API documentation
178
+ ├── requirements.txt # Python dependencies
179
+ └── README.md # This file
180
+ ```
181
+
182
+ ## 🐛 Troubleshooting
183
+
184
+ ### Common Issues
185
+
186
+ 1. **Server won't start**
187
+ - Check if all dependencies are installed: `pip install -r requirements.txt`
188
+ - Verify your `.env` file has the correct API keys
189
+ - Check if port 8000 is available
190
+
191
+ 2. **PDF not updating**
192
+ - Ensure the server is running
193
+ - Check browser console for errors
194
+ - Verify the session ID is correct
195
+
196
+ 3. **Connection errors**
197
+ - Make sure the server URL in the HTML file matches your server
198
+ - Check CORS settings if accessing from a different domain
199
+
200
+ ### Debug Mode
201
+
202
+ To run the server in debug mode:
203
+
204
+ ```bash
205
+ cd app
206
+ python main.py --debug
207
+ ```
208
+
209
+ ## 📚 API Documentation
210
+
211
+ For detailed API documentation, see `LIVE_PDF_README.md`.
212
+
213
+ ## 🤝 Contributing
214
+
215
+ 1. Fork the repository
216
+ 2. Create a feature branch
217
+ 3. Make your changes
218
+ 4. Test thoroughly
219
+ 5. Submit a pull request
220
+
221
+ ## 📄 License
222
+
223
+ This project is licensed under the MIT License.
224
+
225
+ ## 🆘 Support
226
+
227
+ If you encounter any issues:
228
+
229
+ 1. Check the troubleshooting section above
230
+ 2. Review the API documentation in `LIVE_PDF_README.md`
231
+ 3. Check the server logs for error messages
232
+ 4. Open an issue on GitHub with detailed error information
app/DocumentGeneration/__init__.py CHANGED
@@ -17,7 +17,6 @@ from document_helpers import (
17
  extract_business_name_from_content,
18
  filter_empty_sections,
19
  extract_subheadings,
20
- enhance_subheadings_with_bold,
21
  remove_duplicate_headings
22
  )
23
  from grouped import (
@@ -33,10 +32,6 @@ from markdown_renderer import (
33
  render_markdown_to_docx_grouped,
34
  clean_text_for_docx
35
  )
36
- from mixed import (
37
- make_sentences_ending_with_colon_bold,
38
- process_bold_text_for_docx
39
- )
40
 
41
  __all__ = [
42
  'create_pdf_document',
@@ -51,14 +46,11 @@ __all__ = [
51
  'parse_content_into_groups',
52
  'extract_key_phrases',
53
  'get_content_groups_info',
54
- 'enhance_subheadings_with_bold',
55
  'remove_duplicate_headings',
56
  'clean_text_for_pdf',
57
  'render_markdown_to_pdf',
58
  'render_markdown_to_pdf_grouped',
59
  'render_markdown_to_docx',
60
  'render_markdown_to_docx_grouped',
61
- 'process_bold_text_for_docx',
62
- 'clean_text_for_docx',
63
- 'make_sentences_ending_with_colon_bold'
64
  ]
 
17
  extract_business_name_from_content,
18
  filter_empty_sections,
19
  extract_subheadings,
 
20
  remove_duplicate_headings
21
  )
22
  from grouped import (
 
32
  render_markdown_to_docx_grouped,
33
  clean_text_for_docx
34
  )
 
 
 
 
35
 
36
  __all__ = [
37
  'create_pdf_document',
 
46
  'parse_content_into_groups',
47
  'extract_key_phrases',
48
  'get_content_groups_info',
 
49
  'remove_duplicate_headings',
50
  'clean_text_for_pdf',
51
  'render_markdown_to_pdf',
52
  'render_markdown_to_pdf_grouped',
53
  'render_markdown_to_docx',
54
  'render_markdown_to_docx_grouped',
55
+ 'clean_text_for_docx'
 
 
56
  ]
app/DocumentGeneration/chart_generator.py CHANGED
@@ -11,7 +11,7 @@ from typing import List, Dict, Any, Optional
11
 
12
  # Add the parent directory to sys.path to import from models.py
13
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
14
- from app.models import ExportSection
15
 
16
  def parse_embedded_chart_data(sections: List[ExportSection]) -> List[Dict[str, Any]]:
17
  """Parse chart data embedded in section content using CHARTDATA markers"""
 
11
 
12
  # Add the parent directory to sys.path to import from models.py
13
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
14
+ from models import ExportSection
15
 
16
  def parse_embedded_chart_data(sections: List[ExportSection]) -> List[Dict[str, Any]]:
17
  """Parse chart data embedded in section content using CHARTDATA markers"""
app/DocumentGeneration/document_helpers.py CHANGED
@@ -8,7 +8,7 @@ from typing import List, Dict, Any
8
 
9
  # Add the parent directory to sys.path to import from models.py
10
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
11
- from app.models import ExportSection
12
 
13
  def extract_business_name_from_content(sections: List[ExportSection]) -> str:
14
  """Extract business name from markdown content"""
@@ -97,43 +97,6 @@ def filter_empty_sections(sections: List[ExportSection]) -> List[ExportSection]:
97
  return filtered_sections
98
 
99
 
100
- def enhance_subheadings_with_bold(content: str) -> str:
101
- """Enhance subheadings with bold formatting and ensure no duplicates"""
102
- if not content:
103
- return content
104
-
105
- lines = content.split('\n')
106
- enhanced_lines = []
107
- seen_headings = set()
108
-
109
- for line in lines:
110
- line = line.strip()
111
- if not line:
112
- enhanced_lines.append('')
113
- continue
114
-
115
- # Check if this is a subheading (## or ###)
116
- if line.startswith('##') and not line.startswith('###'):
117
- # Extract the heading text
118
- heading_text = re.sub(r'^##+\s*', '', line)
119
- # heading_text = re.sub(r'[*_`~]', '', heading_text).strip() # Commented out to preserve ** symbols
120
- heading_text = heading_text.strip()
121
-
122
- # Check for duplicates
123
- if heading_text.lower() in seen_headings:
124
- continue
125
-
126
- seen_headings.add(heading_text.lower())
127
-
128
- # Make it bold and ensure proper formatting
129
- enhanced_line = f"**{heading_text}**"
130
- enhanced_lines.append(enhanced_line)
131
- else:
132
- enhanced_lines.append(line)
133
-
134
- return '\n'.join(enhanced_lines)
135
-
136
-
137
  def remove_duplicate_headings(content: str) -> str:
138
  """Remove duplicate headings from content"""
139
  if not content:
 
8
 
9
  # Add the parent directory to sys.path to import from models.py
10
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
11
+ from models import ExportSection
12
 
13
  def extract_business_name_from_content(sections: List[ExportSection]) -> str:
14
  """Extract business name from markdown content"""
 
97
  return filtered_sections
98
 
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  def remove_duplicate_headings(content: str) -> str:
101
  """Remove duplicate headings from content"""
102
  if not content:
app/DocumentGeneration/live_pdf_generator.py CHANGED
@@ -13,7 +13,7 @@ import sys
13
  import os
14
  sys.path.append(os.path.dirname(__file__))
15
  from pdf_generator import create_pdf_document
16
- from app.models import ExportRequest
17
 
18
  class LivePDFGenerator:
19
  """Generates and streams PDF updates in real-time"""
 
13
  import os
14
  sys.path.append(os.path.dirname(__file__))
15
  from pdf_generator import create_pdf_document
16
+ from models import ExportRequest
17
 
18
  class LivePDFGenerator:
19
  """Generates and streams PDF updates in real-time"""
app/DocumentGeneration/markdown_renderer.py CHANGED
@@ -9,7 +9,6 @@ from typing import List, Dict, Any, Optional
9
 
10
  # Import from the same directory (Document Generation)
11
  from grouped import parse_content_into_groups, should_break_page_for_group
12
- from mixed import _render_mixed_text_to_pdf, process_bold_text_for_docx
13
 
14
  def clean_markdown_text(text: str) -> str:
15
  """Clean markdown formatting for PDF generation - PRESERVE HEADINGS"""
@@ -346,17 +345,21 @@ def render_markdown_to_pdf_grouped(pdf, content: str, primary_color, accent_colo
346
 
347
  if not re.match(r'^\d+\.', text) and len(text) < 80:
348
  # Main heading style
 
 
349
  pdf.set_xy(25, current_y)
350
- _render_mixed_text_to_pdf(pdf, text, 25, current_y, line_height_heading, primary_color, bold_font_size=12, normal_font_size=12)
351
- current_y += line_height_heading
352
  pdf.set_xy(25, current_y)
353
  pdf.ln(6)
354
  current_y = pdf.get_y()
355
  else:
356
  # Regular bold text
 
 
357
  pdf.set_xy(25, current_y)
358
- _render_mixed_text_to_pdf(pdf, text, 25, current_y, line_height_text, text_color, bold_font_size=12, normal_font_size=12)
359
- current_y += line_height_text
360
  pdf.set_xy(25, current_y)
361
  current_y = pdf.get_y()
362
 
@@ -467,10 +470,12 @@ def render_markdown_to_docx_grouped(doc, content: str):
467
  doc.add_heading(text, level=4)
468
  elif subheading_type == 'bold':
469
  if not re.match(r'^\d+\.', text) and len(text) < 80:
470
- paragraph = process_bold_text_for_docx(text, doc)
 
471
  paragraph.style = doc.styles['Heading 1'] # Apply heading style
472
  else:
473
- process_bold_text_for_docx(text, doc) # Use helper for regular paragraphs
 
474
  elif subheading_type == 'numbered':
475
  doc.add_heading(text, level=2)
476
 
 
9
 
10
  # Import from the same directory (Document Generation)
11
  from grouped import parse_content_into_groups, should_break_page_for_group
 
12
 
13
  def clean_markdown_text(text: str) -> str:
14
  """Clean markdown formatting for PDF generation - PRESERVE HEADINGS"""
 
345
 
346
  if not re.match(r'^\d+\.', text) and len(text) < 80:
347
  # Main heading style
348
+ pdf.set_font("Arial", "B", 12) # Bold, size 12
349
+ pdf.set_text_color(*primary_color) # Black
350
  pdf.set_xy(25, current_y)
351
+ pdf.multi_cell(160, 8, text) # Multi-cell for text
352
+ current_y += 8 # Move down for next line
353
  pdf.set_xy(25, current_y)
354
  pdf.ln(6)
355
  current_y = pdf.get_y()
356
  else:
357
  # Regular bold text
358
+ pdf.set_font("Arial", "B", 12) # Bold, size 12
359
+ pdf.set_text_color(*text_color) # Dark gray
360
  pdf.set_xy(25, current_y)
361
+ pdf.multi_cell(160, 8, text) # Multi-cell for text
362
+ current_y += 8 # Move down for next line
363
  pdf.set_xy(25, current_y)
364
  current_y = pdf.get_y()
365
 
 
470
  doc.add_heading(text, level=4)
471
  elif subheading_type == 'bold':
472
  if not re.match(r'^\d+\.', text) and len(text) < 80:
473
+ # Simple paragraph with bold text
474
+ paragraph = doc.add_paragraph(text)
475
  paragraph.style = doc.styles['Heading 1'] # Apply heading style
476
  else:
477
+ # Regular paragraph
478
+ doc.add_paragraph(text)
479
  elif subheading_type == 'numbered':
480
  doc.add_heading(text, level=2)
481
 
app/DocumentGeneration/mixed.py CHANGED
@@ -1,91 +1,6 @@
1
- import re
2
-
3
- def make_sentences_ending_with_colon_bold(content: str) -> str:
4
- """
5
- Make text before a colon (:) bold by wrapping it in ** markers.
6
- This handles cases like "Short-Term (next 12 months):" to make only the part before the colon bold.
7
- """
8
- if not content:
9
- return content
10
-
11
- lines = content.split('\n')
12
- processed_lines = []
13
-
14
- for line in lines:
15
- if not line.strip():
16
- processed_lines.append(line)
17
- continue
18
-
19
- last_colon_index = line.rfind(':')
20
-
21
- if last_colon_index != -1:
22
- text_before_colon = line[:last_colon_index].strip()
23
- text_after_colon = line[last_colon_index:].strip()
24
-
25
- if not (text_before_colon.startswith('**') and text_before_colon.endswith('**')):
26
- processed_lines.append(f"**{text_before_colon}**{text_after_colon}")
27
- else:
28
- processed_lines.append(line)
29
- else:
30
- processed_lines.append(line)
31
-
32
- return '\n'.join(processed_lines)
33
-
34
- def _render_mixed_text_to_pdf(pdf, line: str, current_x: float, current_y: float, line_height: float, text_color: tuple, bold_font_size: int = 12, normal_font_size: int = 12):
35
- """Helper to render a line with mixed bold and normal text using pdf.cell"""
36
- parts = re.split(r'(\*\*.*?\*\*)', line)
37
-
38
- for part in parts:
39
- if part.startswith('**') and part.endswith('**'):
40
- bold_text = part[2:-2] # Remove ** markers
41
- pdf.set_font("Arial", "B", bold_font_size)
42
- pdf.set_text_color(*text_color)
43
- pdf.set_xy(current_x, current_y)
44
- text_width = pdf.get_string_width(bold_text)
45
- pdf.cell(text_width, line_height, bold_text)
46
- current_x += text_width
47
- else:
48
- if part:
49
- pdf.set_font("Arial", "", normal_font_size)
50
- pdf.set_text_color(*text_color)
51
- pdf.set_xy(current_x, current_y)
52
- text_width = pdf.get_string_width(part)
53
- pdf.cell(text_width, line_height, part)
54
- current_x += text_width
55
- return current_x
56
-
57
- def clean_bold_text_for_pdf(text: str) -> str:
58
- """Clean bold text for PDF rendering by removing literal asterisks and converting to proper format"""
59
- # Handle cases where asterisks are literal characters instead of markdown
60
- # Convert patterns like "*Business Name:**" to "**Business Name:**"
61
-
62
- # First, handle the specific pattern we're seeing: "*Business Name:**" -> "**Business Name:**"
63
- text = re.sub(r'\*([^*]+)\*\*:', r'**\1**:', text)
64
-
65
- # Handle other similar patterns
66
- text = re.sub(r'\*([^*]+)\*\*', r'**\1**', text)
67
-
68
- # Clean up any remaining single asterisks that shouldn't be there
69
- text = re.sub(r'(?<!\*)\*(?!\*)', '', text) # Remove single asterisks not part of **
70
-
71
- return text
72
-
73
- def process_bold_text_for_docx(text: str, doc):
74
- """Process bold text markers (**text**) in content for Word documents"""
75
- # For Word documents, we can actually render bold text properly
76
- # Split text by ** markers and create runs with appropriate formatting
77
- parts = re.split(r'(\*\*.*?\*\*)', text)
78
- paragraph = doc.add_paragraph()
79
-
80
- for part in parts:
81
- if part.startswith('**') and part.endswith('**'):
82
- # This is bold text
83
- bold_text = part # Keep ** markers
84
- run = paragraph.add_run(bold_text)
85
- run.bold = True
86
- else:
87
- # Regular text
88
- if part: # Only add non-empty parts
89
- paragraph.add_run(part)
90
-
91
- return paragraph
 
1
+ # This file has been removed as all its functions are not present in maintest.txt
2
+ # Functions removed:
3
+ # - make_sentences_ending_with_colon_bold()
4
+ # - _render_mixed_text_to_pdf()
5
+ # - clean_bold_text_for_pdf()
6
+ # - process_bold_text_for_docx()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/DocumentGeneration/pdf_generator.py CHANGED
@@ -10,7 +10,7 @@ from typing import List, Dict, Any
10
 
11
  # Add the parent directory to sys.path to import from models.py
12
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
13
- from app.models import ExportRequest
14
 
15
  # Import from the same directory (Document Generation)
16
  from document_helpers import (
@@ -24,16 +24,15 @@ from markdown_renderer import (
24
  clean_text_for_pdf,
25
  render_markdown_to_pdf_grouped
26
  )
27
- from mixed import make_sentences_ending_with_colon_bold
28
 
29
  # Add Currency Mapping path
30
  currency_mapping_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Currency Mapping')
31
  if currency_mapping_path not in sys.path:
32
  sys.path.append(currency_mapping_path)
33
- from app.CurrencyMapping.currency_mapping import convert_currency_symbols_to_iso
34
 
35
  # Import sort_sections_by_order from utils module
36
- from app.utils import sort_sections_by_order
37
 
38
  def create_pdf_document(request: ExportRequest):
39
  """Create a PROFESSIONAL PDF document from the business plan data using FPDF2
@@ -301,9 +300,6 @@ def create_pdf_document(request: ExportRequest):
301
  # content_text = enhance_subheadings_with_bold(content_text)
302
  content_text = remove_duplicate_headings(content_text)
303
 
304
- # Make text before colons bold
305
- content_text = make_sentences_ending_with_colon_bold(content_text)
306
-
307
  # Add content with proper markdown rendering using grouped approach
308
  if content_text and content_text.strip():
309
  render_markdown_to_pdf_grouped(pdf, content_text, primary_color, accent_color, text_color)
 
10
 
11
  # Add the parent directory to sys.path to import from models.py
12
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
13
+ from models import ExportRequest
14
 
15
  # Import from the same directory (Document Generation)
16
  from document_helpers import (
 
24
  clean_text_for_pdf,
25
  render_markdown_to_pdf_grouped
26
  )
 
27
 
28
  # Add Currency Mapping path
29
  currency_mapping_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Currency Mapping')
30
  if currency_mapping_path not in sys.path:
31
  sys.path.append(currency_mapping_path)
32
+ from CurrencyMapping.currency_mapping import convert_currency_symbols_to_iso
33
 
34
  # Import sort_sections_by_order from utils module
35
+ from utils import sort_sections_by_order
36
 
37
  def create_pdf_document(request: ExportRequest):
38
  """Create a PROFESSIONAL PDF document from the business plan data using FPDF2
 
300
  # content_text = enhance_subheadings_with_bold(content_text)
301
  content_text = remove_duplicate_headings(content_text)
302
 
 
 
 
303
  # Add content with proper markdown rendering using grouped approach
304
  if content_text and content_text.strip():
305
  render_markdown_to_pdf_grouped(pdf, content_text, primary_color, accent_color, text_color)
app/DocumentGeneration/table_of_content.py CHANGED
@@ -8,8 +8,8 @@ from typing import List, Dict, Any
8
 
9
  # Add the parent directory to sys.path to import from models.py and constants.py
10
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
11
- from app.models import ExportSection
12
- from app.constants import SECTION_ORDER
13
 
14
  def generate_table_of_contents(sections: List[ExportSection], business_idea: str) -> List[Dict[str, Any]]:
15
  """Generate a structured table of contents with page numbers following SECTION_ORDER"""
 
8
 
9
  # Add the parent directory to sys.path to import from models.py and constants.py
10
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
11
+ from models import ExportSection
12
+ from constants import SECTION_ORDER
13
 
14
  def generate_table_of_contents(sections: List[ExportSection], business_idea: str) -> List[Dict[str, Any]]:
15
  """Generate a structured table of contents with page numbers following SECTION_ORDER"""
app/DocumentGeneration/word_generator.py CHANGED
@@ -11,23 +11,22 @@ from typing import List, Dict, Any
11
 
12
  # Add the parent directory to sys.path to import from models.py
13
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
14
- from app.models import ExportRequest
15
 
16
  # Import from the same directory (Document Generation)
17
  from document_helpers import (
18
  filter_empty_sections,
19
  extract_business_name_from_content
20
  )
21
- from table_of_content import generate_table_of_contents
22
  from chart_generator import parse_embedded_chart_data, create_chart_from_data
23
  from markdown_renderer import (
24
  render_markdown_to_docx_grouped
25
  )
26
- from mixed import process_bold_text_for_docx
27
 
28
  # Add Currency Mapping path
29
  sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Currency Mapping'))
30
- from currency_mapping import convert_currency_symbols_to_iso
31
 
32
  def create_word_document(request: ExportRequest):
33
  """Create a Word document from the business plan data with front page, TOC, and proper page breaks"""
@@ -245,9 +244,6 @@ def create_word_document(request: ExportRequest):
245
  filtered_lines.append(line)
246
  clean_content = '\n'.join(filtered_lines)
247
 
248
- # Make text before colons bold
249
- clean_content = make_sentences_ending_with_colon_bold(clean_content)
250
-
251
  # Render markdown content with proper heading styling using grouped approach
252
  render_markdown_to_docx_grouped(doc, clean_content)
253
 
 
11
 
12
  # Add the parent directory to sys.path to import from models.py
13
  sys.path.append(os.path.dirname(os.path.dirname(__file__)))
14
+ from models import ExportRequest
15
 
16
  # Import from the same directory (Document Generation)
17
  from document_helpers import (
18
  filter_empty_sections,
19
  extract_business_name_from_content
20
  )
21
+ from DocumentGeneration.table_of_content import generate_table_of_contents
22
  from chart_generator import parse_embedded_chart_data, create_chart_from_data
23
  from markdown_renderer import (
24
  render_markdown_to_docx_grouped
25
  )
 
26
 
27
  # Add Currency Mapping path
28
  sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Currency Mapping'))
29
+ from CurrencyMapping.currency_mapping import convert_currency_symbols_to_iso
30
 
31
  def create_word_document(request: ExportRequest):
32
  """Create a Word document from the business plan data with front page, TOC, and proper page breaks"""
 
244
  filtered_lines.append(line)
245
  clean_content = '\n'.join(filtered_lines)
246
 
 
 
 
247
  # Render markdown content with proper heading styling using grouped approach
248
  render_markdown_to_docx_grouped(doc, clean_content)
249
 
app/__init__.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # App Package
2
+ # This file makes the app directory a proper Python package
3
+
4
+ import os
5
+ import sys
6
+
7
+ # Add the current directory to sys.path
8
+ current_dir = os.path.dirname(__file__)
9
+ if current_dir not in sys.path:
10
+ sys.path.insert(0, current_dir)
11
+
12
+ # Import main modules for easy access
13
+ from models import ExportRequest, ExportSection, ExportResponse, SectionJob, BatchGenerateRequest, GenerateRequest, CreatePlanRequest
14
+ from constants import SECTION_ORDER, SECTION_MAP, SECTION_COLUMNS
15
+ from utils import sort_sections_by_order
16
+
17
+ __all__ = [
18
+ 'ExportRequest',
19
+ 'ExportSection',
20
+ 'ExportResponse',
21
+ 'SectionJob',
22
+ 'BatchGenerateRequest',
23
+ 'GenerateRequest',
24
+ 'CreatePlanRequest',
25
+ 'SECTION_ORDER',
26
+ 'SECTION_MAP',
27
+ 'SECTION_COLUMNS',
28
+ 'sort_sections_by_order'
29
+ ]
app/__pycache__/constants.cpython-311.pyc DELETED
Binary file (1.41 kB)
 
app/__pycache__/main.cpython-311.pyc DELETED
Binary file (80.7 kB)
 
app/__pycache__/models.cpython-311.pyc DELETED
Binary file (3.98 kB)
 
app/__pycache__/utils.cpython-311.pyc DELETED
Binary file (2.42 kB)
 
app/main.py CHANGED
@@ -94,40 +94,39 @@ import sys
94
  import os
95
 
96
  # Add the Document Generation and Currency Mapping paths to sys.path
97
- sys.path.append(os.path.join(os.path.dirname(__file__), 'Document Generation'))
98
- sys.path.append(os.path.join(os.path.dirname(__file__), 'Currency Mapping'))
99
 
100
  # Import models
101
- from app.models import ExportRequest, ExportSection, ExportResponse, SectionJob, BatchGenerateRequest, GenerateRequest, CreatePlanRequest
102
 
103
  # Import constants
104
- from app.constants import SECTION_ORDER, SECTION_MAP, SECTION_COLUMNS
105
 
106
  # Import utilities
107
- from app.utils import sort_sections_by_order
108
 
109
  # Now import the modules
110
  import sys
111
  import os
112
 
113
  # Add the Document Generation and Currency Mapping paths to sys.path
114
- sys.path.append(os.path.join(os.path.dirname(__file__), 'Document Generation'))
115
- sys.path.append(os.path.join(os.path.dirname(__file__), 'Currency Mapping'))
116
-
117
- from app.DocumentGeneration.pdf_generator import create_pdf_document
118
- from app.DocumentGeneration.word_generator import create_word_document
119
- from app.DocumentGeneration.live_pdf_generator import live_pdf_generator
120
- from app.DocumentGeneration.chart_generator import parse_embedded_chart_data, create_chart_from_data
121
- from app.DocumentGeneration.table_of_content import generate_table_of_contents, add_table_of_contents_page
122
- from app.DocumentGeneration.document_helpers import (
123
  extract_business_name_from_content,
124
  filter_empty_sections,
125
  extract_subheadings,
126
- enhance_subheadings_with_bold,
127
  remove_duplicate_headings
128
  )
129
- from app.DocumentGeneration.grouped import parse_content_into_groups, extract_key_phrases, get_content_groups_info
130
- from app.DocumentGeneration.markdown_renderer import (
131
  clean_text_for_pdf,
132
  render_markdown_to_pdf,
133
  render_markdown_to_pdf_grouped,
@@ -135,8 +134,7 @@ from app.DocumentGeneration.markdown_renderer import (
135
  render_markdown_to_docx_grouped,
136
  clean_text_for_docx
137
  )
138
- from app.DocumentGeneration.mixed import make_sentences_ending_with_colon_bold, process_bold_text_for_docx
139
- from app.CurrencyMapping.currency_mapping import convert_currency_symbols_to_iso
140
 
141
  # ──────────────────────────────────────────────────────────────────────────────
142
  # Logging
 
94
  import os
95
 
96
  # Add the Document Generation and Currency Mapping paths to sys.path
97
+ sys.path.append(os.path.join(os.path.dirname(__file__), 'DocumentGeneration'))
98
+ sys.path.append(os.path.join(os.path.dirname(__file__), 'CurrencyMapping'))
99
 
100
  # Import models
101
+ from models import ExportRequest, ExportSection, ExportResponse, SectionJob, BatchGenerateRequest, GenerateRequest, CreatePlanRequest
102
 
103
  # Import constants
104
+ from constants import SECTION_ORDER, SECTION_MAP, SECTION_COLUMNS
105
 
106
  # Import utilities
107
+ from utils import sort_sections_by_order
108
 
109
  # Now import the modules
110
  import sys
111
  import os
112
 
113
  # Add the Document Generation and Currency Mapping paths to sys.path
114
+ sys.path.append(os.path.join(os.path.dirname(__file__), 'DocumentGeneration'))
115
+ sys.path.append(os.path.join(os.path.dirname(__file__), 'CurrencyMapping'))
116
+
117
+ from DocumentGeneration.pdf_generator import create_pdf_document
118
+ from DocumentGeneration.word_generator import create_word_document
119
+ from DocumentGeneration.live_pdf_generator import live_pdf_generator
120
+ from DocumentGeneration.chart_generator import parse_embedded_chart_data, create_chart_from_data
121
+ from DocumentGeneration.table_of_content import generate_table_of_contents, add_table_of_contents_page
122
+ from DocumentGeneration.document_helpers import (
123
  extract_business_name_from_content,
124
  filter_empty_sections,
125
  extract_subheadings,
 
126
  remove_duplicate_headings
127
  )
128
+ from DocumentGeneration.grouped import parse_content_into_groups, extract_key_phrases, get_content_groups_info
129
+ from DocumentGeneration.markdown_renderer import (
130
  clean_text_for_pdf,
131
  render_markdown_to_pdf,
132
  render_markdown_to_pdf_grouped,
 
134
  render_markdown_to_docx_grouped,
135
  clean_text_for_docx
136
  )
137
+ from CurrencyMapping.currency_mapping import convert_currency_symbols_to_iso
 
138
 
139
  # ──────────────────────────────────────────────────────────────────────────────
140
  # Logging
app/utils.py CHANGED
@@ -2,8 +2,8 @@
2
  # This file helps break circular imports between main.py and pdf_generator.py
3
 
4
  from typing import List
5
- from app.models import ExportSection
6
- from app.constants import SECTION_ORDER
7
 
8
  def sort_sections_by_order(sections: List[ExportSection]) -> List[ExportSection]:
9
  """Sort sections according to the predefined SECTION_ORDER to ensure correct numerical ordering"""
 
2
  # This file helps break circular imports between main.py and pdf_generator.py
3
 
4
  from typing import List
5
+ from models import ExportSection
6
+ from constants import SECTION_ORDER
7
 
8
  def sort_sections_by_order(sections: List[ExportSection]) -> List[ExportSection]:
9
  """Sort sections according to the predefined SECTION_ORDER to ensure correct numerical ordering"""
bp _template.txt ADDED
@@ -0,0 +1,293 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Executive Summary
2
+
3
+ ### 1.1 Business Name, Tagline & Logo Reference
4
+ - **Business Name:** Desert Innovate
5
+ - **Tagline:** Empowering UAE Growth Through Innovation
6
+ - **Logo Concept:** A sleek, modern falcon silhouette in gold and deep green, symbolizing strength and prosperity, set against a minimalist desert dune backdrop to reflect the UAE’s heritage and forward-looking vision.
7
+
8
+ ### 1.2 Business Concept Overview
9
+ Desert Innovate provides tailored business solutions and training workshops designed for startups and SMEs across the United Arab Emirates. Our core offering includes interactive demonstrations and hands-on workshops that help local entrepreneurs and businesses adopt innovative tools and strategies to enhance their competitiveness in the dynamic UAE market. We focus on practical, culturally relevant approaches that align with the country’s rapid economic diversification and digital transformation goals.
10
+
11
+ ### 1.3 Problem Statement
12
+ Many UAE businesses face challenges in adopting the latest technologies and innovative business practices due to a lack of accessible, culturally relevant training and demonstration opportunities. Existing solutions are often generic or imported without adaptation, leaving a gap in effective knowledge transfer and practical application tailored to the unique UAE business environment.
13
+
14
+ ### 1.4 Solution Summary
15
+ Desert Innovate addresses these challenges by offering free, engaging workshops and demonstrations that are customized to the needs and cultural context of UAE businesses.
16
+ - Hands-on learning experiences that build confidence and competence
17
+ - Culturally aligned content that resonates with local business practices
18
+ - Direct engagement to foster lasting partnerships and customer loyalty
19
+
20
+ ### 1.5 Vision and Mission Statement
21
+ **Vision:** To be the leading catalyst for innovation-driven business growth across the UAE, empowering enterprises to thrive in a competitive global economy.
22
+ **Mission:** Desert Innovate is committed to providing accessible and culturally tailored innovation workshops and solutions that enable UAE businesses to harness new technologies and strategies, supporting the nation’s vision for economic diversification and sustainable development.
23
+
24
+ ### 1.6 Financial Snapshot and Funding Requirement
25
+ Projected revenues are expected to range between د.إ 500,000 and د.إ 750,000 in the first year, driven primarily by workshop fees and consulting engagements. Major cost drivers include marketing, content development, and facilitator salaries, with an anticipated profit margin of approximately 25% as operational efficiencies improve.
26
+ We seek د.إ 200,000 in funding to accelerate development, expand marketing efforts, and scale workshop delivery across key UAE cities. The investment will be strategically allocated to customer acquisition, content localization, and technology infrastructure.
27
+
28
+ ### 1.7 Key Milestones and Traction to Date
29
+ - Developed initial workshop curriculum tailored for UAE SMEs (Q1 2024)
30
+ - Conducted pilot workshops with 50+ participants, receiving positive feedback (Q2 2024)
31
+ - Established partnerships with two local business councils for outreach support (Q2 2024)
32
+ - Secured د.إ 50,000 in initial seed funding from angel investors (Q2 2024)
33
+
34
+ ## Company Profile
35
+
36
+ ### 2.1 Company Overview (Founding, Location)
37
+ The company is planned to be founded in the second quarter of 2024 by a team of experienced professionals specialized in marketing and customer engagement. The founding team includes a marketing strategist, a business development manager, and a technical consultant. The headquarters will be located in Dubai, United Arab Emirates, chosen for its status as a leading business hub with excellent connectivity, infrastructure, and access to a diverse customer base across the Middle East.
38
+
39
+ ### 2.2 Legal Structure and Ownership
40
+ The company will be registered as a Limited Liability Company (LLC) under UAE law, providing flexibility and protection to its owners. Ownership is divided among three principal shareholders: the marketing strategist holding 40%, the business development manager with 35%, and the technical consultant owning 25%. This structure allows for clear roles in operations and decision-making.
41
+
42
+ ### 2.3 Business Objectives (Short-Term and Long-Term)
43
+ **Short-Term (next 12 months):**
44
+ - Acquire 500 paying customers through targeted marketing and free workshops.
45
+ - Generate د.إ 200,000 in revenue by the end of the first operational year.
46
+ - Conduct at least 20 free demonstrations or workshops to build brand awareness and engagement.
47
+
48
+ **Long-Term (2–5 years):**
49
+ - Expand operations to at least two other emirates within the UAE.
50
+ - Achieve profitability with a 25% net margin through scaling and operational efficiency.
51
+ - Establish strategic partnerships with local businesses to enhance service distribution and customer reach.
52
+
53
+ ### 2.4 Company History or Origin Story
54
+ The business idea originated from observing a gap in the local market for effective customer engagement solutions tailored to UAE businesses. The founders recognized that many companies struggled to attract and retain customers despite having quality products and services. Leveraging their combined expertise in marketing and technology, they envisioned a service offering free demonstrations and workshops to bridge this gap and foster stronger client relationships.
55
+
56
+ ### 2.5 Business Type and Operating Model
57
+ This is a B2B service-oriented business focused on providing customer engagement solutions to other companies in the UAE. Revenue is primarily generated through subscription fees and service packages following initial free demonstrations or workshops. The company plans to leverage partnerships with local business councils and chambers of commerce to reach target customers effectively and build credibility within the regional market.
58
+
59
+ ## Market Analysis
60
+
61
+ ### 3.1 Target Market Segmentation
62
+ - **Young Professionals in Urban Areas:** This segment includes individuals aged 25-40 living primarily in Dubai and Abu Dhabi. They are tech-savvy, career-focused, and seek convenient, innovative solutions to improve their lifestyle. The estimated size is approximately 1.5 million people, representing a significant consumer base with disposable income in the UAE.
63
+ - **Small and Medium Enterprises (SMEs):** SMEs across various sectors such as retail, hospitality, and services form this segment. These businesses typically have 10-50 employees and annual revenues ranging from د.إ 1 million to د.إ 10 million. There are over 300,000 registered SMEs in the UAE, many of which are looking for cost-effective tools and workshops to improve their operations and customer engagement.
64
+
65
+ ### 3.2 Market Size and Growth Potential
66
+ - The total addressable market for our offerings in the UAE is estimated to be worth د.إ 2 billion, considering demand from both individual consumers and SMEs.
67
+ - Key growth drivers include the rapid digital transformation fueled by government initiatives such as the UAE Vision 2021, and the increasing number of startups and SMEs seeking innovative solutions to stay competitive.
68
+
69
+ ### 3.3 Industry Trends and Market Drivers
70
+ - Rising E-commerce Adoption: Online retail sales in the UAE increased by 23% in 2024, highlighting growing consumer comfort with digital platforms.
71
+ - Government Support for Innovation: The UAE government launched multiple incentive programs in 2023, aimed at fostering entrepreneurship and digital skills development.
72
+ - Increasing Mobile Penetration: Mobile internet usage reached 98% of the population in 2024, enabling easier access to digital services.
73
+ - Demand for Experiential Marketing: Businesses are focusing on interactive customer experiences to stand out, with 65% reporting increased investment in workshops and demos.
74
+
75
+ ### 3.4 Customer Needs and Pain Points
76
+ - Need for Hands-on Experience: Customers in the UAE prefer engaging directly with products or services before committing, making free demonstrations essential.
77
+ - Language and Cultural Relevance: Many consumers seek offerings tailored to Arabic and English speakers, respecting local cultural nuances.
78
+ - Time Efficiency: Busy professionals and SME owners require quick, effective solutions that fit into their schedules without causing disruption.
79
+ - Trust and Reliability Concerns: Given the competitive market, customers often hesitate without clear proof of value and credibility.
80
+
81
+ ### 3.5 Competitive Landscape Overview
82
+ - **Dubai Business Solutions:** Provides digital marketing workshops and consultancy with an estimated 15% market share in the SME segment. Their strong network and tailored content are key strengths. Our business differentiates by offering hands-on demonstrations and more personalized engagement.
83
+ - **Innovate UAE:** Focuses on tech-driven training programs for startups with a market presence primarily in Abu Dhabi. They emphasize cutting-edge technology but lack localized cultural customization, which our business prioritizes.
84
+ - **NextGen Workshops:** Offers a range of professional development sessions across the UAE, known for their comprehensive curriculum but limited free offerings. We stand out by providing no-cost demos that lower the entry barrier for potential clients.
85
+
86
+ ### 3.6 SWOT Analysis
87
+
88
+ #### Strengths
89
+ - Deep understanding of the UAE market and cultural nuances.
90
+ - Ability to offer free, interactive demonstrations that build trust and engagement.
91
+ - Strong potential for partnership with government and private sector initiatives.
92
+
93
+ #### Weaknesses
94
+ - Limited brand recognition as a new entrant in a competitive market.
95
+ - Initial resource constraints may limit geographic reach and marketing efforts.
96
+ - Dependence on in-person workshops may be challenged by shifting preferences toward virtual formats.
97
+
98
+ #### Opportunities
99
+ - Expansion of digital infrastructure and government incentives supporting SMEs.
100
+ - Growing interest in experiential marketing and interactive learning formats.
101
+ - Potential to collaborate with established business hubs and accelerators in the UAE.
102
+
103
+ #### Threats
104
+ - Presence of well-established competitors with loyal customer bases.
105
+ - Economic fluctuations or regulatory changes impacting SME budgets.
106
+ - Currency volatility affecting pricing and operational costs.
107
+
108
+ ## Product or Service
109
+
110
+ ### 4.1 Product or Service Description
111
+ Our offering consists of an innovative solution tailored to meet the dynamic needs of customers in the United Arab Emirates. It integrates advanced technology with user-friendly design to provide a seamless and engaging experience. The service emphasizes convenience, reliability, and customization, which are highly valued by AE consumers. End users will benefit from personalized support and features that reflect local cultural preferences and business practices, ensuring relevance and ease of adoption.
112
+
113
+ ### 4.2 Core Features and Benefits
114
+ - **Feature**: Multilingual interface including Arabic and English – **Benefit**: Ensures accessibility and ease of use across diverse AE demographics.
115
+ - **Feature**: Mobile-first platform optimized for smartphones – **Benefit**: Aligns with the UAE’s high mobile penetration and on-the-go lifestyle.
116
+ - **Feature**: Localized payment options including popular AE digital wallets – **Benefit**: Facilitates smooth transactions preferred by the regional market.
117
+ - **Feature**: Integration with UAE government services – **Benefit**: Streamlines user processes and builds trust through official partnerships.
118
+
119
+ ### 4.3 Unique Selling Proposition (USP)
120
+ Our product uniquely combines advanced technology with deep localization to deliver a service that resonates specifically with UAE consumers.
121
+ - It addresses local language and cultural nuances that many competitors overlook, enhancing user engagement.
122
+ - The solution’s integration with regional payment and government systems meets local regulatory requirements and customer expectations.
123
+
124
+ ### 4.4 Development Stage (MVP, Beta, Market Launch)
125
+ Currently, the product is in the Market Launch phase, with a fully functional platform deployed for early adopters in the UAE. Initial user feedback has been positive, with over 100 active users onboarded in the first month. An investment of د.إ 10,000 has been dedicated to marketing and user acquisition activities to accelerate growth.
126
+
127
+ ### 4.5 Intellectual Property and Innovation
128
+ - Trademark registered in the UAE for brand protection (Registration number pending).
129
+ - Proprietary algorithm for user personalization, currently patent-pending locally.
130
+ - Unique integration framework for UAE government service APIs, developed in-house.
131
+ This innovation ensures a strong competitive advantage by offering exclusive features tailored to the UAE market, fostering customer loyalty and barriers to entry for competitors.
132
+
133
+ ## Business Model
134
+
135
+ ### 5.1 Revenue Streams
136
+ - One-time sales: د.إ 150,000 annually. This stream is ideal for AE customers who prefer upfront purchases for tangible products or services without ongoing commitments.
137
+ - Service contracts: د.إ 100,000 annually. Recurring contracts provide steady income and appeal to businesses seeking reliable, ongoing support in the UAE market.
138
+ - Workshops and demonstrations: د.إ 50,000 annually. Offering free demonstrations helps convert interested prospects into paying customers, driving sales growth in a competitive environment.
139
+
140
+ ### 5.2 Pricing Strategy
141
+ The business will offer two main pricing tiers: Basic at د.إ 1,000 per package and Premium at د.إ 2,500 per package. This tiered approach reflects the purchasing power of a diverse customer base in the UAE, providing options for smaller businesses as well as larger enterprises. Competitor pricing analysis shows these rates are competitive while allowing for premium value-added services.
142
+
143
+ ### 5.3 Sales and Distribution Channels
144
+ - Direct sales: Engaging customers through in-person meetings and consultations, common in the UAE’s relationship-driven business culture.
145
+ - E-commerce marketplace: Utilizing popular UAE platforms supporting digital payments like credit cards and mobile wallets for convenience.
146
+ - Retail partnerships: Collaborating with local retailers to expand reach, leveraging their established distribution networks within UAE cities.
147
+ - Workshops and demonstrations: Hosting events to showcase products, attracting and educating potential clients in key UAE business hubs.
148
+
149
+ ### 5.4 Customer Acquisition Strategy
150
+ - Social media ads: Targeted campaigns on platforms popular in the UAE such as Instagram and LinkedIn, aiming for a Cost Per Acquisition (CPA) of د.إ 100.
151
+ - Referral program: Incentivizing existing customers with rewards to introduce new clients, leveraging strong community connections typical in the UAE.
152
+ - Local events and exhibitions: Participating in UAE trade shows and business forums to build brand awareness and generate leads.
153
+ - Free workshops: Offering no-cost demonstrations to lower entry barriers and convert attendees into paying customers.
154
+
155
+ ### 5.5 Customer Retention and Loyalty Plan
156
+ - Loyalty points: Customers earn points redeemable for discounts or services, encouraging repeat business and customer engagement within the UAE market.
157
+ - Exclusive content: Providing subscribers with access to advanced tutorials and industry insights, fostering a sense of community and value.
158
+ - Premium support: Offering dedicated customer service with quick response times, meeting the high service expectations of UAE clients.
159
+ - Regular follow-ups: Personalized communication to gather feedback and offer tailored solutions, boosting long-term satisfaction and retention.
160
+
161
+ <!--CHART_DATA_START-->
162
+ [["Business Model","DC","Revenue Streams Breakdown","Annual",[["One-time sales",150000],["Service contracts",100000],["Workshops and demonstrations",50000]]],["Business Model","BG","Pricing Tier Comparison","Annual",[["Basic",1000],["Premium",2500]]],["Business Model","DC","Sales Channel Distribution","Annual",[["Direct sales",1],["E-commerce marketplace",1],["Retail partnerships",1],["Workshops and demonstrations",1]]],["Business Model","DC","Customer Acquisition Strategy Metrics","Annual",[["Social media ads",100]]]]
163
+ <!--CHART_DATA_END-->
164
+
165
+ ## Marketing and Growth Strategy
166
+
167
+ ### 6.1 Marketing Strategy Overview
168
+ Our marketing approach focuses on leveraging digital platforms combined with in-person engagement to build strong customer relationships in the UAE market. We plan to allocate a budget of approximately د.إ 50,000 initially, prioritizing online advertising, social media, and free demonstrations to attract and engage our target audience. Messaging will be culturally sensitive, reflecting the UAE’s diverse population and emphasizing respect, trust, and innovation. Localized content in both Arabic and English will be used to maximize reach and relevance.
169
+
170
+ ### 6.2 Brand Positioning
171
+ The business is the most customer-centric provider of high-quality [product/service] in the United Arab Emirates for discerning individuals and organizations seeking reliability and innovation.
172
+
173
+ - The tone is professional yet approachable, highlighting trustworthiness and a commitment to excellence tailored to the UAE’s multicultural environment.
174
+ - Visual style incorporates modern, clean design elements with culturally appropriate colors and motifs that resonate with both local and expatriate communities.
175
+
176
+ ### 6.3 Advertising and Promotion Channels
177
+ - **Google Ads:** Targeted campaigns focused on UAE demographics, expected monthly spend د.إ 15,000, reaching thousands of potential customers.
178
+ - **Social Media Influencers:** Partner with regional influencers to boost brand awareness, estimated cost د.إ 10,000 per campaign with high engagement potential.
179
+ - **Local Radio Spots:** Affordable advertising on popular UAE radio stations, budgeted at د.إ 5,000 monthly, effective for broad reach.
180
+ - **Workshops and Demonstrations:** Hosting free events to showcase products/services, with minimal costs mainly for venue and materials, enhancing direct customer interaction.
181
+
182
+ ### 6.4 Partnerships and Referral Strategies
183
+ - **Local Distributors:** Collaborate with distributors who have established networks, offering د.إ 100 credit per referred customer to incentivize referrals, leveraging their market knowledge.
184
+ - **Industry Associations:** Partner with relevant UAE business groups for co-marketing opportunities and referral incentives, fostering credibility and access to niche markets.
185
+ - **Corporate Clients:** Develop referral programs for existing clients, rewarding them with discounts or credits for each new customer introduced, promoting loyalty and word-of-mouth growth.
186
+
187
+ <!--CHART_DATA_START-->
188
+ []
189
+ <!--CHART_DATA_END-->
190
+
191
+ ## Operations Plan
192
+
193
+ ### 7.1 Operational Workflow Overview
194
+ - Receive customer inquiries and schedule free demonstrations or workshops to showcase products or services, building engagement and trust.
195
+ - Confirm orders and process payments through secure channels, ensuring clarity on product specifications and delivery terms.
196
+ - Coordinate with local and international suppliers to source materials or products, considering typical delivery lead times within the UAE and neighboring regional hubs.
197
+ - Prepare, package, and dispatch orders through reliable logistics partners, aiming for prompt delivery within 3–5 business days across the UAE.
198
+ - Follow up with customers post-delivery to gather feedback and provide after-sales support, strengthening customer relationships and encouraging repeat business.
199
+
200
+ ### 7.2 Facility and Equipment Requirements
201
+ - Office space in Dubai or Abu Dhabi, with approximate monthly rent of د.إ 15,000, serving as the main administrative and customer engagement hub.
202
+ - Warehouse facility near a major logistics hub, renting for around د.إ 25,000 per month, to store inventory and manage dispatch.
203
+ - Computers and office equipment, including laptops and printers, estimated at د.إ 20,000 for initial setup to support daily operations.
204
+ - Workshop or demonstration area equipped with necessary presentation tools, costing approximately د.إ 10,000 to create an interactive customer experience.
205
+
206
+ ### 7.3 Supply Chain and Vendor Management
207
+ - Local suppliers in the UAE for quick replenishment, typically offering 30-day net payment terms and delivery lead times of 2–4 days.
208
+ - International suppliers from regions such as Asia and Europe, with payment terms negotiated around 45-day net, and delivery lead times averaging 10–15 days.
209
+ - Use of regional distribution hubs in the UAE to expedite product flow and reduce shipping delays.
210
+ - Compliance with UAE import regulations, including customs clearance and adherence to product standards set by the Emirates Authority for Standardization and Metrology (ESMA).
211
+
212
+ ### 7.4 Regulatory and Compliance Requirements
213
+ - Business registration with the Department of Economic Development (DED) in the relevant emirate is mandatory to legally operate.
214
+ - Industry-specific permits or approvals may be required depending on the product or service offered, such as health and safety certifications.
215
+ - Ongoing tax obligations include Value Added Tax (VAT) registration and periodic filing with the Federal Tax Authority (FTA).
216
+ - Compliance with UAE labor laws and occupational health and safety standards to ensure a safe and lawful working environment.
217
+
218
+ <!--CHART_DATA_START-->
219
+ [["Operations Plan","DC","Facility Cost Breakdown","Monthly",[["Office Rent",15000],["Warehouse Rent",25000],["Computers and Equipment",20000],["Workshop Setup",10000]]],["Operations Plan","BG","Supplier Payment Terms and Delivery Lead Times","N/A",[["Local Supplier Payment Terms (days)",30],["Local Supplier Delivery Lead Time (days)",4],["International Supplier Payment Terms (days)",45],["International Supplier Delivery Lead Time (days)",15]]]]
220
+ <!--CHART_DATA_END-->
221
+
222
+ ## Management and Team
223
+
224
+ ### 8.1 Core Roles and Functional Responsibilities
225
+ **- Chief Executive Officer (CEO):** Leads the overall strategic direction of the AE business, ensuring compliance with UAE commercial laws and fostering partnerships across the region. Oversees business growth initiatives including free demonstrations and workshops to attract customers.
226
+ **- Chief Operating Officer (COO):** Manages daily operations with a focus on efficiency and adherence to UAE-specific labor and safety regulations. Coordinates between departments to deliver seamless service experiences aligned with local market expectations.
227
+ **- Marketing Manager:** Develops and executes marketing strategies tailored to the UAE market, including organizing interactive workshops and demonstrations to engage potential clients. Ensures culturally relevant messaging and digital presence.
228
+ **- Compliance Officer:** Ensures all activities comply with UAE AE industry regulations and licensing requirements. Monitors ongoing legal changes and implements necessary adjustments to company policies and procedures.
229
+ **- Customer Relations Manager:** Oversees client engagement and retention strategies, including managing feedback from free demonstrations to improve service offerings and customer satisfaction within the UAE context.
230
+
231
+ ### 8.2 Key Hires or Specialized Team Requirements
232
+ **- AE Technical Specialist:** Critical for delivering high-quality demonstrations and workshops, this role requires deep knowledge of AE products and services tailored to the UAE market.
233
+ **- Local Legal Advisor:** Essential to navigate UAE-specific regulatory frameworks and ensure all business practices meet local compliance standards.
234
+ **- Bilingual Customer Support Representative:** Provides support in both Arabic and English, enhancing communication and customer experience in the culturally diverse UAE environment.
235
+ **- Digital Marketing Expert:** Focused on leveraging UAE digital platforms and social media channels to maximize workshop attendance and brand awareness.
236
+
237
+ ### 8.3 Advisory Board and Strategic Mentors
238
+ **- Industry Expert (Regional AE Markets):** Provides insights on regional market trends and competitive landscape to position the business effectively within the UAE.
239
+ **- Legal and Compliance Consultant:** Advises on evolving UAE regulations affecting AE operations, helping to mitigate risks and maintain adherence to local laws.
240
+ **- Business Development Mentor:** Supports strategic partnerships and growth opportunities in the UAE, especially around customer engagement initiatives such as free workshops.
241
+
242
+ ### 8.4 Organizational Structure and Reporting Lines
243
+ - **CEO** -> Board of Directors -> Oversees all company operations and strategic growth
244
+ - **COO** -> CEO -> Manages daily operations and ensures regulatory compliance
245
+ - **Marketing Manager** -> COO -> Develops and implements marketing campaigns and customer engagement events
246
+ - **Compliance Officer** -> COO -> Monitors regulatory adherence and manages legal risk
247
+ - **Customer Relations Manager** -> COO -> Handles client communication and feedback from demonstrations and workshops
248
+
249
+ ## Financial Plan and Funding
250
+
251
+ ### 9.1 Startup and Operating Costs
252
+
253
+ - **Startup Costs:**
254
+ - Equipment and software licenses estimated at د.إ 100,000 to ensure the business is fully operational with up-to-date technology.
255
+ - Business registration and licensing fees approximately د.إ 15,000 to comply with UAE regulations.
256
+ - Initial marketing campaigns including free workshops setup costing around د.إ 30,000 to attract early customers.
257
+ - Office setup and furnishing expected to be د.إ 25,000 for a professional environment.
258
+
259
+ - **Operating Costs (Monthly or Annual):**
260
+ - Monthly office rent approximately د.إ 20,000 in a prime location within the UAE.
261
+ - Staff salaries estimated at د.إ 60,000 monthly to attract skilled professionals.
262
+ - Utilities, internet, and maintenance estimated at د.إ 5,000 per month.
263
+ - Marketing and promotional activities budgeted at د.إ 15,000 monthly to sustain customer engagement.
264
+
265
+ ### 9.2 Revenue Forecast and Growth Projections (1–3 Years)
266
+
267
+ - **Year 1 Projected Revenue:** د.إ 1,200,000, based on initial client acquisition through free demonstrations and workshops converting to paid services.
268
+ - **Year 2 Projected Revenue:** د.إ 1,800,000, assuming a 50% increase due to expanding brand presence and customer base.
269
+ - **Year 3 Projected Revenue:** د.إ 2,700,000, reflecting a 50% growth supported by market expansion within the UAE and introduction of new service offerings.
270
+
271
+ ### 9.3 Break-even Analysis (Optional)
272
+
273
+ The business is expected to break even by Month 15 with a required revenue of approximately د.إ 1,000,000. This projection assumes fixed costs such as rent and salaries remain constant, while variable costs scale with sales. The average sale price per service, combined with steady client growth, supports reaching profitability within this timeframe.
274
+
275
+ ### 9.4 Funding Requirements and Use of Funds
276
+
277
+ A total funding requirement of د.إ 250,000 is needed to cover startup costs and initial operating expenses until the business reaches cash flow positivity. These funds will be allocated strategically to ensure smooth launch and early growth phases.
278
+
279
+ - د.إ 100,000 for equipment and software procurement.
280
+ - د.إ 50,000 dedicated to marketing efforts, including free demonstrations and digital campaigns.
281
+ - د.إ 70,000 allocated for staffing and training to build a competent team.
282
+ - د.إ 30,000 reserved as working capital for operational expenses during the first six months.
283
+
284
+ ### 9.5 Financial Milestones and Investor ROI Expectations
285
+
286
+ - Reach د.إ 1,200,000 in revenue by the end of Year 1; projected ROI: 15% by Year 3.
287
+ - Achieve profitability by Month 15, reducing operating losses; projected ROI: 25% by Year 3.
288
+ - Expand customer base to over 500 clients by Year 2; projected ROI: 40% by Year 4.
289
+ - Increase revenue to د.إ 2,700,000 by Year 3 through market expansion; projected ROI: 60% by Year 5.
290
+
291
+ <!--CHART_DATA_START-->
292
+ [["Financial Plan and Funding","LC","Projected Revenue Over Time","Annual",[["Year 1",1200000],["Year 2",1800000],["Year 3",2700000]]],["Financial Plan and Funding","DC","Startup Cost Breakdown","Annual",[["Equipment and software licenses",100000],["Marketing and digital campaigns",30000],["Business registration and licensing",15000],["Office setup and furnishing",25000]]],["Financial Plan and Funding","DC","Operating Cost Breakdown","Monthly",[["Rent",20000],["Salaries",60000],["Utilities and maintenance",5000],["Marketing and promotions",15000]]],["Financial Plan and Funding","DC","Funding Allocation","Annual",[["Equipment and software procurement",100000],["Marketing efforts",50000],["Staffing and training",70000],["Working capital",30000]]]]
293
+ <!--CHART_DATA_END-->
maintest.txt CHANGED
@@ -1776,8 +1776,7 @@ def create_pdf_document(request: ExportRequest):
1776
  # content_text = enhance_subheadings_with_bold(content_text)
1777
  content_text = remove_duplicate_headings(content_text)
1778
 
1779
- # Make text before colons bold
1780
- content_text = make_sentences_ending_with_colon_bold(content_text)
1781
 
1782
  # Add content with proper markdown rendering using grouped approach
1783
  if content_text and content_text.strip():
@@ -2216,8 +2215,7 @@ def create_word_document(request: ExportRequest):
2216
  filtered_lines.append(line)
2217
  clean_content = '\n'.join(filtered_lines)
2218
 
2219
- # Make text before colons bold
2220
- clean_content = make_sentences_ending_with_colon_bold(clean_content)
2221
 
2222
  # Render markdown content with proper heading styling using grouped approach
2223
  render_markdown_to_docx_grouped(doc, clean_content)
@@ -3064,41 +3062,7 @@ def filter_empty_sections(sections: List[ExportSection]) -> List[ExportSection]:
3064
  # logging.info(f"Filtered sections: {len(filtered_sections)} out of {len(sections)} total")
3065
  return filtered_sections
3066
 
3067
- def enhance_subheadings_with_bold(content: str) -> str:
3068
- """Enhance subheadings with bold formatting and ensure no duplicates"""
3069
- if not content:
3070
- return content
3071
-
3072
- lines = content.split('\n')
3073
- enhanced_lines = []
3074
- seen_headings = set()
3075
-
3076
- for line in lines:
3077
- line = line.strip()
3078
- if not line:
3079
- enhanced_lines.append('')
3080
- continue
3081
-
3082
- # Check if this is a subheading (## or ###)
3083
- if line.startswith('##') and not line.startswith('###'):
3084
- # Extract the heading text
3085
- heading_text = re.sub(r'^##+\s*', '', line)
3086
- # heading_text = re.sub(r'[*_`~]', '', heading_text).strip() # Commented out to preserve ** symbols
3087
- heading_text = heading_text.strip()
3088
-
3089
- # Check for duplicates
3090
- if heading_text.lower() in seen_headings:
3091
- continue
3092
-
3093
- seen_headings.add(heading_text.lower())
3094
-
3095
- # Make it bold and ensure proper formatting
3096
- enhanced_line = f"**{heading_text}**"
3097
- enhanced_lines.append(enhanced_line)
3098
- else:
3099
- enhanced_lines.append(line)
3100
-
3101
- return '\n'.join(enhanced_lines)
3102
 
3103
  def remove_duplicate_headings(content: str) -> str:
3104
  """Remove duplicate headings from content"""
@@ -3325,7 +3289,7 @@ def should_break_page_for_group(pdf, group: Dict[str, Any], current_y: int, page
3325
  estimated_height = calculate_group_height(pdf, group)
3326
 
3327
  # If the group is very large (more than half a page), always break
3328
- if estimated_height > page_height * 0.7:
3329
  return True
3330
 
3331
  # If the group won't fit on current page, break
@@ -3338,28 +3302,7 @@ def should_break_page_for_group(pdf, group: Dict[str, Any], current_y: int, page
3338
 
3339
  return False
3340
 
3341
- def _render_mixed_text_to_pdf(pdf, line: str, current_x: float, current_y: float, line_height: float, text_color: tuple, bold_font_size: int = 12, normal_font_size: int = 12):
3342
- """Helper to render a line with mixed bold and normal text using pdf.cell"""
3343
- parts = re.split(r'(\*\*.*?\*\*)', line)
3344
-
3345
- for part in parts:
3346
- if part.startswith('**') and part.endswith('**'):
3347
- bold_text = part[2:-2] # Remove ** markers
3348
- pdf.set_font("Arial", "B", bold_font_size)
3349
- pdf.set_text_color(*text_color)
3350
- pdf.set_xy(current_x, current_y)
3351
- text_width = pdf.get_string_width(bold_text)
3352
- pdf.cell(text_width, line_height, bold_text)
3353
- current_x += text_width
3354
- else:
3355
- if part:
3356
- pdf.set_font("Arial", "", normal_font_size)
3357
- pdf.set_text_color(*text_color)
3358
- pdf.set_xy(current_x, current_y)
3359
- text_width = pdf.get_string_width(part)
3360
- pdf.cell(text_width, line_height, part)
3361
- current_x += text_width
3362
- return current_x
3363
 
3364
  def render_markdown_to_pdf_grouped(pdf, content: str, primary_color, accent_color, text_color):
3365
  """Render markdown content to PDF with subheading-content grouping and smart page breaks"""
@@ -3455,18 +3398,19 @@ def render_markdown_to_pdf_grouped(pdf, content: str, primary_color, accent_colo
3455
 
3456
  if not re.match(r'^\d+\.', text) and len(text) < 80:
3457
  # Main heading style
 
 
3458
  pdf.set_xy(25, current_y)
3459
- _render_mixed_text_to_pdf(pdf, text, 25, current_y, line_height_heading, primary_color, bold_font_size=12, normal_font_size=12)
3460
- current_y += line_height_heading
3461
- pdf.set_xy(25, current_y)
3462
  pdf.ln(6)
3463
  current_y = pdf.get_y()
3464
  else:
3465
  # Regular bold text
 
 
3466
  pdf.set_xy(25, current_y)
3467
- _render_mixed_text_to_pdf(pdf, text, 25, current_y, line_height_text, text_color, bold_font_size=12, normal_font_size=12)
3468
- current_y += line_height_text
3469
- pdf.set_xy(25, current_y)
3470
  current_y = pdf.get_y()
3471
 
3472
  elif subheading_type == 'numbered':
@@ -3491,19 +3435,12 @@ def render_markdown_to_pdf_grouped(pdf, content: str, primary_color, accent_colo
3491
  content_lines = group_content.split('\n')
3492
  for line in content_lines:
3493
  if line.strip():
3494
- # Check if line contains bold text and render accordingly
3495
- if '**' in line:
3496
- line_height = 8
3497
- _render_mixed_text_to_pdf(pdf, line, 25, current_y, line_height, text_color, bold_font_size=12, normal_font_size=12)
3498
- current_y += line_height
3499
- pdf.set_xy(25, current_y)
3500
- else:
3501
- # No bold text - render normally
3502
- pdf.set_font("Arial", "", 12)
3503
- pdf.set_text_color(*text_color)
3504
- pdf.set_xy(25, current_y)
3505
- pdf.multi_cell(160, 8, line)
3506
- current_y = pdf.get_y()
3507
  else:
3508
  # Empty line spacing (original)
3509
  pdf.ln(3)
@@ -4119,10 +4056,10 @@ def render_markdown_to_docx_grouped(doc, content: str):
4119
  doc.add_heading(text, level=4)
4120
  elif subheading_type == 'bold':
4121
  if not re.match(r'^\d+\.', text) and len(text) < 80:
4122
- paragraph = process_bold_text_for_docx(text, doc)
4123
  paragraph.style = doc.styles['Heading 1'] # Apply heading style
4124
  else:
4125
- process_bold_text_for_docx(text, doc) # Use helper for regular paragraphs
4126
  elif subheading_type == 'numbered':
4127
  doc.add_heading(text, level=2)
4128
 
@@ -4131,32 +4068,14 @@ def render_markdown_to_docx_grouped(doc, content: str):
4131
  content_lines = group_content.split('\n')
4132
  for line in content_lines:
4133
  if line.strip():
4134
- # Process bold text markers for Word documents
4135
- process_bold_text_for_docx(line, doc)
4136
  else:
4137
  doc.add_paragraph() # Empty paragraph for spacing (original logic)
4138
 
4139
  # Removed process_bold_text_in_content function - now handled inline with proper bold rendering
4140
 
4141
- def process_bold_text_for_docx(text: str, doc):
4142
- """Process bold text markers (**text**) in content for Word documents"""
4143
- # For Word documents, we can actually render bold text properly
4144
- # Split text by ** markers and create runs with appropriate formatting
4145
- parts = re.split(r'(\*\*.*?\*\*)', text)
4146
- paragraph = doc.add_paragraph()
4147
-
4148
- for part in parts:
4149
- if part.startswith('**') and part.endswith('**'):
4150
- # This is bold text
4151
- bold_text = part # Keep ** markers
4152
- run = paragraph.add_run(bold_text)
4153
- run.bold = True
4154
- else:
4155
- # Regular text
4156
- if part: # Only add non-empty parts
4157
- paragraph.add_run(part)
4158
-
4159
- return paragraph
4160
 
4161
  def clean_text_for_docx(text: str) -> str:
4162
  # Replace problematic Unicode characters with ASCII equivalents
@@ -4184,33 +4103,3 @@ def clean_text_for_docx(text: str) -> str:
4184
 
4185
  return text
4186
 
4187
- def make_sentences_ending_with_colon_bold(content: str) -> str:
4188
- """
4189
- Make text before a colon (:) bold by wrapping it in ** markers.
4190
- This handles cases like "Short-Term (next 12 months):" to make only the part before the colon bold.
4191
- """
4192
- if not content:
4193
- return content
4194
-
4195
- lines = content.split('\n')
4196
- processed_lines = []
4197
-
4198
- for line in lines:
4199
- if not line.strip():
4200
- processed_lines.append(line)
4201
- continue
4202
-
4203
- last_colon_index = line.rfind(':')
4204
-
4205
- if last_colon_index != -1:
4206
- text_before_colon = line[:last_colon_index].strip()
4207
- text_after_colon = line[last_colon_index:].strip()
4208
-
4209
- if not (text_before_colon.startswith('**') and text_before_colon.endswith('**')):
4210
- processed_lines.append(f"**{text_before_colon}**{text_after_colon}")
4211
- else:
4212
- processed_lines.append(line)
4213
- else:
4214
- processed_lines.append(line)
4215
-
4216
- return '\n'.join(processed_lines)
 
1776
  # content_text = enhance_subheadings_with_bold(content_text)
1777
  content_text = remove_duplicate_headings(content_text)
1778
 
1779
+
 
1780
 
1781
  # Add content with proper markdown rendering using grouped approach
1782
  if content_text and content_text.strip():
 
2215
  filtered_lines.append(line)
2216
  clean_content = '\n'.join(filtered_lines)
2217
 
2218
+
 
2219
 
2220
  # Render markdown content with proper heading styling using grouped approach
2221
  render_markdown_to_docx_grouped(doc, clean_content)
 
3062
  # logging.info(f"Filtered sections: {len(filtered_sections)} out of {len(sections)} total")
3063
  return filtered_sections
3064
 
3065
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3066
 
3067
  def remove_duplicate_headings(content: str) -> str:
3068
  """Remove duplicate headings from content"""
 
3289
  estimated_height = calculate_group_height(pdf, group)
3290
 
3291
  # If the group is very large (more than half a page), always break
3292
+ if estimated_height > page_height * 0.5:
3293
  return True
3294
 
3295
  # If the group won't fit on current page, break
 
3302
 
3303
  return False
3304
 
3305
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3306
 
3307
  def render_markdown_to_pdf_grouped(pdf, content: str, primary_color, accent_color, text_color):
3308
  """Render markdown content to PDF with subheading-content grouping and smart page breaks"""
 
3398
 
3399
  if not re.match(r'^\d+\.', text) and len(text) < 80:
3400
  # Main heading style
3401
+ pdf.set_font("Arial", "B", 18)
3402
+ pdf.set_text_color(*primary_color)
3403
  pdf.set_xy(25, current_y)
3404
+ pdf.multi_cell(160, line_height_heading, text)
3405
+ current_y = pdf.get_y()
 
3406
  pdf.ln(6)
3407
  current_y = pdf.get_y()
3408
  else:
3409
  # Regular bold text
3410
+ pdf.set_font("Arial", "B", 12)
3411
+ pdf.set_text_color(*text_color)
3412
  pdf.set_xy(25, current_y)
3413
+ pdf.multi_cell(160, line_height_text, text)
 
 
3414
  current_y = pdf.get_y()
3415
 
3416
  elif subheading_type == 'numbered':
 
3435
  content_lines = group_content.split('\n')
3436
  for line in content_lines:
3437
  if line.strip():
3438
+ # Render text normally (removed mixed text support)
3439
+ pdf.set_font("Arial", "", 12)
3440
+ pdf.set_text_color(*text_color)
3441
+ pdf.set_xy(25, current_y)
3442
+ pdf.multi_cell(160, 8, line)
3443
+ current_y = pdf.get_y()
 
 
 
 
 
 
 
3444
  else:
3445
  # Empty line spacing (original)
3446
  pdf.ln(3)
 
4056
  doc.add_heading(text, level=4)
4057
  elif subheading_type == 'bold':
4058
  if not re.match(r'^\d+\.', text) and len(text) < 80:
4059
+ paragraph = doc.add_paragraph(text)
4060
  paragraph.style = doc.styles['Heading 1'] # Apply heading style
4061
  else:
4062
+ doc.add_paragraph(text) # Use simple paragraph
4063
  elif subheading_type == 'numbered':
4064
  doc.add_heading(text, level=2)
4065
 
 
4068
  content_lines = group_content.split('\n')
4069
  for line in content_lines:
4070
  if line.strip():
4071
+ # Simple text rendering (removed bold processing)
4072
+ doc.add_paragraph(line)
4073
  else:
4074
  doc.add_paragraph() # Empty paragraph for spacing (original logic)
4075
 
4076
  # Removed process_bold_text_in_content function - now handled inline with proper bold rendering
4077
 
4078
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4079
 
4080
  def clean_text_for_docx(text: str) -> str:
4081
  # Replace problematic Unicode characters with ASCII equivalents
 
4103
 
4104
  return text
4105